docs: add architecture and intake intent documentation
- Add architecture overview, implementation plan, and intent overview - Add intake intent process specs (gap analyse, bouwplan, testplan) - Add swift architecture specs and visualization prompts - Remove obsolete aispeedrun-manifesto template Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
471
docs/swift/architectuur.md
Normal file
471
docs/swift/architectuur.md
Normal file
@@ -0,0 +1,471 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user