| FM-CHART-01 | PostgreSQL primary unavailable | Chart reads and writes fail; clinicians cannot access or record data | Health probe fails; patient_chart_db_connection_errors_total metric fires | Retry up to 3x (transient); pod fails readiness probe; Kubernetes routes traffic to healthy replicas; DR failover triggered by SRE if sustained > 5 min |
| FM-CHART-02 | NATS JetStream unavailable | Domain events not published; outbox rows accumulate; no downstream fan-out | patient_chart_outbox_lag metric > threshold; NATS health check fails | Outbox relay continues to retry; events delivered once NATS recovers; at-least-once guarantee maintained; no data loss |
| FM-CHART-03 | terminology-service unavailable | Coded value rendering fails; problem/allergy add with auto-code fails | HTTP circuit breaker opens; 503 returned to caller | Fail-open for free-text entry: allow record with codingPending=true flag; alert SRE; terminology retry on next edit |
| FM-CHART-04 | ai-gateway-service unavailable | AI-assist for clinical notes unavailable | HTTP 503 from ai-gateway; circuit breaker opens | Graceful degradation: note authoring continues manually; AI assist button grayed out; alert fires |
| FM-CHART-05 | registration-service unavailable | Patient exists check fails; encounter context unavailable | HTTP circuit breaker opens | Fail-open for existing chart reads (patient ID already known); new chart open with cached patient data; alert fires |
| FM-CHART-06 | Allergy advisory sync call fails (orders-service / medication-service) | Advisory check may be skipped at order entry | HTTP 503; circuit breaker | Callers (orders, medication) implement fail-open per contract; chart does not block; alert logged |
| FM-CHART-07 | Document-service unavailable | Signed note PDF upload fails; note stays in signed state without DocumentReference | HTTP circuit breaker | Note signing completes; PDF upload retried via outbox; DocumentReference written once doc-service recovers |
| FM-CHART-08 | Optimistic lock conflict on ClinicalNote | Concurrent editor receives 409 CHART_INVALID_VERSION | HTTP 409 returned | Client must re-fetch and reapply changes; UX shows "note was updated by another user"; non-destructive |
| FM-CHART-09 | Break-glass invocation without reason | Chart access blocked | CHART_BREAKGLASS_REASON_MISSING 422 | Enforced in domain layer; no workaround; SRE cannot override |
| FM-CHART-10 | NATS duplicate event delivery (at-least-once) | Duplicate audit entries or double allergy events | source_event_id UNIQUE index in consumers | Inbox deduplication on eventId; idempotent handlers; harmless duplicate ACK |
| FM-CHART-11 | Note signed without cosign when policy requires | Signing blocked; CHART_NOTE_COSIGN_REQUIRED returned | 422 from SignNote use case | Domain invariant enforced; note moves to pending_cosign; cosign request emitted |
| FM-CHART-12 | Vitals range validation hard-stop fires | Recording blocked | CHART_VITALS_RANGE_REJECTED 422 | Configurable warn vs reject policy per facility; warn path records with flag |
| FM-CHART-13 | Memory pressure / pod OOM | Service restarts; in-flight requests lost | Kubernetes OOM kill event; alert | Stateless pod restarts quickly; in-flight HTTP returns 503 to caller (client retries); outbox ensures event safety |
| FM-CHART-14 | Data migration error during five-module consolidation | Orphaned records in legacy schema | Migration job exit code ≠ 0; CI gate | Migration is idempotent; run in dry-run mode first; rollback script restores legacy schema from snapshot |
| FM-CHART-15 | RLS misconfiguration: tenant data leak | Cross-tenant chart data visible | RLS integration test fails in CI | Mandatory tenant-isolation.spec.ts must pass before deploy; RLS policy version-controlled |