Architecture
System Overview
Owner: Platform EngineeringLast reviewed:
System context
Service responsibilities
| Service | Responsibility | Owns data | Must never |
|---|---|---|---|
core-api | All domain REST APIs, authorization, tenancy, audit, event publication | PostgreSQL schema | Call OpenAI; render PDFs inline |
realtime-gateway | Authenticated WebSocket fan-out of NATS events (recording, transcription, jobs, island state) | Nothing durable | Persist PHI; accept writes other than presence/acks |
ai-gateway | Prompt registry, model routing, privacy gate, de-identification, structured outputs, validation, cost accounting | ai_* metadata via core-api callbacks | Be reachable from browsers; log payloads |
worker | Durable async jobs: transcription assembly, generation, rendering, delivery, retention | Job state in PostgreSQL | Skip idempotency keys |
document-service | HTML template → Gotenberg PDF/Office rendering | Rendered assets in MinIO | Fetch arbitrary URLs (SSRF-guarded) |
integration-service | Vendor adapter execution, webhook verification, reconciliation | integration_* tables via core-api | Store vendor credentials outside OpenBao |
clinic-web, patient-portal, and platform-admin are BFF-style Next.js apps:
session cookie (HttpOnly, encrypted) in the app, access token attached
server-side, zero tokens in browser storage.
Trust boundaries
- Browser ⇄ Next.js BFF — TLS, session cookie, CSRF-safe (SameSite=Lax + origin checks on mutations).
- BFF ⇄ core-api — TLS, short-lived Keycloak access token, tenant claims verified server-side.
- core-api ⇄ data plane — mTLS in-cluster (Cilium), per-service credentials.
- worker/ai-gateway ⇄ OpenAI — egress-controlled,
AI_PHI_MODEgate,store:false, minimized payloads. - integration-service ⇄ vendors — allow-listed egress, credentials from OpenBao, signed webhooks.
Primary data flows
Recording → transcript → drafts → approval
Approved document → patient
core-api → NATS document.approved → worker → document-service (Gotenberg) →
MinIO versioned asset → delivery request (portal-first; email is a notification
with a secure expiring link, never a PHI attachment by default) → patient portal
→ signature / acceptance → audit.
Environments
| Environment | Data | Topology |
|---|---|---|
| development | synthetic only | Docker Compose (compose.yaml), one command |
| staging | synthetic / approved de-identified | RKE2, production-like, separate credentials |
| production | real PHI | RKE2 ≥3 CP + ≥3 app workers + dedicated DB/storage nodes, Canadian DCs, DR site |
Degraded modes
- OpenAI unavailable → recording, transcript editing, manual documentation, charts, portal all keep working; generation queues with visible status.
- NATS unavailable → synchronous APIs keep working; async pipelines pause with backlog alerts.
- Redis unavailable → sessions fall back to DB-backed checks; rate limits fail closed for auth endpoints, open for reads.