## Audit outcome **Important — correction chains are double-counted outside the medication audit history.** A synthetic 3-row chain (`administered → corrected/missed → corrected/administered`) produced: - `/day`: three raw entries across three dates; the superseded origin remains administered. - `/calendar`: medication count `1` on all three dates. - `/events` and doctor-report `timeline`: three events. - Explorer: stale origin is grouped as **Medikamente**, while correction events fall into **Sonstige** because `eventGroup()` recognizes only `medication_administered`, not `type=medication`. - Medication history/doctor medication section correctly retains all three audit rows and marks: - origin `superseded_by_correction=true` - first correction `is_latest_effective=false` - terminal correction `is_latest_effective=true` ### Exact code risks - `read_api.py:992-1042` — `_events()` queries raw rows; no correction supersession. - `read_api.py:1360-1404` — `_day_medications()` queries raw rows and has no chain projection. - `read_api.py:2698-2712` — calendar counts raw row IDs, including every correction revision. - `read_api.py:3937-3959` — record overview’s “latest administered” can select a superseded origin and ignores an effective administered correction because it remains in the `corrected` bucket. - `read_api.py:4301` — doctor timeline inherits raw `_events()` duplication. - `dashboard-v5-api-explorer.js:252-262` — corrections are misclassified as `other`; stale administered origins remain medication markers. - `dashboard-v5-record.js:961` — report chart markers use every raw `administered` item, including superseded origins, and omit terminal corrections whose effective status is administered. - Doctor medication history itself is audit-correct, but its generic documented-row count at `read_api.py:4427-4430` counts all versions; it must not be interpreted as effective administration count. **Important — day projection drops structured medication semantics.** `_day_medications()` selects only legacy `dose` and `route`. A structured row containing: - `actual_quantity_value="1"` - `actual_dosage_form="Spritze"` - `actual_strength="40 mg"` - `route_original="subkutan"` - `route_normalized="subcutaneous"` - `injection_side="right"` was returned by `/day` with empty `dose` and empty `route`. The current passing F1 test hides this because the worker also populates compatibility fields. **Moderate — displayed enums are not localized in history details.** `dashboard-v5-record.js:885` renders raw values: - `item.status` → `administered` - `item.route_normalized` → `subcutaneous` - `item.injection_side` → `right` The select controls are localized correctly (`Subkutan`, `Rechts`), but read-only details are not. **Moderate — `route_original` fallback is only partially safe.** `read_api.py:3641` performs fallback before validation: ```python safe_metadata_text(row["route_original"] or row["route"], ...) ``` If `route_original` is non-empty but rejected as unsafe while legacy `route` is valid, the valid fallback is lost. Sanitize independently, then fallback: ```python safe(route_original) or safe(route) ``` ### Minimal implementation shape Add one shared medication chain projection in `medication_contract.py`: - annotate every row with `chain_origin_id`, `superseded_by_correction`, `is_latest_effective`; - retain all rows for `/medications` and doctor audit history; - expose terminal effective rows/statuses separately; - make day, calendar, events/timeline, record-summary KPIs, and report chart markers consume only terminal effective rows. Keep correction-record date versus origin-event date an explicit contract decision; do not derive it differently per endpoint. Add shared renderer maps for status, route, and side enums, used by history details and report rendering. ### Minimal regression tests 1. **Single synthetic three-row chain** - `/medications` and doctor medication history retain all 3 rows with exactly one `is_latest_effective`. - Effective day/calendar/events/timeline surfaces count exactly 1 semantic event, not 3. - Effective status is `administered`. - Record-summary “latest administered” and report marker use the terminal correction, never the superseded origin. 2. **Structured projection** - Insert a structured event without compatibility `dose`/`route`. - Assert `/day` renders `1 Spritze · 40 mg`, with route fallback/localization. 3. **Renderer localization** - Browser assertion that details contain `Subkutan` and `Rechts`. - Assert raw `subcutaneous` and `right` are absent from visible detail text. 4. **Fallback counterexample** - Unsafe/non-displayable `route_original` plus valid legacy `route="subkutan"`. - Assert API returns the valid legacy fallback without exposing the rejected value. ### Verification - Existing focused suite: **21 passed** `pytest -q -p no:cacheprovider tests/test_dashboard_v5_sprint7c_f.py tests/test_dashboard_v5_sprint7c_f1.py` - Repository remained clean at `a730ca4f0f3cf12c74dbb3e1c512ad1978c96fe3`. - **Files modified:** none.