# Read-only Health Dashboard API Explorer: implementation and release discipline

Use when extending a sensitive local health dashboard with a browser-side chart/explorer backed by a read-only same-origin API.

## Contract-first build order

1. Add synthetic RED tests for every field the explorer needs before changing UI code:
   - server-authoritative local `today` for open ranges;
   - per-point rolling baseline that uses strictly prior observations only;
   - ISO-week `week_start`, `week_end`, and a deterministic `drilldown_date`;
   - laboratory reference metadata per observation, with an explicit missing-reference state only where the explorer needs it.
2. Keep endpoint disclosure scopes separate. `/labs` may remain strict (only usable verified references), while `/series` can expose an explicit `missing_reference` marker for a selected observation. Do not loosen the broad lab endpoint to satisfy a chart.
3. Make additive API fields explicit in legacy exact-object tests. Update affected expected shapes intentionally; never hide new contract fields by weakening assertions.

## Browser session boundary

- A browser must never need an API Bearer token or Basic secret.
- Render a single-use server-registered CSRF bootstrap value into the V5 HTML, pair it with an HttpOnly SameSite cookie, and require both plus exact same-origin checks for the browser-session POST.
- Issue only a short-lived server-side API session (`HttpOnly`, `SameSite=Strict`, `Path=/api/v1/`).
- Keep V4 CSP at `connect-src 'none'`; V5 alone may use `connect-src 'self'`.
- Tests must assert no Bearer/Basic/session identifier appears in HTML, JS, URL, storage, cookie values, or logs.

## Explorer minimum scope

- Add the new client as a separate local asset. Do not replace the existing Chart.js/static fallback while validating the new path.
- Use only same-origin `fetch(..., {credentials: 'same-origin'})`; no remote CDN or runtime fetch.
- Cap raw comparison to two metrics with the same unit until a reviewed compatibility/dual-axis policy exists.
- Preserve gaps (`connectNulls: false`); do not interpolate missing calendar days.
- Provide an accessible table/text fallback sharing the exact ISO-day selection behavior of the chart point callback.
- Render reference bands only from observation-provided reference values. Absence means unknown, never a fabricated normal range.

## Synthetic test isolation

- Server-loading fixtures must explicitly control `HEALTH_DASHBOARD_TEST_INSTANCE_ID` and action-inbox environment variables. A stale parent-process value can accidentally activate synthetic-only startup guards in unrelated tests.
- Do not relax the production fail-closed guard to accommodate a leaking fixture; reset the test environment instead.
- Run focused API, server-session, renderer and JS syntax checks during build. Run full Python and Playwright suites only after the candidate is frozen.

## Release gate

Before commit/push/deploy: freeze the tree, run independent spec and quality review, prove V4 surface unchanged, run controlled synthetic browser evidence against the candidate server, verify local-only assets/no credential leakage, create versioned aggregate evidence, then deploy and validate route/CSP/auth/redaction live without revealing sensitive data.
