# Health Sanitizer Mapping

The Health sanitizer is allowlist-first. It builds a `ModuleSnapshot` only from safe metadata produced by `health_probe.py` or synthetic tests.

## Used safe fields

- `runtime_exists` -> source reachability category
- `reachable` -> source health reachable flag
- `pipeline_seen` -> pipeline status category
- `pipeline_stale` -> stale flag and attention item
- `report_fresh` -> freshness category only
- `review_count` -> bounded count only
- `last_success_at` or safe metadata timestamp -> source health timestamps

## Ignored fields

All unknown fields are ignored. Dynamic keys are never promoted into KPI labels or UI text.

## Blocked health classes

The sanitizer blocks diagnosis-like, lab-like, medication-like, clinician-report-like, OCR/PDF-like, patient/symptom/tracker-like, Drive/path/database-like and secret-like fields. Dedicated dirty fixtures prove these strings do not reach API output.

## Error handling

Probe errors become degraded snapshots. Error text is redacted before it can enter `SourceHealth.last_error_redacted` or overview errors.

## Phase 6B inventory mapping rules

### Allowed input metadata

Synthetic or probe-produced metadata may include only:

```json
{
  "pipeline_freshness": "fresh",
  "review_count": 2,
  "backup_freshness": "unknown"
}
```

Equivalent internal probe fields may include boolean reachability, bounded counts, mtime-derived freshness, and coarse success/failure categories.

### Forbidden input content

The sanitizer must reject or ignore any input resembling source content. Synthetic forbidden examples:

```json
{
  "lab_value": "BLOCKED",
  "diagnosis": "BLOCKED",
  "pdf_text": "BLOCKED"
}
```

Also blocked: medication names, clinician report text, OCR text, tracker rows, database rows, source links, local paths, filenames, Drive identifiers, raw logs, and raw error traces.

### Sanitizer output

Output remains limited to the existing `ModuleSnapshot` fields with at most three KPIs, safe attention items, a link-only `/health` primary action, and redacted `SourceHealth`.

### Redaction rules

- Unknown fields are ignored.
- Dynamic keys never become labels.
- Error messages are redacted before output.
- Filenames and paths are not counted as displayable values.
- Counts are bounded and never accompanied by item details.

## Phase 6C safe marker sanitizer mapping

For `safe_marker`, unknown fields are rejected before mapping instead of ignored. Only the strict marker fields are allowed. The adapter maps:
- `pipeline_freshness` -> `Pipeline Freshness` KPI and stale attention when not `fresh`.
- `backup_freshness` -> `Backup Freshness` KPI and source stale state when not `fresh`.
- `review_count` -> `Review Count` KPI and review attention when greater than zero.
- `source_reachable` -> `source_health.reachable` and offline attention when not `yes`.
- `last_success_at` -> safe timestamp only.

Any validation/redaction failure becomes a degraded/offline snapshot with redacted error category only.
