# Health Safe Status Marker Contract

Phase 6C defines a safe metadata-only bridge from HealthManager to the JARVIS Dashboard. It is not a Health content integration.

## Purpose

HealthManager may later produce one small JSON marker that JARVIS can read in `HEALTH_ADAPTER_MODE=safe_marker`. JARVIS validates the marker strictly, sanitizes it, and maps it to the existing Health `ModuleSnapshot`.

## Allowed marker fields only

```json
{
  "schema_version": "1.0",
  "generated_at": "2026-01-01T00:00:00Z",
  "source": "healthmanager_safe_status",
  "pipeline_freshness": "fresh",
  "backup_freshness": "fresh",
  "review_count": 0,
  "source_reachable": "yes",
  "last_success_at": "2026-01-01T00:00:00Z",
  "status": "ok",
  "notes_category": "none"
}
```

`last_success_at` may be `null`. `review_count` is bounded to `0..99`. All other value-bearing fields are strict enums.

## Schema

Canonical schema: `schemas/health-safe-status-marker.schema.json`.

Rules:
- `additionalProperties: false` — unknown fields are rejected.
- No dynamic keys.
- No nested raw objects or arrays.
- No freetext fields.
- No URLs, paths, filenames, Drive IDs, document titles, patient details, or medical content.

## Forbidden content

The marker must never contain laboratory values, diagnoses, medications, reports, PDFs, OCR output, symptoms, tracker/YAZIO/Apple Health raw data, DB rows, JSON/CSV Health data, Drive links/IDs, local paths, filenames, patient details, report contents, or document titles.

## Adapter behavior

Runtime env:
- `HEALTH_ADAPTER_MODE=safe_marker`
- `HEALTH_SAFE_STATUS_MARKER_PATH=` must be set for this mode.
- `HEALTH_SAFE_STATUS_MAX_AGE_HOURS=72` by default.

Fail-closed rules:
- Missing marker path -> offline/degraded safe Health snapshot.
- Missing/unreadable marker -> degraded safe Health snapshot.
- Broken JSON -> degraded safe Health snapshot.
- Schema failure, unknown fields, nested values, unsafe terms, path leaks -> degraded safe Health snapshot.
- `/api/overview` must not crash.
- The marker path and filename must never appear in API output.

## Marker to ModuleSnapshot mapping

JARVIS emits only:
- `module_id=health`
- `status` from marker, except stale/unsafe marker can downgrade to `degraded/offline`
- KPIs, maximum three:
  - `Pipeline Freshness`
  - `Backup Freshness`
  - `Review Count`
- `source_health`:
  - `reachable`
  - `stale`
  - `source_type=safe_marker`
  - `contract_version=health.safe_status_marker.v1`
  - `last_success_at`
  - `last_attempt_at`
  - `last_error_redacted`
- attention items, enum-derived only:
  - `Health Source offline`
  - `Health Pipeline stale`
  - `Health Review required`
- `primary_action.href=/health`
- `primary_action.mode=link_only`

Not emitted: marker path, marker filename, Health runtime path, medical source data, document metadata, Health detail UI, tables, charts, report links, or generated Health reports.

## Synthetic fixtures and tests

Synthetic fixtures live in `apps/api-gateway/tests/fixtures/health_safe_marker/`. Tests live in:
- `apps/api-gateway/tests/test_health_safe_marker_schema.py`
- `apps/api-gateway/tests/test_health_safe_marker_adapter.py`
- `apps/api-gateway/tests/test_health_safe_marker_redaction.py`
- `apps/api-gateway/tests/test_health_safe_marker_overview_resilience.py`

Optional smoke: `make smoke-health-safe-marker`.
