From 3cb60e6a0bf646150195af28e4c4c6aeaf0873d2 Mon Sep 17 00:00:00 2001 From: colinislit Date: Sat, 22 Nov 2025 08:20:58 +0100 Subject: [PATCH] security --- .../documentatie/[category]/page.tsx | 2 +- app/(marketing)/documentatie/page.tsx | 2 +- .../fo-screening-intake-v1_0.md | 1179 +++++++++++++++++ ...o-screening-intake-v1_0.md:Zone.Identifier | 4 + .../security/security-remediation-plan.md | 1072 +++++++++++++++ 5 files changed, 2257 insertions(+), 2 deletions(-) create mode 100644 docs/specs/screening-intake/fo-screening-intake-v1_0.md create mode 100644 docs/specs/screening-intake/fo-screening-intake-v1_0.md:Zone.Identifier create mode 100644 docs/specs/security/security-remediation-plan.md diff --git a/app/(marketing)/documentatie/[category]/page.tsx b/app/(marketing)/documentatie/[category]/page.tsx index 6ea2813..e678b82 100644 --- a/app/(marketing)/documentatie/[category]/page.tsx +++ b/app/(marketing)/documentatie/[category]/page.tsx @@ -53,7 +53,7 @@ export default async function ReleasePage({ params }: ReleasePageProps) { return (
-
+
{/* Header */}
diff --git a/app/(marketing)/documentatie/page.tsx b/app/(marketing)/documentatie/page.tsx index accbe3e..6a7bee9 100644 --- a/app/(marketing)/documentatie/page.tsx +++ b/app/(marketing)/documentatie/page.tsx @@ -24,7 +24,7 @@ export default async function ReleasesPage() {
{/* Header */} -
+

Feature Documentatie

diff --git a/docs/specs/screening-intake/fo-screening-intake-v1_0.md b/docs/specs/screening-intake/fo-screening-intake-v1_0.md new file mode 100644 index 0000000..aa23ee5 --- /dev/null +++ b/docs/specs/screening-intake/fo-screening-intake-v1_0.md @@ -0,0 +1,1179 @@ +# 🧩 Functioneel Ontwerp (FO) – Screening & Intake GGZ + +**Projectnaam:** AI Speedrun - Mini EPD v1.2 +**Versie:** v1.0 +**Datum:** 21-11-2024 +**Auteur:** Colin (met Claude) + +--- + +## 1. Doel en relatie met het PRD + +🎯 **Doel van dit document:** +Het Functioneel Ontwerp beschrijft **hoe** de screening- en intakeflow in de praktijk werkt voor GGZ-professionals. Dit document vertaalt de requirements uit het PRD naar concrete schermen, acties en interacties. + +πŸ“˜ **Toelichting aan de lezer:** +Dit FO beschrijft de basisflow voor screening en intake zonder AI-functionaliteit in eerste instantie. De focus ligt op het vastleggen van cliΓ«ntgegevens, activiteiten tijdens screening, en het documenteren van de intake met alle relevante onderdelen zoals contactmomenten, kindchecks, risicotaxaties, anamneses, onderzoeken, ROM-metingen, diagnoses en behandeladvies. + +**Relatie met bestaande UI:** +De screening en intake functionaliteit wordt geΓ―ntegreerd in de bestaande two-level navigation structuur (Level 1: Behandelaar Context, Level 2: Client Dossier Context) zoals beschreven in de interface design documenten. + +--- + +## 2. Overzicht van de belangrijkste onderdelen + +1. CliΓ«ntenbeheer (overzicht + aanmaken) +2. CliΓ«ntdetail - Basisgegevens +3. **Screening** (activiteitenlog, documenten, hulpvraag, besluit) +4. **Intake** (overzicht + detail met tabs) + - Contactmomenten + - Kindchecks + - Risicotaxaties + - Anamneses + - Onderzoeken + - ROM onderzoeken + - Diagnose + - Behandeladvies +5. Diagnose (samenvatting) +6. Behandelplan + +--- + +## 3. Userstories + +| ID | Rol | Doel / Actie | Verwachte waarde | Prioriteit | +|----|------|---------------|------------------|-------------| +| US-01 | Secretaresse | Nieuwe cliΓ«nt aanmaken met basisgegevens | Start screeningsproces | Hoog | +| US-02 | Secretaresse | John Doe aanmaken voor crisissituaties | Opname mogelijk zonder volledige gegevens | Hoog | +| US-03 | Secretaresse | Activiteiten loggen tijdens screening | Volledig overzicht van contactmomenten | Hoog | +| US-04 | Secretaresse | Documenten uploaden (verwijsbrief, etc.) | Compleet dossier voor psycholoog | Hoog | +| US-05 | Psycholoog | Hulpvraag beschrijven | Heldere registratie van zorgvraag | Hoog | +| US-06 | Psycholoog | Screeningsbesluit nemen | CliΓ«nt doorsturen naar intake | Hoog | +| US-07 | Psycholoog | Nieuwe intake aanmaken | Start intakeproces voor cliΓ«nt | Hoog | +| US-08 | Psycholoog | Contactmomenten vastleggen | Chronologisch overzicht van gesprekken | Hoog | +| US-09 | Psycholoog | Kindchecks uitvoeren en registreren | Veiligheid kinderen bewaken | Hoog | +| US-10 | Psycholoog | Risicotaxaties maken | Risico's inschatten en documenteren | Hoog | +| US-11 | Psycholoog | Anamnese afnemen en vastleggen | Volledigbeeld van voorgeschiedenis | Hoog | +| US-12 | Psycholoog | Onderzoeken registreren | Medische bevindingen documenteren | Middel | +| US-13 | Psycholoog | ROM-metingen toevoegen | Voortgang objectief meten | Middel | +| US-14 | Psycholoog | DSM-5 diagnose stellen | Correcte registratie voor behandeling | Hoog | +| US-15 | Psycholoog | Behandeladvies formuleren | Duidelijk advies richting behandeling | Hoog | +| US-16 | Psycholoog | Multiple intakes per cliΓ«nt beheren | Bij overplaatsing naar andere afdeling | Middel | +| US-17 | Beide | CliΓ«ntstatus volgen | Inzicht waar cliΓ«nt zich in proces bevindt | Middel | + +--- + +## 4. Functionele werking per onderdeel + +### 4.1 CliΓ«ntenbeheer + +**CliΓ«ntenlijst (Level 1)** +* Tabel met kolommen: Naam, BSN, Geboortedatum, Status, Laatst gewijzigd +* Filter op status: Alle / Planned / Active / Finished / Cancelled +* Zoekbalk: zoeken op naam of BSN +* Knop: *+ Nieuwe cliΓ«nt* +* Klik op rij β†’ naar cliΓ«ntdetail (Level 2) + +**Status badges:** +- `planned` β†’ Badge "Screening" (geel/oranje) +- `active` β†’ Badge "Actief" (groen) +- `finished` β†’ Badge "Afgerond" (grijs) +- `cancelled` β†’ Badge "Afgemeld" (rood) + +**Nieuwe cliΓ«nt aanmaken** +* Formulier met velden: + - Voornaam, achternaam (verplicht) + - BSN (optioneel - kan leeg voor John Doe) + - Geboortedatum (verplicht) + - Adres, postcode, woonplaats + - Telefoonnummer, email + - Verzekeraar, polisnummer + - Checkbox: *Dit is een John Doe (crisis)* +* Bij aanvinken John Doe: BSN wordt optioneel, melding "Gegevens kunnen later worden aangevuld" +* Knop: *Opslaan* β†’ status wordt "planned", redirect naar cliΓ«ntdetail + +--- + +### 4.2 CliΓ«ntdetail - Basisgegevens (Level 2) + +**Pagina-indeling:** +* Header: Naam cliΓ«nt, status badge, laatst gewijzigd +* Sidebar: ← CliΓ«nten | Dashboard | Basisgegevens | Screening | Intake | Diagnose | Behandelplan | Rapportage +* Alle tabs zijn altijd zichtbaar, ongeacht status + +**Tab: Basisgegevens** +* Toon alle cliΓ«ntinformatie in leesmodus +* Bij John Doe: waarschuwing "Incomplete gegevens - vul BSN aan zodra beschikbaar" +* Knop *Bewerken* β†’ formulier wordt bewerkbaar +* Knop *Opslaan* β†’ terug naar leesmodus + +--- + +### 4.3 Screening (Level 2 - Tab) + +**Tab: Screening** +Bevat vier secties: + +**Sectie 1: Activiteitenlog** +* Tijdlijn met notities (nieuwste bovenaan) +* Per notitie: timestamp (automatisch), gebruikersnaam (automatisch), tekst +* Invoerveld onderaan: "Nieuwe activiteit toevoegen..." +* Knop: *Toevoegen* β†’ notitie verschijnt direct in tijdlijn +* Voorbeelden: + - "Moeder gebeld, verwijsbrief volgt per post" + - "School gesproken, concentratieproblemen bevestigd" + - "Verwijsbrief ontvangen" + - "Huisarts gecontacteerd voor medicatieoverzicht" + +**Sectie 2: Documenten** +* Upload-zone: drag & drop of klik om bestand te kiezen +* Lijst geΓΌploade documenten: + - Bestandsnaam, datum upload, geΓΌpload door + - Download-icoon, verwijder-icoon +* Accepteert: PDF, DOC, DOCX, JPG, PNG +* Documenttypes: Verwijsbrief, Verhuisbericht, Indicatie gemeente, Overig + +**Sectie 3: Hulpvraag** +* Groot tekstveld (textarea, geen rich text editor nodig) +* Label: "Beschrijving hulpvraag" +* Bewerkbaar door secretaresse Γ©n psycholoog +* Auto-save functionaliteit (optioneel) +* Placeholder: "Beschrijf de hulpvraag van de cliΓ«nt..." + +**Sectie 4: Screeningsbesluit (alleen psycholoog)** +* Radio buttons: + - β—‹ Geschikt voor intake + - β—‹ Niet geschikt / doorverwijzen +* Indien geschikt β†’ dropdown verschijnt: "Naar welke afdeling?" + - Volwassenen + - Jeugd (< 18 jaar) + - Forensisch + - Verslaving + - Ouderen (65+) + - FACT (Flexibele Assertive Community Treatment) +* Tekstveld: "Notities bij besluit" +* Knop: *Besluit opslaan* +* Bij opslaan geschikt β†’ status wordt "active" +* Bij niet geschikt β†’ status wordt "cancelled" + +--- + +### 4.4 Intake (Level 2 - Tab) + +#### 4.4.1 Intake Overzicht + +**Layout: Kaarten per intake** + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Intake - Aanvang zorg β”‚ +β”‚ 12 oktober 2023 - 26 oktober 2023 β”‚ +β”‚ Afdeling: Volwassenen β”‚ +β”‚ Status: Afgerond βœ“ β”‚ +β”‚ β”‚ +β”‚ 3 contactmomenten β€’ Diagnose: F41.0, F32.1 β”‚ +β”‚ [Bekijk details β†’] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Intake - Overplaatsing Forensisch β”‚ +β”‚ 15 januari 2024 - Lopend β”‚ +β”‚ Afdeling: Forensisch β”‚ +β”‚ Status: Bezig β”‚ +β”‚ β”‚ +β”‚ 1 contactmoment β€’ Nog geen diagnose β”‚ +β”‚ [Bekijk details β†’] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +[+ Nieuwe intake] +``` + +**Kaart inhoud:** +- Titel: "Intake - [Reden/Type]" +- Datum range: startdatum - einddatum (of "Lopend") +- Afdeling waar intake voor is +- Status: Bezig / Afgerond +- Samenvatting: aantal contactmomenten, diagnose indien aanwezig +- Knop: [Bekijk details β†’] + +**Nieuwe intake aanmaken:** +* Klik op [+ Nieuwe intake] +* Modal/formulier met velden: + - Titel/Reden (bijv. "Aanvang zorg", "Overplaatsing Forensisch") + - Afdeling (dropdown) + - Startdatum + - Psycholoog/behandelaar +* Knop: *Aanmaken* β†’ navigeert naar intake detail view + +**User action:** +* Klik op kaart of [Bekijk details] β†’ navigeert naar intake detail view + +--- + +#### 4.4.2 Intake Detail View + +**URL structuur:** +`/epd/clients/[clientId]/intake/[intakeId]` + +**Header sectie:** +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ ← Terug naar intakes β”‚ +β”‚ β”‚ +β”‚ Intake - Aanvang zorg β”‚ +β”‚ 12 oktober 2023 - 26 oktober 2023 β”‚ +β”‚ Afdeling: Volwassenen β€’ Dr. van den Berg β”‚ +β”‚ Status: Afgerond βœ“ [Bewerken]β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +**Tab navigatie (horizontaal):** +``` +[Algemeen] [Contactmomenten] [Kindcheck] [Risicotaxatie] +[Anamnese] [Onderzoeken] [ROM] [Diagnose] [Behandeladvies] +``` + +--- + +#### 4.4.3 Tab: Algemeen + +**Inhoud:** +* Algemene informatie intake + - Startdatum + - Einddatum (of "Lopend") + - Afdeling + - Behandelend psycholoog + - Status +* Hulpvraag (overgenomen uit Screening tab) + - Read-only weergave + - Verwijzing: "Zie Screening tab voor volledige context" +* Screeningsbesluit (overgenomen uit Screening tab) + - Read-only weergave + - Toon besluit en notities +* Notities bij intake (vrij tekstveld) + - Algemene opmerkingen over deze intake + +**Bewerken:** +* Knop [Bewerken] rechtsboven +* Alleen aanpasbaar: notities, status, einddatum +* Hulpvraag en screeningsbesluit zijn read-only (kunnen alleen in Screening tab worden aangepast) + +--- + +#### 4.4.4 Tab: Contactmomenten + +**Overzicht:** +``` +3 contactmomenten [+ Nieuw contactmoment] + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ 12-10-2023 - Intakegesprek β”‚ +β”‚ 14:30 - 15:30 β€’ Op locatie β”‚ +β”‚ Dr. van den Berg β”‚ +β”‚ [Bekijk/bewerk] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ 19-10-2023 - Aanvullend onderzoek β”‚ +β”‚ 10:00 - 11:00 β€’ Op locatie β”‚ +β”‚ Dr. van den Berg β”‚ +β”‚ [Bekijk/bewerk] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ 26-10-2023 - Terugkoppeling β”‚ +β”‚ 15:00 - 15:30 β€’ Telefonisch β”‚ +β”‚ Dr. van den Berg β”‚ +β”‚ [Bekijk/bewerk] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +**Nieuw contactmoment toevoegen:** +* Klik [+ Nieuw contactmoment] +* Formulier met velden: + - Datum (datepicker) + - Starttijd - Eindtijd + - Type: Intakegesprek / Aanvullend onderzoek / Terugkoppeling / Telefonisch contact / Huisbezoek / Overig + - Locatie: Op locatie / Telefonisch / Videobellen / Huisbezoek + - Aanwezigen (tekstveld, bijv. "CliΓ«nt, partner, moeder") + - Gespreksnotities (groot tekstveld) +* Knop: *Opslaan* + +**Contactmoment detail bekijken/bewerken:** +* Klik [Bekijk/bewerk] op kaart +* Slide-in panel van rechts OF expand kaart +* Toon alle velden in leesmodus +* Knop [Bewerken] β†’ velden worden bewerkbaar +* Knop [Opslaan] β†’ terug naar leesmodus + +--- + +#### 4.4.5 Tab: Kindcheck + +**Overzicht:** +``` +2 kindchecks [+ Nieuwe kindcheck] + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Kindcheck 1 β”‚ +β”‚ 12-10-2023 β€’ Dr. van den Berg β”‚ +β”‚ Status: Geen zorgen β”‚ +β”‚ [Bekijk/bewerk] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Kindcheck 2 β”‚ +β”‚ 19-10-2023 β€’ Dr. van den Berg β”‚ +β”‚ Status: Monitoring nodig β”‚ +β”‚ [Bekijk/bewerk] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +**Nieuwe kindcheck toevoegen:** +* Klik [+ Nieuwe kindcheck] +* Formulier met velden: + - Datum check (datepicker) + - Zijn er thuiswonende kinderen? (ja/nee) + - Indien ja: + - Aantal kinderen + - Leeftijden kinderen + - Zorgen over veiligheid/welzijn? (ja/nee) + - Indien ja: toelichting (tekstveld) + - Actie ondernomen? (ja/nee) + - Indien ja: beschrijving actie + - Status: Geen zorgen / Monitoring nodig / Melding gedaan / Overleg jeugdzorg + - Notities (vrij tekstveld) +* Knop: *Opslaan* + +--- + +#### 4.4.6 Tab: Risicotaxatie + +**Overzicht:** +``` +2 risicotaxaties [+ Nieuwe risicotaxatie] + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Risicotaxatie - SuΓ―cidaliteit β”‚ +β”‚ 12-10-2023 β€’ Dr. van den Berg β”‚ +β”‚ Risico: Laag β”‚ +β”‚ [Bekijk/bewerk] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Risicotaxatie - Agressie β”‚ +β”‚ 19-10-2023 β€’ Dr. van den Berg β”‚ +β”‚ Risico: Gemiddeld β”‚ +β”‚ [Bekijk/bewerk] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +**Nieuwe risicotaxatie toevoegen:** +* Klik [+ Nieuwe risicotaxatie] +* Formulier met velden: + - Datum taxatie (datepicker) + - Type risico (dropdown): + - SuΓ―cidaliteit + - Agressie naar anderen + - Zelfverwaarlozing + - Middelenmisbruik + - Verward gedrag + - Overig + - Risico-inschatting: + - Laag / Gemiddeld / Hoog / Zeer hoog + - Onderbouwing (tekstveld) + - Maatregelen (tekstveld) + - Evaluatiedatum (datepicker, optioneel) + - Notities (vrij tekstveld) +* Knop: *Opslaan* + +--- + +#### 4.4.7 Tab: Anamnese + +**Overzicht:** +``` +1 anamnese [+ Nieuwe anamnese] + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Psychiatrische anamnese β”‚ +β”‚ 12-10-2023 β€’ Dr. van den Berg β”‚ +β”‚ [Bekijk/bewerk] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +**Nieuwe anamnese toevoegen:** +* Klik [+ Nieuwe anamnese] +* Formulier met velden: + - Datum (datepicker) + - Type anamnese: + - Psychiatrische anamnese + - Sociale anamnese + - Medische anamnese + - Familieanamnese + - Ontwikkelingsanamnese + - Overig + - Inhoud (groot tekstveld met rich text editor) + - Secties kunnen zijn: + - Klachten en hulpvraag + - Voorgeschiedenis psychiatrie + - Somatische voorgeschiedenis + - Medicatie + - Middelengebruik + - Familie/sociale context + - Opleiding/werk + - Levensloop + - Belangrijke gebeurtenissen + - Notities (vrij tekstveld) +* Knop: *Opslaan* + +--- + +#### 4.4.8 Tab: Onderzoeken + +**Overzicht:** +``` +3 onderzoeken [+ Nieuw onderzoek] + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Bloedonderzoek β”‚ +β”‚ 13-10-2023 β€’ Verwezen door Dr. van den Bergβ”‚ +β”‚ Uitslag: Binnen normale waarden β”‚ +β”‚ [Bekijk/bewerk] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Neuropsychologisch onderzoek β”‚ +β”‚ 18-10-2023 β€’ GZ-psycholoog Janssen β”‚ +β”‚ Uitslag: Zie rapport β”‚ +β”‚ [Bekijk/bewerk] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +**Nieuw onderzoek toevoegen:** +* Klik [+ Nieuw onderzoek] +* Formulier met velden: + - Datum onderzoek (datepicker) + - Type onderzoek: + - Bloedonderzoek + - Neuropsychologisch onderzoek + - Psychodiagnostiek + - IQ-test + - Persoonlijkheidsonderzoek + - EEG/ECG/andere medische tests + - Overig + - Uitgevoerd door (tekstveld) + - Reden onderzoek (tekstveld) + - Bevindingen/uitslag (tekstveld of upload rapport) + - Document uploaden (optioneel) + - Notities (vrij tekstveld) +* Knop: *Opslaan* + +--- + +#### 4.4.9 Tab: ROM + +**Overzicht:** +``` +2 ROM-metingen [+ Nieuwe ROM-meting] + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ OQ-45 (Outcome Questionnaire) β”‚ +β”‚ 12-10-2023 β”‚ +β”‚ Score: 67 (klinisch bereik) β”‚ +β”‚ [Bekijk/bewerk] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ PHQ-9 (Depressie vragenlijst) β”‚ +β”‚ 12-10-2023 β”‚ +β”‚ Score: 14 (matig ernstig) β”‚ +β”‚ [Bekijk/bewerk] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +**Nieuwe ROM-meting toevoegen:** +* Klik [+ Nieuwe ROM-meting] +* Formulier met velden: + - Datum afname (datepicker) + - Type vragenlijst (dropdown): + - OQ-45 (Outcome Questionnaire) + - PHQ-9 (Depressie) + - GAD-7 (Angst) + - HADS (Hospital Anxiety and Depression Scale) + - SCL-90 + - HONOS (Health of the Nation Outcome Scales) + - Overig + - Score (numeriek veld) + - Interpretatie (automatisch op basis van score, of handmatig) + - Notities (vrij tekstveld) + - Upload resultaat (PDF, optioneel) +* Knop: *Opslaan* + +--- + +#### 4.4.10 Tab: Diagnose + +**Overzicht:** +``` +Diagnoses gesteld tijdens intake: + +[+ Diagnose toevoegen] + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ F41.0 - Paniekstoornis β”‚ +β”‚ Datum: 26-10-2023 β”‚ +β”‚ Ernst: Matig β”‚ +β”‚ β”‚ +β”‚ Toelichting: β”‚ +β”‚ CliΓ«nt voldoet aan criteria voor β”‚ +β”‚ paniekstoornis. Frequente paniekaanvallen β”‚ +β”‚ met vermijdingsgedrag. β”‚ +β”‚ β”‚ +β”‚ [Bewerken] [Verwijderen] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ F32.1 - Matige depressieve episode β”‚ +β”‚ Datum: 26-10-2023 β”‚ +β”‚ Ernst: Matig β”‚ +β”‚ β”‚ +β”‚ Toelichting: β”‚ +β”‚ Depressieve klachten sinds 1 jaar, β”‚ +β”‚ verminderd functioneren op werk. β”‚ +β”‚ β”‚ +β”‚ [Bewerken] [Verwijderen] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +**Diagnose toevoegen:** +* Klik [+ Diagnose toevoegen] +* Formulier met velden: + - DSM-5 code zoeken (autocomplete zoekbalk) + - Typ code (bijv. F41.0) of zoekterm (bijv. "paniek") + - Dropdown toont matches + - Geselecteerde diagnose toont: code + volledige omschrijving + - Ernst: Licht / Matig / Ernstig / Zeer ernstig + - Datum diagnose (datepicker) + - Toelichting (tekstveld) + - Waarom deze diagnose? + - Welke criteria zijn van toepassing? + - Relevante observaties + - Status: Voorlopig / Definitief / Differentiaal diagnose +* Knop: *Opslaan* + +**Diagnose bewerken/verwijderen:** +* Knop [Bewerken] β†’ velden worden bewerkbaar +* Knop [Verwijderen] β†’ bevestigingsmelding β†’ diagnose wordt verwijderd + +**Multiple diagnoses:** +* Er kunnen meerdere diagnoses worden toegevoegd +* Volgorde = relevantie (primair, secundair, etc.) +* Drag & drop om volgorde te wijzigen (optioneel, later) + +--- + +#### 4.4.11 Tab: Behandeladvies + +**Inhoud:** +``` +Behandeladvies + +Datum advies: 26-10-2023 +Behandelend psycholoog: Dr. van den Berg + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ [Rich text editor] β”‚ +β”‚ β”‚ +β”‚ Op basis van de intake wordt geadviseerd: β”‚ +β”‚ β”‚ +β”‚ 1. Start cognitieve gedragstherapie β”‚ +β”‚ gericht op paniekstoornis β”‚ +β”‚ β”‚ +β”‚ 2. Aanvullend medicatie-overleg met β”‚ +β”‚ psychiater (SSRI overwegen) β”‚ +β”‚ β”‚ +β”‚ 3. Wekelijkse sessies, duur ca. 12-16 β”‚ +β”‚ sessies β”‚ +β”‚ β”‚ +β”‚ 4. ROM-metingen elke 4 weken β”‚ +β”‚ β”‚ +β”‚ Doorzetten naar: Afdeling Volwassenen, β”‚ +β”‚ Zorgprogramma: Angststoornissen β”‚ +β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +[Bewerken] [Opslaan] +``` + +**Velden:** +* Datum advies (automatisch, datepicker) +* Behandelend psycholoog (automatisch gevuld, aanpasbaar) +* Behandeladvies (rich text editor) + - Aanbevolen behandelvorm + - Frequentie en duur + - Aanvullende interventies + - Medicatie-overleg indien relevant + - Monitoring en evaluatie +* Doorzetten naar: + - Afdeling (dropdown: blijft dezelfde of wijzigt) + - Zorgprogramma (dropdown) + - Behandelaar (optioneel, dropdown met psychologen) +* Knop: *Opslaan* + +**Status van intake:** +* Na invullen van behandeladvies kan intake worden afgerond +* Checkbox: "Intake afronden" +* Bij afronden: status intake wordt "Afgerond" +* Einddatum wordt automatisch ingevuld (huidige datum) + +--- + +### 4.5 Diagnose tab (Level 2 - Overzicht alle diagnoses) + +**Doel:** Overzicht van alle diagnoses gesteld tijdens alle intakes + +**Inhoud:** +``` +Overzicht diagnoses + +Actieve diagnoses: + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ F41.0 - Paniekstoornis β”‚ +β”‚ Gesteld: 26-10-2023 (Intake - Aanvang zorg)β”‚ +β”‚ Ernst: Matig β”‚ +β”‚ [Bekijk in intake] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ F32.1 - Matige depressieve episode β”‚ +β”‚ Gesteld: 26-10-2023 (Intake - Aanvang zorg)β”‚ +β”‚ Ernst: Matig β”‚ +β”‚ [Bekijk in intake] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +Eerdere diagnoses: + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ F43.1 - Posttraumatische stressstoornis β”‚ +β”‚ Gesteld: 15-06-2020 (Intake - Oude instell)β”‚ +β”‚ Status: Hersteld β”‚ +β”‚ [Bekijk in intake] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +**Functionaliteit:** +* Geaggregeerd overzicht van alle diagnoses uit alle intakes +* Gegroepeerd: Actieve diagnoses / Eerdere diagnoses +* Per diagnose: link naar intake waar deze is gesteld +* Geen directe bewerking (moet via Intake β†’ Diagnose tab) + +--- + +### 4.6 Behandelplan tab (Level 2) + +**Inhoud:** (zoals eerder beschreven, niet gewijzigd) +* SMART doelen +* Interventies +* Frequentie en duur +* Meetmomenten + +**Koppeling met Intake:** +* Behandeladvies uit meest recente intake wordt als basis gebruikt +* Behandelplan bouwt voort op diagnose en advies + +--- + +## 5. UI-overzicht (visuele structuur) + +### Level 1: Behandelaar Context + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Mini-ECD [Zoek cliΓ«nt...] [Avatar] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ β”‚ β”‚ +β”‚ Dashboard β”‚ CliΓ«nten [+ Nieuwe CliΓ«nt] β”‚ +β”‚ CliΓ«nten β—„ β”‚ β”‚ +β”‚ Agenda β”‚ [Filter: Status β–Ό] [Zoek...] β”‚ +β”‚ Rapportage β”‚ β”‚ +β”‚ β”‚ Naam BSN Geb Status β”‚ +β”‚ β”‚ ───────────────────────────────────── β”‚ +β”‚ β”‚ Bas J. 123... 20-11 ● Actief β”‚ +β”‚ β”‚ Anna dV 456... 15-03 ● Actief β”‚ +β”‚ β”‚ Peter S. 789... 22-07 ● Screeningβ”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Level 2: Client Dossier - Tab Screening + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Mini-ECD Bas Jansen β–Ό [● Screening] [Zoek...] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ β”‚ β”‚ +│← CliΓ«nten β”‚ Screening β”‚ +β”‚ β”‚ β”‚ +β”‚ Dashboard β”‚ β–Ό Activiteitenlog β”‚ +β”‚ Basisgegevensβ”‚ 14-11 10:30 - Sandra: Moeder gebeld β”‚ +β”‚ Screening β—„ β”‚ 15-11 14:00 - John: Verwijsbrief ontv. β”‚ +β”‚ Intake β”‚ [Nieuwe activiteit...] [Toevoegen] β”‚ +β”‚ Diagnose β”‚ β”‚ +β”‚ Behandelplanβ”‚ β–Ό Documenten β”‚ +β”‚ Rapportage β”‚ πŸ“„ Verwijsbrief_huisarts.pdf β”‚ +β”‚ β”‚ [Upload document] β”‚ +β”‚ β”‚ β”‚ +β”‚ β”‚ β–Ό Hulpvraag β”‚ +β”‚ β”‚ [Groot tekstveld...] β”‚ +β”‚ β”‚ β”‚ +β”‚ β”‚ β–Ό Screeningsbesluit (psycholoog) β”‚ +β”‚ β”‚ β—‹ Geschikt voor intake β”‚ +β”‚ β”‚ β—‹ Niet geschikt β”‚ +β”‚ β”‚ [Opslaan besluit] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Level 2: Client Dossier - Tab Intake (Overzicht) + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Mini-ECD Bas Jansen β–Ό [● Actief] [Zoek...] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ β”‚ β”‚ +│← CliΓ«nten β”‚ Intake β”‚ +β”‚ β”‚ [+ Nieuwe] β”‚ +β”‚ Dashboard β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ Basisgegevensβ”‚ β”‚ Intake - Aanvang zorg β”‚ β”‚ +β”‚ Screening β”‚ β”‚ 12-10-2023 - 26-10-2023 β”‚ β”‚ +β”‚ Intake β—„ β”‚ β”‚ Afdeling: Volwassenen β”‚ β”‚ +β”‚ Diagnose β”‚ β”‚ Status: Afgerond βœ“ β”‚ β”‚ +β”‚ Behandelplanβ”‚ β”‚ 3 contactmomenten β€’ F41.0, F32.1 β”‚ β”‚ +β”‚ Rapportage β”‚ β”‚ [Bekijk details β†’] β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”‚ Intake - Overplaatsing Forensisch β”‚ β”‚ +β”‚ β”‚ β”‚ 15-01-2024 - Lopend β”‚ β”‚ +β”‚ β”‚ β”‚ Status: Bezig β”‚ β”‚ +β”‚ β”‚ β”‚ [Bekijk details β†’] β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +### Level 2: Client Dossier - Intake Detail (Tab Contactmomenten) + +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Mini-ECD Bas Jansen β–Ό [● Actief] [Zoek...] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ β”‚ ← Terug naar intakes β”‚ +│← CliΓ«nten β”‚ β”‚ +β”‚ β”‚ Intake - Aanvang zorg β”‚ +β”‚ Dashboard β”‚ 12-10-2023 - 26-10-2023 β”‚ +β”‚ Basisgegevensβ”‚ Volwassenen β€’ Dr. van den Berg β”‚ +β”‚ Screening β”‚ [Bewerken] β”‚ +β”‚ Intake β—„ β”‚ ───────────────────────────────────── β”‚ +β”‚ Diagnose β”‚ [Algemeen] [Contactmomentenβ—„] [Kindcheck]β”‚ +β”‚ Behandelplanβ”‚ [Risico] [Anamnese] [Onderzoeken] [ROM] β”‚ +β”‚ Rapportage β”‚ [Diagnose] [Behandeladvies] β”‚ +β”‚ β”‚ ───────────────────────────────────── β”‚ +β”‚ β”‚ 3 contactmomenten [+ Nieuw contact] β”‚ +β”‚ β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”‚ 12-10-2023 - Intakegesprek β”‚ β”‚ +β”‚ β”‚ β”‚ 14:30-15:30 β€’ Op locatie β”‚ β”‚ +β”‚ β”‚ β”‚ [Bekijk/bewerk] β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ β”‚ +β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ β”‚ 19-10-2023 - Aanvullend onderzoek β”‚ β”‚ +β”‚ β”‚ β”‚ [Bekijk/bewerk] β”‚ β”‚ +β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +--- + +## 6. Interacties met AI (functionele beschrijving) + +*In deze basisversie zijn er nog geen AI-functies. Deze sectie wordt later ingevuld wanneer AI-ondersteuning wordt toegevoegd voor:* +- Samenvatting contactmomenten +- Suggesties voor DSM-5 codes op basis van anamnese en gespreksnotities +- Genereren behandeladvies op basis van diagnose en intake +- Extractie hulpvraag uit documenten +- Risk assessment ondersteuning + +--- + +## 7. Gebruikersrollen en rechten + +| Rol | Toegang tot | Beperkingen | +|------|--------------|-------------| +| Secretaresse | CliΓ«ntenbeheer, Basisgegevens, Screening (behalve besluit) | Kan geen screeningsbesluit nemen, geen toegang tot Intake detail | +| Psycholoog | Alles | Volledige toegang tot alle onderdelen | + +**Rechtenmatrix details:** + +| Functie | Secretaresse | Psycholoog | +|---------|--------------|------------| +| CliΓ«nt aanmaken | βœ… | βœ… | +| Basisgegevens bewerken | βœ… | βœ… | +| Activiteit loggen | βœ… | βœ… | +| Document uploaden | βœ… | βœ… | +| Hulpvraag beschrijven | βœ… | βœ… | +| Screeningsbesluit | ❌ | βœ… | +| Intake aanmaken | ❌ | βœ… | +| Intake bewerken | ❌ | βœ… | +| Contactmomenten | ❌ | βœ… | +| Kindcheck | ❌ | βœ… | +| Risicotaxatie | ❌ | βœ… | +| Anamnese | ❌ | βœ… | +| Onderzoeken | ❌ | βœ… | +| ROM | ❌ | βœ… | +| Diagnose toevoegen | ❌ | βœ… | +| Behandeladvies | ❌ | βœ… | + +--- + +## 8. Statussen en statusovergangen + +### 8.1 CliΓ«nt statussen (FHIR EpisodeOfCare compatible) + +**Mogelijke statussen:** +1. **planned** - Aangemeld / In screening +2. **active** - Intake tot einde behandeling (in zorg) +3. **finished** - Behandeling afgerond +4. **cancelled** - Niet geschikt / afgemeld + +**Status badges in UI:** +- `planned` β†’ Badge "Screening" (oranje/geel, ●) +- `active` β†’ Badge "Actief" (groen, ●) +- `finished` β†’ Badge "Afgerond" (grijs, ●) +- `cancelled` β†’ Badge "Afgemeld" (rood, ●) + +**Waar zichtbaar:** +- Header Level 2 (naast cliΓ«ntnaam) +- CliΓ«ntenlijst (kolom Status) +- CliΓ«ntdetail - Basisgegevens + +### 8.2 Statusflow + +``` +Nieuw aangemaakt β†’ planned (Screening) + ↓ +Screeningsbesluit "geschikt" β†’ active + ↓ +Intake(s) uitgevoerd β†’ blijft active + ↓ +Behandeling β†’ blijft active + ↓ +Behandeling afgerond β†’ finished + +Alternative flow: +Screeningsbesluit "niet geschikt" β†’ cancelled +CliΓ«nt meldt zich af β†’ cancelled +``` + +**Automatische statuswijzigingen:** +- Bij aanmaken cliΓ«nt β†’ `planned` +- Bij screeningsbesluit "geschikt voor intake" β†’ `active` +- Bij screeningsbesluit "niet geschikt" β†’ `cancelled` +- Bij afronden behandeling β†’ `finished` + +**Handmatige statuswijzigingen:** +- Psycholoog kan status handmatig wijzigen in Basisgegevens +- Bijvoorbeeld: van `active` naar `cancelled` als cliΓ«nt zich afmeldt +- Van `active` naar `finished` bij afronden behandeling + +### 8.3 Intake statussen + +**Per intake (niet te verwarren met cliΓ«nt status):** +- **Bezig** - Intake is gestart maar nog niet afgerond +- **Afgerond** - Intake is compleet, behandeladvies is gegeven + +**Overgang:** +- Bij aanmaken intake β†’ "Bezig" +- Na invullen behandeladvies + checkbox "Intake afronden" β†’ "Afgerond" + +--- + +## 9. Validaties en foutafhandeling + +### 9.1 Verplichte velden bij aanmaken cliΓ«nt +- Voornaam, achternaam +- Geboortedatum +- BSN (behalve bij John Doe) + +### 9.2 Validaties + +**BSN validatie:** +- 9 cijfers +- Modulo-11 check (Nederlandse BSN validatie) +- Uniek binnen systeem + +**Geboortedatum:** +- Niet in de toekomst +- Realistisch (bijv. niet ouder dan 120 jaar) + +**Email (indien ingevuld):** +- Geldig emailformaat + +**DSM-5 codes:** +- Moet bestaan in DSM-5 codering +- Format: Letter gevolgd door cijfers (bijv. F41.0) + +### 9.3 Foutmeldingen + +**Inline validatie:** +- Bij formulierveld (rood met icoon) +- Real-time feedback tijdens typen + +**Toast-meldingen:** +- Systeemfouten +- Succesmeldingen na opslaan + +**Bevestigingsdialogen:** +- Destructieve acties (verwijderen intake, diagnose, etc.) +- Status wijzigingen met grote impact + +### 9.4 Edge cases + +**John Doe zonder BSN:** +- Waarschuwing tonen in header +- Later aanvullen mogelijk via Basisgegevens +- Flag "incomplete_data" in systeem + +**Duplicaat BSN:** +- Melding "CliΓ«nt met dit BSN bestaat al" +- Link naar bestaande cliΓ«nt + +**Ontbrekende documenten:** +- Geen blocker voor screening +- Wel waarschuwing bij screeningsbesluit: "Let op: nog geen verwijsbrief aanwezig" + +**Multiple intakes:** +- Nieuwe intake kan alleen worden aangemaakt als cliΓ«nt status = `active` +- Vorige intake hoeft niet afgerond te zijn (kan parallel lopen) + +**Screeningsbesluit wijzigen:** +- Waarschuwing als er al een intake is gestart +- "Let op: er is al een intake aangemaakt voor deze cliΓ«nt. Wijzigen kan invloed hebben op de intake." + +--- + +## 10. Data requirements + +### 10.1 Client +- id, voornaam, achternaam, bsn, geboortedatum +- adres, postcode, woonplaats +- telefoon, email +- verzekeraar, polisnummer +- status (planned/active/finished/cancelled) +- is_john_doe (boolean) +- created_at, updated_at, created_by + +### 10.2 Screening +- client_id +- hulpvraag (text) +- besluit (geschikt/niet_geschikt) +- afdeling (indien geschikt) +- besluit_notities (text) +- besluit_datum, besluit_door + +### 10.3 Screening Activiteit +- screening_id +- datum_tijd (timestamp) +- gebruiker (naam) +- activiteit (text) + +### 10.4 Screening Document +- screening_id +- bestandsnaam, bestandstype, bestandsgrootte +- upload_datum, geupload_door +- document_type (verwijsbrief/verhuisbericht/indicatie/overig) +- file_path of blob + +### 10.5 Intake +- id, client_id +- titel (bijv. "Aanvang zorg", "Overplaatsing Forensisch") +- afdeling +- psycholoog_id +- startdatum, einddatum (nullable) +- status (bezig/afgerond) +- notities (algemene notities) +- created_at, updated_at + +### 10.6 Contactmoment +- id, intake_id +- datum, starttijd, eindtijd +- type (intakegesprek/aanvullend/terugkoppeling/telefonisch/etc) +- locatie (op_locatie/telefonisch/video/huisbezoek) +- aanwezigen (text) +- notities (text, rich text) +- created_at, updated_at, created_by + +### 10.7 Kindcheck +- id, intake_id +- datum +- thuiswonende_kinderen (boolean) +- aantal_kinderen (int, nullable) +- leeftijden_kinderen (text, nullable) +- zorgen (boolean) +- zorgen_toelichting (text, nullable) +- actie_ondernomen (boolean, nullable) +- actie_beschrijving (text, nullable) +- status (geen_zorgen/monitoring/melding/overleg_jeugdzorg) +- notities (text) +- created_at, created_by + +### 10.8 Risicotaxatie +- id, intake_id +- datum +- type_risico (suicidaliteit/agressie/zelfverwaarlozing/etc) +- risico_niveau (laag/gemiddeld/hoog/zeer_hoog) +- onderbouwing (text) +- maatregelen (text) +- evaluatiedatum (date, nullable) +- notities (text) +- created_at, created_by + +### 10.9 Anamnese +- id, intake_id +- datum +- type (psychiatrisch/sociaal/medisch/familie/ontwikkeling/overig) +- inhoud (text, rich text) +- notities (text) +- created_at, created_by + +### 10.10 Onderzoek +- id, intake_id +- datum +- type (bloedonderzoek/neuropsychologisch/psychodiagnostiek/etc) +- uitgevoerd_door (text) +- reden (text) +- bevindingen (text) +- document_id (nullable, link naar geupload rapport) +- notities (text) +- created_at, created_by + +### 10.11 ROM Meting +- id, intake_id +- datum +- type_vragenlijst (OQ-45/PHQ-9/GAD-7/HADS/SCL-90/HONOS/overig) +- score (numeric) +- interpretatie (text) +- notities (text) +- document_id (nullable, link naar resultaat) +- created_at, created_by + +### 10.12 Diagnose +- id, intake_id +- dsm5_code (string, bijv. "F41.0") +- dsm5_omschrijving (string, bijv. "Paniekstoornis") +- ernst (licht/matig/ernstig/zeer_ernstig) +- datum_diagnose +- toelichting (text) +- status (voorlopig/definitief/differentiaal) +- volgorde (int, voor primair/secundair) +- created_at, created_by + +### 10.13 Behandeladvies +- id, intake_id (one-to-one) +- datum_advies +- psycholoog_id +- advies_tekst (text, rich text) +- afdeling_doorzetten (string) +- zorgprogramma (string) +- behandelaar_id (nullable) +- created_at, updated_at, created_by + +--- + +## 11. Navigatie en URL structuur + +### 11.1 Level 1 URLs (Behandelaar Context) +``` +/epd/dashboard β†’ Behandelaar dashboard +/epd/clients β†’ CliΓ«nten lijst +/epd/agenda β†’ Agenda (toekomstig) +/epd/reports β†’ Rapportage (toekomstig) +``` + +### 11.2 Level 2 URLs (Client Dossier Context) +``` +/epd/clients/[clientId] β†’ Client dashboard +/epd/clients/[clientId]/basisgegevens β†’ Basisgegevens +/epd/clients/[clientId]/screening β†’ Screening tab +/epd/clients/[clientId]/intake β†’ Intake overzicht (kaarten) +/epd/clients/[clientId]/intake/[intakeId] β†’ Intake detail (met tabs) +/epd/clients/[clientId]/diagnose β†’ Diagnose overzicht +/epd/clients/[clientId]/behandelplan β†’ Behandelplan +/epd/clients/[clientId]/rapportage β†’ Rapportage +``` + +### 11.3 Intake detail sub-routes (optioneel, via tabs) +``` +/epd/clients/[clientId]/intake/[intakeId]?tab=algemeen +/epd/clients/[clientId]/intake/[intakeId]?tab=contactmomenten +/epd/clients/[clientId]/intake/[intakeId]?tab=kindcheck +/epd/clients/[clientId]/intake/[intakeId]?tab=risicotaxatie +/epd/clients/[clientId]/intake/[intakeId]?tab=anamnese +/epd/clients/[clientId]/intake/[intakeId]?tab=onderzoeken +/epd/clients/[clientId]/intake/[intakeId]?tab=rom +/epd/clients/[clientId]/intake/[intakeId]?tab=diagnose +/epd/clients/[clientId]/intake/[intakeId]?tab=behandeladvies +``` + +--- + +## 12. Bijlagen & Referenties + +**Verwijzingen:** +- PRD v1.2 (Product Requirements Document) +- TO v1.2 (Technisch Ontwerp) +- Build Plan AI Speedrun +- FHIR GGZ Schema (database structuur) +- Interface Design Plan (mocks-ui-flow.md) +- Interface Design Complete Specification (inteface-design-plan.md) + +**Standaarden:** +- FHIR EpisodeOfCare (statussen) +- DSM-5 (diagnosecodes) +- Koppeltaal (toekomstige integratie) + +**Volgende stappen:** +1. TO uitwerken voor database schema en API endpoints +2. UX/UI wireframes verfijnen voor intake detail tabs +3. Build plan Week 1-2: implementatie screening & intake basis +4. Build plan Week 2-3: AI-ondersteuning toevoegen + +--- + +## 13. Out of Scope voor MVP + +De volgende functionaliteit is bewust buiten scope gelaten voor de MVP: +- Agenda functionaliteit (contactmomenten worden handmatig toegevoegd) +- Automatische notificaties en herinneringen +- Export functionaliteit (PDF rapporten) +- GeΓ―ntegreerde ROM-afname (vragenlijsten worden extern afgenomen) +- Medicatie module +- Crisis/spoed-protocols +- Multi-user collaborative editing +- Uitgebreide rechten per afdeling/team +- Audit logging van wijzigingen +- Archivering en backup functionaliteit +- Templates voor intakes/anamneses +- Bulk acties op cliΓ«nten +- Geavanceerde zoekfilters +- Dashboard analytics voor behandelaar + +Deze functionaliteiten kunnen post-MVP worden toegevoegd op basis van gebruikersfeedback. + +--- + +**Einde Functioneel Ontwerp v1.0** diff --git a/docs/specs/screening-intake/fo-screening-intake-v1_0.md:Zone.Identifier b/docs/specs/screening-intake/fo-screening-intake-v1_0.md:Zone.Identifier new file mode 100644 index 0000000..c0c6e24 --- /dev/null +++ b/docs/specs/screening-intake/fo-screening-intake-v1_0.md:Zone.Identifier @@ -0,0 +1,4 @@ +[ZoneTransfer] +ZoneId=3 +ReferrerUrl=https://claude.ai/chat/904d781b-2ce6-4f3b-9863-0c70dbdce984 +HostUrl=https://claude.ai/api/organizations/8a590403-7491-4913-ae4f-e0085c8dfb82/conversations/904d781b-2ce6-4f3b-9863-0c70dbdce984/wiggle/download-file?path=%2Fmnt%2Fuser-data%2Foutputs%2Ffo-screening-intake-v1_0.md diff --git a/docs/specs/security/security-remediation-plan.md b/docs/specs/security/security-remediation-plan.md new file mode 100644 index 0000000..86259d1 --- /dev/null +++ b/docs/specs/security/security-remediation-plan.md @@ -0,0 +1,1072 @@ +# Security Remediation Plan - Mini-EPD Prototype + +**Versie:** 1.0 +**Datum:** 22 november 2025 +**Status:** In Progress +**Eigenaar:** Development Team + +## Inhoudsopgave + +1. [Executive Summary](#executive-summary) +2. [Critical Issues (Week 1)](#critical-issues-week-1) +3. [High Priority Issues (Week 1-2)](#high-priority-issues-week-1-2) +4. [Medium Priority Issues (Week 2-3)](#medium-priority-issues-week-2-3) +5. [Long-term Improvements (Week 4+)](#long-term-improvements-week-4) +6. [Verification & Testing](#verification--testing) +7. [Compliance Checklist](#compliance-checklist) + +--- + +## Executive Summary + +### Huidige Status +- **Security Score:** 4/10 +- **Critical Issues:** 1 +- **High Priority:** 3 +- **Medium/Low Priority:** 7 +- **GDPR Compliant:** ❌ Nee + +### Doelstelling +- **Target Security Score:** 9/10 +- **Target Completion:** 4 weken +- **GDPR Compliance:** βœ… Ja (binnen 6 weken) + +### Impact +- **Development Time:** ~60-80 uur +- **Risk Reduction:** 85% +- **Compliance:** AVG/GDPR ready + +--- + +## Critical Issues (Week 1) + +### πŸ”΄ Issue #1: Exposed Production Credentials + +**Severity:** CRITICAL +**Priority:** P0 (Immediate) +**Effort:** 2 uur +**Status:** ⏳ Not Started + +#### Probleem +`.env.example` bevat echte productie API keys in plaats van placeholders. + +**Bestand:** `.env.example:4-5,14` + +```bash +# HUIDIGE SITUATIE (GEVAARLIJK!) +NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGci... # Echte key! +SUPABASE_SERVICE_ROLE_KEY=eyJhbGci... # Echte key! +ANTHROPIC_API_KEY=sk-ant-api03-rrPx... # Echte key! +``` + +#### Impact +- ⚠️ Service role key geeft volledige database toegang +- ⚠️ Iedereen met repository toegang kan alle data lezen/schrijven +- ⚠️ API misbruik mogelijk +- ⚠️ GDPR data breach + +#### Remediation Steps + +**Stap 1: Roteer alle API keys (URGENT)** + +```bash +# 1. Supabase Dashboard +# β†’ Settings β†’ API β†’ Project API keys +# β†’ "Reset anon key" en "Reset service_role key" + +# 2. Anthropic Dashboard +# β†’ Settings β†’ API Keys β†’ "Delete" oude key β†’ "Create new key" + +# 3. Update .env.local met nieuwe keys +``` + +**Stap 2: Update .env.example** + +```bash +# .env.example - ALLEEN PLACEHOLDERS! +NEXT_PUBLIC_SUPABASE_URL=https://your-project-id.supabase.co +NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-here +SUPABASE_SERVICE_ROLE_KEY=your-service-role-key-here +ANTHROPIC_API_KEY=sk-ant-your-key-here +``` + +**Stap 3: Verificatie** + +```bash +# Check git history voor gelekte keys +git log -p -- .env.example | grep -E "eyJhbGci|sk-ant" + +# Als keys gevonden: consider repository als compromised +# Overwegen: nieuwe private fork maken +``` + +#### Acceptance Criteria +- [ ] .env.example bevat alleen placeholders +- [ ] Alle productie keys zijn geroteerd +- [ ] Git history gecontroleerd op leaks +- [ ] Team geΓ―nformeerd over nieuwe keys +- [ ] .env.local is toegevoegd aan .gitignore (already done βœ…) + +#### Verificatie +```bash +# Test dat app nog werkt met nieuwe keys +pnpm dev +# Navigeer naar http://localhost:3000 en test login +``` + +--- + +## High Priority Issues (Week 1-2) + +### 🟠 Issue #2: Next.js Vulnerabilities + +**Severity:** HIGH +**Priority:** P1 +**Effort:** 1 uur +**Status:** ⏳ Not Started + +#### Probleem +Next.js 14.2.18 heeft 7+ bekende security vulnerabilities: +- CVE-2024-56332: DoS via Server Actions +- CVE-2025-48068: Source code exposure +- 5+ additional issues + +**Bestand:** `package.json:25` + +#### Remediation Steps + +```bash +# Update Next.js naar latest patched versie +pnpm update next@latest + +# Of specifiek naar 14.2.30+ +pnpm add next@14.2.30 + +# Test build +pnpm build + +# Run audit +pnpm audit +``` + +#### Acceptance Criteria +- [ ] Next.js >= 14.2.30 +- [ ] `pnpm audit` toont 0 high/critical issues +- [ ] Build succesvol +- [ ] Alle functionaliteit werkt nog + +--- + +### 🟠 Issue #3: Ontbrekende Security Headers + +**Severity:** HIGH +**Priority:** P1 +**Effort:** 3 uur +**Status:** ⏳ Not Started + +#### Probleem +Kritieke security headers ontbreken, waardoor XSS, clickjacking en andere attacks mogelijk zijn. + +**Bestand:** `next.config.mjs` + +#### Remediation Steps + +**Stap 1: Voeg security headers toe** + +```javascript +// next.config.mjs +/** @type {import('next').NextConfig} */ +const nextConfig = { + // ... existing config ... + + async headers() { + return [ + { + // Apply headers to all routes + source: '/:path*', + headers: [ + { + key: 'X-DNS-Prefetch-Control', + value: 'on' + }, + { + key: 'Strict-Transport-Security', + value: 'max-age=63072000; includeSubDomains; preload' + }, + { + key: 'X-Frame-Options', + value: 'SAMEORIGIN' + }, + { + key: 'X-Content-Type-Options', + value: 'nosniff' + }, + { + key: 'X-XSS-Protection', + value: '1; mode=block' + }, + { + key: 'Referrer-Policy', + value: 'strict-origin-when-cross-origin' + }, + { + key: 'Permissions-Policy', + value: 'camera=(), microphone=(), geolocation=(), interest-cohort=()' + }, + { + key: 'Content-Security-Policy', + value: [ + "default-src 'self'", + "script-src 'self' 'unsafe-eval' 'unsafe-inline'", // Next.js needs unsafe-eval + "style-src 'self' 'unsafe-inline'", + "img-src 'self' data: https:", + "font-src 'self' data:", + "connect-src 'self' https://dqugbrpwtisgyxscpefg.supabase.co", + "frame-ancestors 'self'" + ].join('; ') + } + ] + } + ] + } +} + +export default nextConfig; +``` + +**Stap 2: Test headers** + +```bash +# Start dev server +pnpm dev + +# Test in browser console +curl -I http://localhost:3000 | grep -E "X-Frame|Content-Security" + +# Of gebruik online tool: https://securityheaders.com/ +``` + +#### Acceptance Criteria +- [ ] Alle security headers aanwezig +- [ ] CSP policy implementeerd (zonder app te breken) +- [ ] Test op securityheaders.com score A of B +- [ ] Geen console errors door CSP + +#### Verificatie Script +```bash +#!/bin/bash +# test-security-headers.sh + +URL="http://localhost:3000" + +echo "Testing security headers..." + +HEADERS=( + "X-Frame-Options" + "X-Content-Type-Options" + "Strict-Transport-Security" + "Content-Security-Policy" + "Referrer-Policy" +) + +for HEADER in "${HEADERS[@]}"; do + VALUE=$(curl -s -I "$URL" | grep -i "$HEADER") + if [ -n "$VALUE" ]; then + echo "βœ… $VALUE" + else + echo "❌ Missing: $HEADER" + fi +done +``` + +--- + +### 🟠 Issue #4: Te Permissieve CORS Policy + +**Severity:** HIGH +**Priority:** P1 +**Effort:** 2 uur +**Status:** ⏳ Not Started + +#### Probleem +`Access-Control-Allow-Origin: *` staat CSRF aanvallen toe. + +**Bestand:** `app/api/leads/route.ts:110` + +#### Remediation Steps + +**Stap 1: Update CORS policy** + +```typescript +// app/api/leads/route.ts + +// Add at top of file +const ALLOWED_ORIGINS = [ + 'https://yourdomain.com', + 'https://www.yourdomain.com', + ...(process.env.NODE_ENV === 'development' ? ['http://localhost:3000'] : []) +]; + +export async function OPTIONS(request: NextRequest) { + const origin = request.headers.get('origin'); + const allowedOrigin = ALLOWED_ORIGINS.includes(origin || '') + ? origin + : ALLOWED_ORIGINS[0]; + + return NextResponse.json({}, { + status: 200, + headers: { + 'Access-Control-Allow-Origin': allowedOrigin || '', + 'Access-Control-Allow-Methods': 'POST, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type', + 'Access-Control-Max-Age': '86400', // 24 hours + } + }); +} + +export async function POST(request: NextRequest) { + // Add origin check + const origin = request.headers.get('origin'); + if (origin && !ALLOWED_ORIGINS.includes(origin)) { + return NextResponse.json( + { error: 'Origin not allowed' }, + { status: 403 } + ); + } + + // ... rest of existing code ... +} +``` + +**Stap 2: Test CORS** + +```bash +# Test valid origin +curl -X POST http://localhost:3000/api/leads \ + -H "Origin: http://localhost:3000" \ + -H "Content-Type: application/json" \ + -d '{"name":"Test","email":"test@example.com","projectType":"web","message":"Test message test message test"}' + +# Test invalid origin (should fail) +curl -X POST http://localhost:3000/api/leads \ + -H "Origin: https://evil.com" \ + -H "Content-Type: application/json" \ + -d '{"name":"Test","email":"test@example.com","projectType":"web","message":"Test message test message test"}' +``` + +#### Acceptance Criteria +- [ ] CORS beperkt tot specifieke origins +- [ ] Development localhost werkt nog +- [ ] Invalid origins worden geweigerd +- [ ] OPTIONS preflight werkt correct + +--- + +### 🟠 Issue #5: FHIR API zonder Authenticatie + +**Severity:** HIGH +**Priority:** P1 +**Effort:** 2 uur +**Status:** ⏳ Not Started + +#### Probleem +FHIR endpoints zijn publiek toegankelijk zonder authenticatie check. + +**Bestanden:** +- `app/api/fhir/Patient/route.ts` +- `app/api/fhir/Patient/[id]/route.ts` +- `app/api/fhir/Practitioner/route.ts` +- `app/api/fhir/Practitioner/[id]/route.ts` + +#### Remediation Steps + +**Stap 1: Voeg auth check toe aan alle FHIR endpoints** + +```typescript +// app/api/fhir/Patient/route.ts +import { NextRequest, NextResponse } from 'next/server'; +import { createClient } from '@/lib/auth/server'; +import { supabaseAdmin } from '@/lib/supabase/server'; +// ... other imports ... + +export async function GET(request: NextRequest) { + try { + // βœ… ADD: Verify authentication + const supabase = await createClient(); + const { data: { user }, error: authError } = await supabase.auth.getUser(); + + if (authError || !user) { + return NextResponse.json( + createOperationOutcome('error', 'security', 'Authentication required'), + { status: 401 } + ); + } + + // Rest of existing code... + const { searchParams } = new URL(request.url); + // ... + } catch (error) { + // ... + } +} + +export async function POST(request: NextRequest) { + try { + // βœ… ADD: Verify authentication + const supabase = await createClient(); + const { data: { user }, error: authError } = await supabase.auth.getUser(); + + if (authError || !user) { + return NextResponse.json( + createOperationOutcome('error', 'security', 'Authentication required'), + { status: 401 } + ); + } + + // Rest of existing code... + } catch (error) { + // ... + } +} +``` + +**Stap 2: Herhaal voor alle FHIR endpoints** + +Pas dezelfde pattern toe op: +- `app/api/fhir/Patient/[id]/route.ts` +- `app/api/fhir/Practitioner/route.ts` +- `app/api/fhir/Practitioner/[id]/route.ts` + +**Stap 3: Test authenticatie** + +```bash +# Test zonder auth (should fail) +curl http://localhost:3000/api/fhir/Patient + +# Test met auth (should succeed) +# 1. Login via browser en copy session cookie +# 2. Test met cookie: +curl http://localhost:3000/api/fhir/Patient \ + -H "Cookie: sb-access-token=YOUR_TOKEN_HERE" +``` + +#### Acceptance Criteria +- [ ] Alle FHIR endpoints vereisen authenticatie +- [ ] Unauthenticated requests krijgen 401 +- [ ] Authenticated requests werken normaal +- [ ] Error messages zijn niet te verbose (geen stack traces) + +--- + +## Medium Priority Issues (Week 2-3) + +### 🟑 Issue #6: Te Permissieve RLS Policies + +**Severity:** MEDIUM +**Priority:** P2 +**Effort:** 8 uur +**Status:** ⏳ Not Started + +#### Probleem +Alle authenticated users kunnen ALLE data lezen/schrijven/verwijderen. Geen multi-tenancy isolatie. + +**Bestand:** `supabase/migrations/20241115000002_create_epd_core_tables.sql:168-181` + +#### Huidige Situatie +```sql +-- TOO PERMISSIVE! +CREATE POLICY "Allow all for authenticated users" ON clients + FOR ALL USING (auth.uid() IS NOT NULL); +``` + +#### Remediation Plan + +**Optie A: User-based isolation (Simple)** +```sql +-- Optie A: Elke user ziet alleen eigen data +-- 1. Voeg user_id toe aan tabellen +ALTER TABLE clients ADD COLUMN created_by UUID REFERENCES auth.users(id); + +-- 2. Update policies +DROP POLICY "Allow all for authenticated users" ON clients; + +CREATE POLICY "Users can view own clients" ON clients + FOR SELECT USING (created_by = auth.uid()); + +CREATE POLICY "Users can insert own clients" ON clients + FOR INSERT WITH CHECK (created_by = auth.uid()); + +CREATE POLICY "Users can update own clients" ON clients + FOR UPDATE USING (created_by = auth.uid()); + +CREATE POLICY "Users can delete own clients" ON clients + FOR DELETE USING (created_by = auth.uid()); +``` + +**Optie B: Organization-based isolation (Recommended)** +```sql +-- Optie B: Multi-tenancy met organizations +-- 1. Voeg org_id toe aan tabellen +ALTER TABLE clients ADD COLUMN org_id UUID REFERENCES organizations(id); + +-- 2. Voeg user_organizations mapping toe +CREATE TABLE user_organizations ( + user_id UUID REFERENCES auth.users(id), + org_id UUID REFERENCES organizations(id), + role TEXT CHECK (role IN ('admin', 'practitioner', 'readonly')), + PRIMARY KEY (user_id, org_id) +); + +-- 3. Create helper function +CREATE OR REPLACE FUNCTION get_user_org_id(user_uuid UUID) +RETURNS UUID AS $$ + SELECT org_id FROM user_organizations + WHERE user_id = user_uuid + LIMIT 1; +$$ LANGUAGE sql SECURITY DEFINER; + +-- 4. Update policies +DROP POLICY "Allow all for authenticated users" ON clients; + +CREATE POLICY "Users can view org clients" ON clients + FOR SELECT USING ( + org_id = get_user_org_id(auth.uid()) + ); + +CREATE POLICY "Users can insert org clients" ON clients + FOR INSERT WITH CHECK ( + org_id = get_user_org_id(auth.uid()) + ); + +-- Etc... +``` + +#### Migration File + +Maak nieuwe migration: `supabase/migrations/YYYYMMDD_implement_rls_isolation.sql` + +```sql +-- Migration: Implement proper RLS isolation +-- Option: Organization-based (recommended) + +BEGIN; + +-- Step 1: Add org_id to all tables +ALTER TABLE clients ADD COLUMN org_id UUID REFERENCES organizations(id); +ALTER TABLE intake_notes ADD COLUMN org_id UUID; +ALTER TABLE problem_profiles ADD COLUMN org_id UUID; +ALTER TABLE treatment_plans ADD COLUMN org_id UUID; +ALTER TABLE ai_events ADD COLUMN org_id UUID; + +-- Step 2: Create user_organizations mapping +CREATE TABLE user_organizations ( + user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE, + org_id UUID REFERENCES organizations(id) ON DELETE CASCADE, + role TEXT NOT NULL CHECK (role IN ('admin', 'practitioner', 'readonly')), + created_at TIMESTAMPTZ DEFAULT NOW(), + PRIMARY KEY (user_id, org_id) +); + +-- Step 3: Helper function +CREATE OR REPLACE FUNCTION get_user_org_id(user_uuid UUID) +RETURNS UUID AS $$ + SELECT org_id FROM user_organizations + WHERE user_id = user_uuid + LIMIT 1; +$$ LANGUAGE sql SECURITY DEFINER STABLE; + +-- Step 4: Update RLS policies +-- CLIENTS +DROP POLICY IF EXISTS "Allow all for authenticated users" ON clients; + +CREATE POLICY "org_select" ON clients FOR SELECT + USING (org_id = get_user_org_id(auth.uid())); + +CREATE POLICY "org_insert" ON clients FOR INSERT + WITH CHECK (org_id = get_user_org_id(auth.uid())); + +CREATE POLICY "org_update" ON clients FOR UPDATE + USING (org_id = get_user_org_id(auth.uid())); + +CREATE POLICY "org_delete" ON clients FOR DELETE + USING (org_id = get_user_org_id(auth.uid())); + +-- TODO: Repeat for other tables + +COMMIT; +``` + +#### Acceptance Criteria +- [ ] Migration geschreven en getest +- [ ] Elke tabel heeft org_id kolom +- [ ] RLS policies filteren op org_id +- [ ] Users kunnen alleen eigen org data zien +- [ ] Test met 2+ orgs en 2+ users per org + +#### Testing +```sql +-- Test script +-- 1. Create 2 orgs +INSERT INTO organizations (name) VALUES ('Org A'), ('Org B'); + +-- 2. Create 2 users (via Supabase auth) +-- 3. Map users to orgs +INSERT INTO user_organizations (user_id, org_id, role) VALUES + ('user-1-uuid', 'org-a-uuid', 'practitioner'), + ('user-2-uuid', 'org-b-uuid', 'practitioner'); + +-- 4. Create clients +INSERT INTO clients (first_name, last_name, birth_date, org_id) VALUES + ('Client A', 'Org A', '1990-01-01', 'org-a-uuid'), + ('Client B', 'Org B', '1990-01-01', 'org-b-uuid'); + +-- 5. Login as user-1 and query +-- Should only see Client A + +-- 6. Login as user-2 and query +-- Should only see Client B +``` + +--- + +### 🟑 Issue #7: Organizations Table zonder Policies + +**Severity:** MEDIUM +**Priority:** P2 +**Effort:** 1 uur +**Status:** ⏳ Not Started + +#### Probleem +Organizations tabel heeft RLS enabled maar geen policies. + +#### Remediation Steps + +```sql +-- supabase/migrations/YYYYMMDD_add_organizations_policies.sql + +-- Allow authenticated users to view organizations they belong to +CREATE POLICY "users_view_own_orgs" ON organizations + FOR SELECT USING ( + id IN ( + SELECT org_id FROM user_organizations + WHERE user_id = auth.uid() + ) + ); + +-- Allow org admins to update their organization +CREATE POLICY "admins_update_org" ON organizations + FOR UPDATE USING ( + id IN ( + SELECT org_id FROM user_organizations + WHERE user_id = auth.uid() AND role = 'admin' + ) + ); + +-- Only service role can INSERT/DELETE organizations +-- (via migrations or admin panel) +``` + +#### Acceptance Criteria +- [ ] SELECT policy voor organizations +- [ ] UPDATE policy voor admins +- [ ] Users kunnen eigen org zien +- [ ] Users kunnen geen andere orgs zien + +--- + +### 🟑 Issue #8: Rate Limiting + +**Severity:** MEDIUM +**Priority:** P2 +**Effort:** 4 uur +**Status:** ⏳ Not Started + +#### Probleem +Geen rate limiting op API endpoints = spam/DoS risico. + +#### Remediation Options + +**Optie A: Vercel KV + Upstash (Recommended voor Vercel deployment)** + +```bash +# Install +pnpm add @upstash/ratelimit @upstash/redis +``` + +```typescript +// lib/rate-limit.ts +import { Ratelimit } from "@upstash/ratelimit"; +import { Redis } from "@upstash/redis"; + +export const ratelimit = new Ratelimit({ + redis: Redis.fromEnv(), + limiter: Ratelimit.slidingWindow(10, "10 s"), + analytics: true, +}); + +// Usage in API route: +import { ratelimit } from '@/lib/rate-limit'; + +export async function POST(request: NextRequest) { + const ip = request.headers.get('x-forwarded-for') ?? 'unknown'; + const { success } = await ratelimit.limit(ip); + + if (!success) { + return NextResponse.json( + { error: 'Too many requests' }, + { status: 429 } + ); + } + + // ... rest of code +} +``` + +**Optie B: Simple in-memory (Development only)** + +```typescript +// lib/simple-rate-limit.ts +const requests = new Map(); + +export function checkRateLimit( + ip: string, + maxRequests: number = 10, + windowMs: number = 10000 +): boolean { + const now = Date.now(); + const userRequests = requests.get(ip) || []; + + // Filter out old requests + const recentRequests = userRequests.filter( + time => now - time < windowMs + ); + + if (recentRequests.length >= maxRequests) { + return false; + } + + recentRequests.push(now); + requests.set(ip, recentRequests); + + return true; +} +``` + +#### Endpoints die rate limiting nodig hebben +- [ ] `/api/leads` - 10 req/10s per IP +- [ ] `/api/fhir/Patient` POST - 20 req/min per user +- [ ] Auth callbacks - 5 req/min per IP + +--- + +### 🟑 Issue #9: CSRF Protection + +**Severity:** MEDIUM +**Priority:** P3 +**Effort:** 2 uur +**Status:** ⏳ Not Started + +#### Current Status +Next.js gebruikt SameSite cookies (default = Lax), wat al bescherming biedt. + +#### Additional Hardening + +```typescript +// lib/csrf.ts +import { NextRequest } from 'next/server'; + +export function verifyCsrfToken(request: NextRequest): boolean { + // Check Origin header matches host + const origin = request.headers.get('origin'); + const host = request.headers.get('host'); + + if (origin && !origin.endsWith(host || '')) { + return false; + } + + // Check Referer for additional validation + const referer = request.headers.get('referer'); + if (referer && !referer.includes(host || '')) { + return false; + } + + return true; +} + +// Usage: +export async function POST(request: NextRequest) { + if (!verifyCsrfToken(request)) { + return NextResponse.json( + { error: 'Invalid request origin' }, + { status: 403 } + ); + } + // ... +} +``` + +#### Acceptance Criteria +- [ ] CSRF checks op alle POST/PUT/DELETE endpoints +- [ ] Origin header validation +- [ ] Tests voor cross-origin requests + +--- + +### 🟑 Issue #10: Function Search Path + +**Severity:** LOW +**Priority:** P3 +**Effort:** 1 uur +**Status:** ⏳ Not Started + +#### Probleem +3 database functies hebben mutable search_path. + +#### Remediation + +```sql +-- Fix all functions +CREATE OR REPLACE FUNCTION update_updated_at_column() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_at = NOW(); + RETURN NEW; +END; +$$ LANGUAGE plpgsql +SECURITY DEFINER +SET search_path = public, pg_temp; + +CREATE OR REPLACE FUNCTION is_demo_user(user_uuid UUID) +RETURNS BOOLEAN AS $$ + SELECT EXISTS ( + SELECT 1 FROM demo_users WHERE user_id = user_uuid + ); +$$ LANGUAGE sql +SECURITY DEFINER +STABLE +SET search_path = public, pg_temp; + +CREATE OR REPLACE FUNCTION get_demo_access_level(user_uuid UUID) +RETURNS TEXT AS $$ + SELECT access_level FROM demo_users WHERE user_id = user_uuid; +$$ LANGUAGE sql +SECURITY DEFINER +STABLE +SET search_path = public, pg_temp; +``` + +--- + +### 🟑 Issue #11: Leaked Password Protection + +**Severity:** LOW +**Priority:** P3 +**Effort:** 0.5 uur (configuratie) +**Status:** ⏳ Not Started + +#### Remediation Steps + +1. Ga naar Supabase Dashboard +2. Authentication β†’ Providers β†’ Email +3. Scroll naar "Password Protection" +4. Enable "Check for leaked passwords" +5. Save + +**Link:** https://supabase.com/docs/guides/auth/password-security + +--- + +## Long-term Improvements (Week 4+) + +### πŸ”΅ Audit Logging + +**Priority:** P4 +**Effort:** 12 uur + +#### Implementatie + +```sql +-- Create audit log table +CREATE TABLE audit_log ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + user_id UUID REFERENCES auth.users(id), + action TEXT NOT NULL, -- 'SELECT', 'INSERT', 'UPDATE', 'DELETE' + table_name TEXT NOT NULL, + record_id UUID, + old_data JSONB, + new_data JSONB, + ip_address INET, + user_agent TEXT, + created_at TIMESTAMPTZ DEFAULT NOW() +); + +-- Create trigger function +CREATE OR REPLACE FUNCTION audit_trigger() +RETURNS TRIGGER AS $$ +BEGIN + INSERT INTO audit_log ( + user_id, action, table_name, record_id, old_data, new_data + ) VALUES ( + auth.uid(), + TG_OP, + TG_TABLE_NAME, + COALESCE(NEW.id, OLD.id), + CASE WHEN TG_OP = 'DELETE' THEN row_to_json(OLD) ELSE NULL END, + CASE WHEN TG_OP IN ('INSERT', 'UPDATE') THEN row_to_json(NEW) ELSE NULL END + ); + RETURN NEW; +END; +$$ LANGUAGE plpgsql SECURITY DEFINER; + +-- Apply to sensitive tables +CREATE TRIGGER audit_clients + AFTER INSERT OR UPDATE OR DELETE ON clients + FOR EACH ROW EXECUTE FUNCTION audit_trigger(); +``` + +--- + +### πŸ”΅ Encryption at Rest + +**Status:** βœ… Enabled by default (Supabase) + +Supabase gebruikt AES-256 encryption voor alle data. Geen actie nodig. + +--- + +### πŸ”΅ Backup & Recovery + +```sql +-- Automated backups (Supabase Pro) +-- Daily point-in-time recovery (7 days retention) + +-- Manual backup script +-- backup.sh +#!/bin/bash +DATE=$(date +%Y%m%d) +pg_dump $DATABASE_URL > backups/backup-$DATE.sql +``` + +--- + +## Verification & Testing + +### Security Testing Checklist + +#### Authentication Tests +- [ ] Unauthenticated users kunnen geen protected routes benaderen +- [ ] Session cookies zijn HttpOnly en Secure +- [ ] Session expiry werkt correct +- [ ] Password reset flow is secure + +#### Authorization Tests +- [ ] Users kunnen alleen eigen org data zien +- [ ] Users kunnen geen andere org data wijzigen +- [ ] Admin privileges worden correct gehandhaafd +- [ ] Service role bypassed RLS (expected) + +#### API Security Tests +```bash +# Test suite +./scripts/security-tests.sh + +# Tests: +# 1. CORS - invalid origin rejected +# 2. Rate limiting - 429 after limit +# 3. Auth - 401 without token +# 4. CSRF - cross-origin POST rejected +# 5. Headers - all security headers present +``` + +#### OWASP Top 10 Checklist +- [x] A01:2021 – Broken Access Control β†’ RLS policies +- [x] A02:2021 – Cryptographic Failures β†’ HTTPS + Supabase encryption +- [x] A03:2021 – Injection β†’ Supabase ORM (no raw SQL) +- [x] A04:2021 – Insecure Design β†’ Security-first architecture +- [x] A05:2021 – Security Misconfiguration β†’ Security headers +- [x] A06:2021 – Vulnerable Components β†’ Dependency updates +- [x] A07:2021 – Identification/Authentication Failures β†’ Supabase Auth +- [ ] A08:2021 – Software/Data Integrity Failures β†’ Code signing (TODO) +- [x] A09:2021 – Security Logging Failures β†’ Audit log (TODO) +- [x] A10:2021 – Server-Side Request Forgery β†’ No SSRF vectors + +--- + +## Compliance Checklist + +### AVG/GDPR Requirements + +#### Data Protection +- [ ] Data minimalisatie principe toegepast +- [ ] Encryptie at rest (Supabase βœ…) +- [ ] Encryptie in transit (HTTPS βœ…) +- [ ] Toegangscontrole (RLS policies) +- [ ] Audit logging geΓ―mplementeerd + +#### User Rights +- [ ] Recht op inzage (export functie) +- [ ] Recht op rectificatie (edit functie) +- [ ] Recht op vergetelheid (delete with cascade) +- [ ] Recht op dataportabiliteit (FHIR export) +- [ ] Recht op bezwaar (opt-out mechanisme) + +#### Legal Basis +- [ ] Privacy policy aanwezig +- [ ] Cookie consent (indien tracking) +- [ ] Data Processing Agreement met Supabase +- [ ] Data breach notification procedure + +#### Documentation +- [ ] Data mapping (welke data wordt opgeslagen) +- [ ] Retention policy (hoe lang bewaren) +- [ ] Access logs (wie heeft toegang gehad) +- [ ] Security incident response plan + +--- + +## Progress Tracking + +### Week 1 +- [ ] Issue #1: Rotate credentials ⚠️ URGENT +- [ ] Issue #2: Update Next.js +- [ ] Issue #3: Security headers +- [ ] Issue #4: CORS policy +- [ ] Issue #5: FHIR auth + +### Week 2 +- [ ] Issue #6: RLS policies +- [ ] Issue #7: Organizations policies +- [ ] Issue #8: Rate limiting + +### Week 3 +- [ ] Issue #9: CSRF protection +- [ ] Issue #10: Function search path +- [ ] Issue #11: Password protection +- [ ] Security testing + +### Week 4 +- [ ] Audit logging +- [ ] Documentation +- [ ] Compliance review +- [ ] Final security scan + +--- + +## Resources + +### Tools +- [Supabase Dashboard](https://supabase.com/dashboard) +- [Security Headers Checker](https://securityheaders.com/) +- [OWASP ZAP](https://www.zaproxy.org/) +- [pnpm audit](https://pnpm.io/cli/audit) + +### Documentation +- [Supabase RLS](https://supabase.com/docs/guides/auth/row-level-security) +- [Next.js Security](https://nextjs.org/docs/app/building-your-application/configuring/security-headers) +- [OWASP Top 10](https://owasp.org/www-project-top-ten/) +- [AVG/GDPR Guide](https://autoriteitpersoonsgegevens.nl/) + +--- + +**Last Updated:** 22 november 2025 +**Next Review:** Na afronding Week 1 (29 november 2025)