# Mini-EPD Prototype - Architectuur ## Executive Summary (C-Level) **Mini-EPD** is een moderne, AI-gestuurde elektronische patiëntendossier (EPD) oplossing voor de Nederlandse zorgsector. Het systeem combineert spraakherkenning met intelligente intentieherkenning, waardoor zorgverleners hands-free kunnen rapporteren en navigeren. ### Kernwaarden | Aspect | Waarde | |--------|--------| | **Tijdsbesparing** | 70% van commando's verwerkt in <20ms door lokale AI | | **Gebruiksgemak** | Natuurlijke taal en spraak als primaire input | | **Compliance** | GDPR-vriendelijk met soft deletes en audit trail | | **Schaalbaarheid** | Serverless architectuur, horizontaal schaalbaar | | **Integratie** | FHIR-geïnspireerd datamodel voor interoperabiliteit | ### Strategische Voordelen 1. **Lagere administratielast** - Zorgverleners dicteren notities in natuurlijke taal; AI classificeert en structureert automatisch 2. **Proactieve ondersteuning** - Systeem suggereert vervolgacties op basis van klinische protocollen 3. **Snelle implementatie** - Cloud-native stack (Vercel + Supabase) zonder on-premise infrastructuur 4. **Toekomstbestendig** - Modulaire opzet maakt toevoeging van nieuwe functionaliteit eenvoudig ### Risico's & Mitigatie | Risico | Mitigatie | |--------|-----------| | AI-hallucinaties | Drie-lagen architectuur met confidence scoring; fallback naar menselijke verificatie | | Data privacy | Row Level Security op database niveau; geen PII in logs | | Vendor lock-in | Open standaarden (FHIR, PostgreSQL); migratiepaden beschikbaar | --- ## Technische Architectuur ### Tech Stack | Component | Technologie | Motivatie | |-----------|-------------|-----------| | Frontend | Next.js 14 (App Router) | Server-side rendering, optimale SEO, moderne DX | | Database | Supabase (PostgreSQL) | Managed database met ingebouwde auth en RLS | | Auth | Supabase Auth + JWT | Industrie-standaard, SSR-compatibel | | AI Classification | Claude API (Anthropic) | State-of-the-art NLP voor Nederlands | | Speech-to-Text | Deepgram | Lage latency, hoge nauwkeurigheid | | State Management | Zustand | Lightweight, TypeScript-native | | Styling | Tailwind CSS + shadcn/ui | Consistente UI, snelle ontwikkeling | --- ### Cortex: Drie-Lagen AI Architectuur Het hart van het systeem is **Cortex**, een intelligent command center dat natuurlijke taal omzet naar gestructureerde acties. ``` ┌─────────────────────────────────────────────────────────────────┐ │ GEBRUIKER INPUT │ │ "Maak een dagnotitie voor Jan Bakker" │ └─────────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ │ LAYER 1: REFLEX ARC │ │ Latency: <20ms │ ├─────────────────────────────────────────────────────────────────┤ │ • Regex-gebaseerde pattern matching │ │ • Weighted confidence scoring │ │ • Verwerkt 70%+ van alle commando's lokaal │ │ • Escaleert bij: confidence <0.7, multi-intent, ambiguïteit │ └─────────────────────────────────────────────────────────────────┘ ↓ (indien nodig) ┌─────────────────────────────────────────────────────────────────┐ │ LAYER 2: ORCHESTRATOR │ │ Model: Claude 3.5 Haiku │ ├─────────────────────────────────────────────────────────────────┤ │ • Multi-intent detectie ("annuleer afspraak en maak notitie") │ │ • Pronoun resolutie met actieve patiënt context │ │ • Relatieve tijd parsing ("morgen", "volgende week") │ │ • Context-aware entity extraction │ └─────────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ │ LAYER 3: NUDGE │ │ Proactieve Suggesties │ ├─────────────────────────────────────────────────────────────────┤ │ • Post-actie aanbevelingen op basis van V&VN protocollen │ │ • Voorbeeld: Na wondnotitie → suggestie voor controle-interval │ │ • Niet-intrusief: toast notifications met dismiss optie │ └─────────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────────┐ │ UI ARTIFACT BLOCKS │ │ DagnotatieBlock / ZoekenBlock / OverdrachtBlock │ └─────────────────────────────────────────────────────────────────┘ ``` ### Intent Types | Intent | Beschrijving | Voorbeeld | |--------|--------------|-----------| | `dagnotitie` | Dagelijkse rapportage aanmaken | "Noteer dat mevrouw Jansen goed geslapen heeft" | | `zoeken` | Patiënt opzoeken | "Zoek Jan Bakker" | | `overdracht` | Handover bekijken | "Toon overdracht van gisteren" | | `agenda_query` | Agenda raadplegen | "Wat staat er vandaag gepland?" | | `create_appointment` | Afspraak inplannen | "Plan een intake voor morgen 14:00" | | `cancel_appointment` | Afspraak annuleren | "Annuleer de afspraak van vrijdag" | | `reschedule_appointment` | Afspraak verzetten | "Verzet de afspraak naar volgende week" | --- ### Directory Structuur ``` mini-epd-prototype/ ├── app/ # Next.js App Router │ ├── api/ # Backend API Routes │ │ ├── cortex/ # AI Command Center │ │ │ ├── classify/ # Intent classificatie │ │ │ ├── chat/ # Streaming conversatie │ │ │ ├── patients/ # Patiënt context │ │ │ └── agenda/ # Agenda operaties │ │ ├── reports/ # Rapportage CRUD │ │ ├── overdracht/ # Handover + AI summaries │ │ ├── patients/ # Patiënt data │ │ ├── deepgram/ # Speech-to-text │ │ └── fhir/ # FHIR endpoints │ │ │ ├── epd/ # EPD Modules (Protected) │ │ ├── dashboard/ # Cortex Command Center │ │ ├── verpleegrapportage/ # Nursing reports │ │ │ └── rapportage/ # Timeline invoer │ │ ├── patients/[id]/ # Patiënt dossier │ │ ├── agenda/ # Kalender (FullCalendar) │ │ └── clients/ # Cliëntenbeheer │ │ │ └── auth/ # Authenticatie │ ├── login/ │ └── reset-password/ │ ├── lib/ # Shared Business Logic │ ├── cortex/ # Drie-lagen AI systeem │ │ ├── types.ts # Type definities │ │ ├── reflex-classifier.ts # Layer 1: Pattern matching │ │ ├── orchestrator.ts # Layer 2: Claude classificatie │ │ ├── nudge.ts # Layer 3: Suggesties │ │ ├── entity-extractor.ts # Entity extraction │ │ ├── date-time-parser.ts # Datum/tijd parsing │ │ └── hooks/ # React hooks │ │ │ ├── auth/ # Auth utilities │ │ ├── server.ts # Server-side (API routes) │ │ └── client.ts # Client-side │ │ │ ├── supabase/ # Database layer │ │ ├── database.types.ts # Auto-generated types │ │ ├── client.ts # Browser client │ │ └── server.ts # SSR client │ │ │ └── types/ # Domain types │ ├── report.ts # Rapportage types │ └── overdracht.ts # Handover types │ ├── components/ # React Components │ ├── cortex/ # Cortex UI │ │ ├── command-center/ # Main container │ │ │ ├── command-center.tsx │ │ │ ├── command-input.tsx # Voice/text input │ │ │ ├── context-bar.tsx # Actieve patiënt │ │ │ ├── canvas-area.tsx # Artifact rendering │ │ │ └── offline-banner.tsx │ │ ├── blocks/ # Intent-specifieke UI │ │ │ ├── dagnotitie-block.tsx │ │ │ ├── zoeken-block.tsx │ │ │ └── overdracht-block.tsx │ │ └── chat/ # Chat componenten │ │ │ └── ui/ # shadcn/ui (29 componenten) │ ├── button.tsx │ ├── dialog.tsx │ └── ... │ ├── stores/ # State Management │ └── cortex-store.ts # Zustand store │ ├── supabase/ # Database │ └── migrations/ # SQL migrations │ └── docs/ # Documentatie └── swift/ # Cortex specificaties ``` --- ### Data Model #### Reports Table (Unified) Alle rapportages worden opgeslagen in één tabel met type-discriminatie: ```sql CREATE TABLE reports ( id UUID PRIMARY KEY, patient_id UUID REFERENCES patients(id), type report_type NOT NULL, -- enum content TEXT, structured_data JSONB, -- type-specifieke velden created_at TIMESTAMPTZ, created_by UUID REFERENCES auth.users(id), shift_date DATE, -- berekend: vóór 07:00 = vorige dag deleted_at TIMESTAMPTZ, -- soft delete ai_confidence FLOAT, ai_reasoning TEXT ); ``` **Report Types:** - `voortgang` - Voortgangsrapportage - `observatie` - Klinische observatie - `incident` - Incident melding - `medicatie` - Medicatie gerelateerd - `contact` - Contact met derden - `crisis` - Crisis interventie - `intake` - Intake notities - `behandeladvies` - Behandeladvies - `vrije_notitie` - Vrije tekst - `verpleegkundig` - Verpleegkundige notitie (met categorie) **Verpleegkundig Categories:** - `medicatie`, `adl`, `gedrag`, `incident`, `observatie` #### Shift Logic Rapporten aangemaakt vóór 07:00 worden toegewezen aan de vorige dag (nachtdienst handover): ```typescript function calculateShiftDate(createdAt: Date): Date { const hour = createdAt.getHours(); if (hour < 7) { return subDays(createdAt, 1); } return createdAt; } ``` **Diensten:** | Dienst | Tijdvak | |--------|---------| | Nacht | 00:00 - 07:00 | | Ochtend | 07:00 - 12:00 | | Middag | 12:00 - 17:00 | | Avond | 17:00 - 24:00 | --- ### API Endpoints #### Cortex APIs | Method | Endpoint | Beschrijving | |--------|----------|--------------| | POST | `/api/cortex/classify` | Intent classificatie (Reflex + Orchestrator) | | POST | `/api/cortex/chat` | Streaming chat (SSE) | | GET | `/api/cortex/context` | Huidige gebruikerscontext | | GET | `/api/cortex/patients/search` | Patiënt zoeken voor context | | GET | `/api/cortex/agenda` | Dagagenda ophalen | | POST | `/api/cortex/agenda/create` | Afspraak aanmaken | | POST | `/api/cortex/agenda/cancel` | Afspraak annuleren | | POST | `/api/cortex/agenda/reschedule` | Afspraak verzetten | #### Report APIs | Method | Endpoint | Beschrijving | |--------|----------|--------------| | GET | `/api/reports` | Lijst rapporten (filters: type, datum, patiënt) | | POST | `/api/reports` | Rapport aanmaken | | GET | `/api/reports/[id]` | Enkel rapport ophalen | | PUT | `/api/reports/[id]` | Rapport bijwerken | | DELETE | `/api/reports/[id]` | Soft delete | #### Overdracht APIs | Method | Endpoint | Beschrijving | |--------|----------|--------------| | GET | `/api/overdracht/patients` | Patiënten voor handover | | GET | `/api/overdracht/[patientId]` | Handover data per patiënt | | POST | `/api/overdracht/generate` | AI-gegenereerde samenvatting | --- ### State Management **Zustand Store** (`stores/cortex-store.ts`): ```typescript interface CortexStore { // Chat state messages: ChatMessage[]; pendingAction: IntentAction | null; // Context activePatient: Patient | null; currentShift: 'nacht' | 'ochtend' | 'middag' | 'avond'; // UI openArtifacts: ArtifactInstance[]; suggestions: NudgeSuggestion[]; patientSidebarOpen: boolean; // Actions addMessage(msg: ChatMessage): void; setActivePatient(patient: Patient): void; openArtifact(artifact: ArtifactInstance): void; acceptSuggestion(id: string): void; dismissSuggestion(id: string): void; } ``` --- ### Security #### Row Level Security (RLS) Alle tabellen hebben RLS policies die data toegang beperken tot geautoriseerde gebruikers: ```sql -- Voorbeeld: users kunnen alleen hun eigen patiënten zien CREATE POLICY "Users can view assigned patients" ON patients FOR SELECT USING (auth.uid() IN ( SELECT user_id FROM patient_assignments WHERE patient_id = patients.id )); ``` #### Authentication Flow ``` 1. Login via /auth/login 2. Supabase Auth valideert credentials 3. JWT token in httpOnly cookie 4. Middleware refresht sessie bij elk request 5. API routes valideren via createClient() 6. RLS filtert data op database niveau ``` #### Input Validation Alle API endpoints gebruiken Zod schemas: ```typescript const CreateReportSchema = z.object({ patient_id: z.string().uuid(), type: z.enum(['voortgang', 'observatie', ...]), content: z.string().min(20).max(5000), structured_data: z.object({...}).optional() }); ``` --- ### Performance | Aspect | Implementatie | Target | |--------|---------------|--------| | Intent classificatie | Layer 1 Reflex | <20ms voor 70%+ requests | | Chat responses | SSE streaming | First token <500ms | | Patient search | Debounced input | 300ms debounce | | Build optimization | Code splitting | Three.js in apart chunk | | Database queries | Selective columns | Geen overbodige data | --- ### Monitoring & Audit **AI Events Table:** ```sql CREATE TABLE ai_events ( id UUID PRIMARY KEY, kind TEXT, -- 'classify', 'summarize', 'chat' request JSONB, response JSONB, duration_ms INTEGER, created_at TIMESTAMPTZ, user_id UUID ); ``` Elk AI-verzoek wordt gelogd voor: - Compliance en audit trail - Performance monitoring - Model fine-tuning data --- ### Feature Flags ```typescript // lib/config/feature-flags.ts CORTEX_V2_ENABLED // Drie-lagen architectuur CORTEX_MULTI_INTENT // Multi-intent detectie CORTEX_NUDGE // Proactieve suggesties CORTEX_LOGGING // Debug logging (dev only) ``` --- ## Deployment ### Infrastructuur ``` ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ Vercel │────▶│ Supabase │────▶│ PostgreSQL │ │ (Frontend + │ │ (Auth) │ │ (Database) │ │ API Routes) │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ ▼ ┌─────────────────┐ ┌─────────────────┐ │ Claude API │ │ Deepgram │ │ (Anthropic) │ │ (Speech-to-Text)│ └─────────────────┘ └─────────────────┘ ``` ### Environment Variables ```bash # Supabase NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ... # AI Services ANTHROPIC_API_KEY=sk-ant-... DEEPGRAM_API_KEY=... # Feature Flags NEXT_PUBLIC_CORTEX_V2=true ``` --- ## Extensibility ### Nieuw Intent Toevoegen 1. Voeg toe aan `CortexIntent` type in `lib/cortex/types.ts` 2. Voeg Reflex patterns toe in `lib/cortex/reflex-classifier.ts` 3. Maak artifact block in `components/cortex/blocks/` 4. Update Orchestrator prompt (indien AI-driven) 5. Maak API endpoint (indien nodig) ### Nieuw Report Type Toevoegen 1. Voeg toe aan `REPORT_TYPES` enum in `lib/types/report.ts` 2. Voeg Zod schema toe voor validatie 3. Update UI componenten voor nieuw type 4. Voeg database migration toe indien nodig --- ## Conclusie De Mini-EPD architectuur is ontworpen voor: - **Snelheid**: Drie-lagen AI met <20ms lokale verwerking - **Schaalbaarheid**: Serverless, horizontaal schaalbaar - **Veiligheid**: RLS, JWT, Zod validatie op alle lagen - **Uitbreidbaarheid**: Modulaire opzet met duidelijke interfaces - **Compliance**: Audit trail, soft deletes, Nederlandse foutmeldingen Het systeem is production-ready voor MVP deployment met duidelijke paden voor doorontwikkeling.