Files
triqura-ecd/docs/swift/architectuur.md
colinislit af88ac9446 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>
2026-02-04 19:26:14 +01:00

19 KiB

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:

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):

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):

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:

-- 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:

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:

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

// 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

# 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.