Architecture
EDFlow system context and runtime containers for hospital reviewers: the web tier, the Convex backend, the mobile apps, the integration engine link, optional providers, environments and what runs where.
System context
flowchart LR
subgraph People
PAT[Patient phone]
FAM[Family member]
STF[Staff workstation and managed phone]
TV[Waiting-room display]
end
subgraph Hospital[Hospital network]
EHR[EHR] --> ENG[Integration engine]
ENTRA[Microsoft Entra ID, optional]
end
subgraph Service[The service]
WEB[Web tier: Next.js]
APP[Mobile apps: iOS, Android]
BE[Backend: Convex database, functions, auth, scheduler, HTTP actions]
end
subgraph Providers[Optional providers, generic content only]
PUSH[Push: Expo, APNs, FCM]
SMS[SMS]
MAIL[Email]
end
PAT --> WEB
PAT --> APP
FAM --> WEB
STF --> WEB
STF --> APP
TV --> WEB
WEB <-->|WebSocket, auth cookie proxy| BE
APP <-->|WebSocket| BE
ENG -->|HTTPS, signed or OAuth| BE
STF -.->|OIDC| ENTRA
BE --> PUSH
BE --> SMS
BE --> MAIL
What crosses each boundary
| Boundary | Carries | Never carries |
|---|---|---|
| Engine → backend | Minimized events, FHIR Bundles or HL7 messages; prohibited fields are dropped or rejected before anything is stored | Result values, notes, diagnoses, health card numbers, addresses, phones |
| Browser or app ↔ backend | The signed-in person's projected view only | Anything outside that person's allow-list |
| Browser ↔ web tier | Static assets, the app shell, auth cookies | Rendered patient data: the web tier never renders patient data on the server |
| Backend → push, SMS, email providers | Generic template text, opaque links | Names, test names, hospital names, clinical words, code types |
| Backend → AI gateway | Only what a site's approved AI features need, under zero data retention | Anything before the site's privacy approval |
Runtime containers
| Container | Runs | Region (hospital production) |
|---|---|---|
| Web tier | Next.js app: token shells, patient and family web, staff console, admin, display, stations; the auth cookie proxy | Vercel functions in yul1 (Montréal), or a container in the hospital's Canadian account |
| Backend | Self-hosted Convex: database, functions, auth, scheduler, crons, HTTP actions (ingest, integration API, provider webhooks) | AWS ca-central-1, RDS PostgreSQL with KMS customer-managed keys; DR ca-west-1 |
| Edge | AWS WAF, load balancer and an edge tier that validates client IPs and mTLS for the API | ca-central-1 |
| Mobile | iOS and Android apps; session tokens in the device's secure store | On device |
| Docs | This site, public documentation only | Vercel |
The demo, development and sandbox run on Convex Cloud (US East) with synthetic data only; they are separate deployments that can never reach hospital data.
Environments
| Environment | Data | Where |
|---|---|---|
| Development, showcase, docs capture | Synthetic, enforced | Convex Cloud, US |
| Integration sandbox | Synthetic, enforced (real-looking data refused) | Convex Cloud, US |
| Customer test | Hospital test-domain data, treated as PHI | AWS ca-central-1 |
| Hospital production | PHI | AWS ca-central-1 |
Synthetic-only features (the simulator, seed data, demo sign-in, reset) refuse to run unless the deployment is non-production, marked synthetic and on an allow-list, and they are not built into production bundles.
Realtime and offline
Clients subscribe to live queries over WebSocket; there is no polling. When a phone goes offline, the app shows the last known view with its time; the native app keeps it encrypted and deletes it when access ends, even without a network.
Related
Dernière mise à jour le