Skip to content

docs: maak CLAUDE.md lichter en breng hem bij - #295

Open
ericwout-overheid wants to merge 3 commits into
mainfrom
chore/claude-md-actualisatie
Open

docs: maak CLAUDE.md lichter en breng hem bij#295
ericwout-overheid wants to merge 3 commits into
mainfrom
chore/claude-md-actualisatie

Conversation

@ericwout-overheid

@ericwout-overheid ericwout-overheid commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Twee dingen in deze PR: CLAUDE.md opschonen, en de ingecheckte Claude Code-automatisering in
.claude/ repareren — die deed niets meer.

Deel 1 — CLAUDE.md

Alle genoemde klassen, paden, poorten en configuratiesleutels zijn nagelopen en bestaan nog; de
inhoud was actueel. Wat eruit kwam is één structuurprobleem en drie stukken drift.

De ZAD-gids verhuist. De sectie ZAD deploy & GitOps (debug) was 12 KB: 27% van het bestand,
terwijl ze alleen nodig is bij het onderzoeken van een falende deploy of een vastgelopen preview.
CLAUDE.md wordt elke sessie volledig geladen. De tekst verhuist naar
docs/operations/zad-gitops.md — bij de verplaatsing byte-identiek, daarna één inhoudelijke
correctie (zie hieronder); er blijft een pointer staan met wat je hoe dan
ook moet weten voordat je iets aanraakt — dat Git de bron van waarheid is, de drie project-ids, dat
DELETE op een deployment destructief is, en dat handmatig OM-werk tijdens een lopende deploy
misgaat.

Drift Waarom
fbs-common-beschrijving Stond als "JAX-RS filters en exception mappers", maar draagt ook profiel/ (serviceclient, voorkeuren, toestemming), fsc/ (outway-headers, outbound-TLS) en de LDV-validators. Toestemming kwam nergens in de modulebeschrijving voor
docs/demo-runbook.md, docs/operations/, demo/podman-up.sh + smoke.sh Alleen via een omweg vindbaar; nu in de bestandentabel
uitrol-poort.sh, merge-guard.sh, proeftuin-pin.sh Van de veertien scripts in .github/scripts stonden er twee in de tabel. Deze drie vangen stille CI-uitkomsten af

CLAUDE.md: 459 → 330 regels (44 KB → 36 KB), zonder verlies van kennis.

Deel 2 — de automatisering in .claude/ was dood

Alle drie de ingecheckte automatiseringen deden niets. Dat is teambreed: .claude/settings.json,
de agents en de skills staan in git.

De twee hooks lazen $CLAUDE_TOOL_INPUT. Die variabele bestaat niet — hook-input komt als JSON
op stdin, met het pad in .tool_input.file_path. Beide greps draaiden dus op een lege string en
matchten nooit. De guard op gegenereerde code eindigde bovendien op exit 1, wat een tool-call
niet blokkeert; alleen exit 2 doet dat. Hij hield dus niets tegen, ook niet als hij wél had
gevuurd.

Twee artefacten noemden services/berichtensessiecache, een module die nu
libraries/fbs-berichtensessiecache heet: de PostToolUse-hook, en de skill openapi-wijziging die
daarmee naar een niet-bestaande spec verwees.

Wat er nu staat

De hooks zijn scripts in .claude/hooks/ in plaats van shell-eenregelaars in JSON — leesbaar, en
te draaien zonder Claude Code.

Artefact Wat het doet
hooks/gegenereerde-code-blokkeren.sh Blokkeert een edit onder target/generated-sources (nu écht: stdin-JSON, exit 2)
hooks/flyway-immutabel.sh Nieuw. Blokkeert een edit in een bestaande V*.sql; noemt het eerstvolgende vrije versienummer. Nieuwe migraties en db/rollback/ blijven bewerkbaar
hooks/geraakte-module-test.sh Leidt de module af uit het bewerkte pad in plaats van er één te noemen — zo valt een hernoeming op in plaats van de hook te laten verstommen. De twee pure-JVM-libraries draaien meteen (9s en 20s lokaal) en zwijgen als ze groen zijn; alles wat Quarkus boot of Testcontainers start, krijgt het commando geprint. FBS_HOOK_TESTS=0 zet het draaien uit
agents/taal-en-commentaar-reviewer.md Nieuw. De NL/EN-grens en de commentaarregels — geen tool dekt die af, detekt heeft de comments-ruleset juist uitgezet
agents/pii-log-auditor.md Nieuw. BSN-lekken via logs, URL's en foutmeldingen, inclusief de asymmetrie dat OIN publiek is en juist níet gemaskeerd mag worden — waar een generieke security-review de verkeerde kant op adviseert
skills/openapi-wijziging/SKILL.md Gerepareerd: service als parameter in plaats van hardgecodeerd, plus de twee stappen die ontbraken (Spectral ADR-lint en de Bruno-collectie bijwerken)
skills/pr-klaarmaken/SKILL.md Nieuw, user-only: sync vóór CI vanwege strict branch-protection, verify per geraakte module, warnings triëren, draft zonder reviewer, cross-repo sluitregel

Eén correctie in de verhuisde tekst. De gids beschreef nog dat een reconcile een door OM
uitgeschakeld component niet reactiveert en dat de deployment herscheppen de enige fix is. Sinds
RC-37 (2026-08-06) klopt dat niet meer, en het is een dure fout: het stuurt naar een DELETE die
voor projecten met de postgresql-database-service de databasegegevens wist. Een rollout heft de
uitschakeling nu op — update-image en een upsert wissen elke reden, ook op een ongewijzigde tag;
een handmatige (her)verwerking alleen een image-pull-uitschakeling. Herscheppen blijft staan als
het zware alternatief.

Verificatie

  • De verplaatste ZAD-tekst is byte-identiek aan het origineel (diff, exit 0); de correctie
    erbovenop is een aparte commit
  • De correctie is nagelopen in de OM-broncode (RijksICTGilde/RIG-Cluster) en live bevestigd op
    mpfm-w3h/pr-288/democonsole: update-image met dezelfde tag zette het component weer aan,
    zonder dataverlies
  • Elke hook handmatig gedraaid met echte stdin-JSON: blokkeergevallen geven exit 2 met uitleg
    (inclusief het juiste eerstvolgende migratienummer, V8), doorlaatgevallen exit 0
  • De snelle testroute draait lokaal groen en stil; de print-route noemt Testcontainers alleen voor
    de modules die het echt nodig hebben
  • .claude/settings.json is geldige JSON

Buiten deze PR

.claude/settings.local.json bevat ook nog verouderde permissies (services/berichtenlijst,
absolute /home/...-paden), maar dat bestand is gitignored en persoonlijk — dat hoort niet in een
PR.

Nog te bepalen

Hier hoort mogelijk een issue bij; die bestaat nog niet. Zeg het als er een aangemaakt moet worden,
dan komt de sluitregel er alsnog bij.

🤖 Generated with Claude Code

https://claude.ai/code/session_012EtTFzuvUinGmBM2ZRs71v

ericwout-overheid and others added 2 commits September 6, 2026 17:17
Een audit van CLAUDE.md tegen de huidige boom leverde één structuurprobleem en drie
stukken drift op.

De ZAD-sectie was met 12 KB goed voor 27% van het bestand, terwijl ze alleen nodig is
bij het onderzoeken van een falende deploy of preview. CLAUDE.md wordt elke sessie
volledig geladen, dus die 12 KB drukte op alles wat niet over deployen ging. De gids
gaat ongewijzigd naar docs/operations/zad-gitops.md; in CLAUDE.md blijft een pointer
staan met wat je hoe dan ook moet weten voordat je iets aanraakt: dat Git de bron van
waarheid is, welke project-ids er zijn, dat DELETE op een deployment destructief is, en
dat handmatig OM-werk tijdens een lopende deploy misgaat.

Verder bijgewerkt:

- fbs-common stond beschreven als "JAX-RS filters en exception mappers", maar draagt
  inmiddels ook de Profiel-serviceclient met voorkeuren en toestemming, de FSC-outway-
  headers en -TLS-validatie en de LDV-validators. Toestemming kwam daardoor nergens in
  de modulebeschrijving voor.
- docs/demo-runbook.md, docs/operations/ en de Podman-scripts van de demo waren alleen
  via een omweg vindbaar en staan nu in de bestandentabel.
- Van de veertien scripts in .github/scripts stonden er twee in de tabel. De drie
  poortwachters die stille CI-uitkomsten afvangen — uitrol-poort.sh, merge-guard.sh en
  proeftuin-pin.sh — zijn toegevoegd.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EtTFzuvUinGmBM2ZRs71v
Alle drie de ingecheckte automatiseringen in .claude/ deden niets meer.

De twee hooks in settings.json lazen `$CLAUDE_TOOL_INPUT`. Die variabele bestaat niet:
hook-input komt als JSON op stdin, met het bewerkte pad in .tool_input.file_path. Beide
greps draaiden dus op een lege string en matchten nooit. De guard op gegenereerde code
eindigde bovendien met `exit 1`, wat een tool-call niet blokkeert — alleen `exit 2` doet
dat. Hij hield dus niets tegen, ook niet als hij wel had gevuurd.

De PostToolUse-hook noemde daarnaast `services/berichtensessiecache`, een module die nu
`libraries/fbs-berichtensessiecache` heet. Dezelfde verouderde naam stond in de skill
openapi-wijziging, die daarmee naar een spec verwees die niet bestaat.

De hooks staan nu als scripts in .claude/hooks/ in plaats van als shell-eenregelaars in
JSON: leesbaar, en te draaien zonder Claude Code. De module-hook leidt de module af uit
het bewerkte pad in plaats van er één te noemen, zodat een hernoeming opvalt in plaats
van de hook te laten verstommen. De twee pure-JVM-libraries (9s en 20s lokaal) draaien
meteen en zwijgen als ze groen zijn; alles wat Quarkus boot of Testcontainers start,
krijgt het commando geprint in plaats van de sessie minuten te laten wachten.

Toegevoegd:

- PreToolUse-guard op bestaande Flyway-migraties. Immutabiliteit stond alleen in
  CLAUDE.md; een gewijzigde V*.sql valt pas om bij de volgende boot, ver van de edit.
  Nieuwe V(N+1)-bestanden en de rollback-scripts blijven bewerkbaar.
- Subagent taal-en-commentaar-reviewer voor de NL/EN-grens en de commentaarregels. Die
  worden door geen enkele tool gedekt; detekt heeft de comments-ruleset juist uitgezet.
- Subagent pii-log-auditor voor BSN-lekken via logs, URL's en foutmeldingen — inclusief
  de asymmetrie dat OIN publiek is en juist niet gemaskeerd mag worden, waar een
  generieke security-review de verkeerde kant op adviseert.
- Skill pr-klaarmaken (user-only) voor de PR-volgorde: sync vóór CI vanwege strict
  branch-protection, verify per geraakte module, warnings triëren, draft zonder reviewer,
  en de cross-repo sluitregel.

Handmatig geverifieerd per hook: blokkeergevallen geven exit 2 met uitleg, de
doorlaatgevallen exit 0, en de snelle testroute draait groen en stil.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012EtTFzuvUinGmBM2ZRs71v
@ericwout-overheid

Copy link
Copy Markdown
Contributor Author

Vervolgsuggesties — bewust NIET in deze PR

Bij het repareren van .claude/ kwam een langere lijst kandidaten boven water. Hieronder staan ze
als suggestie, zodat ze vindbaar zijn zonder dat deze PR verder groeit. Niets hiervan is
geïmplementeerd; elke regel is een los, klein stuk werk. Pak eruit wat je wilt.

Hooks

Suggestie Waarom hier
git push naar main blokkeren (PreToolUse op Bash) "Nooit direct pushen naar main" staat in CLAUDE.md en wordt lokaal door niets afgedwongen. Onomkeerbaar als het misgaat, en triviaal te vangen
Bash-scripts testen bij edit (PostToolUse) .github/scripts/ heeft acht test-*.sh-suites die CI via ci-scripts.yml draait. Puur bash, klaar in seconden — directe feedback waar Maven dat niet kan zijn
Bruno-herinnering bij spec-edit (PostToolUse) "Nieuwe endpoints krijgen direct een .bru-request" is precies het soort regel dat je vergeet, en die pas opvalt als de collectie is doodgebloed
Spaties in bestandsnamen blokkeren (PreToolUse) De kebab-case/snake_case-conventie bestaat zodat shellscripts en CI zonder quoting werken. Eén regel code, voorkomt een hele klasse fouten
Poort 8081 checken bij sessiestart (SessionStart) Draait de demo-stack, dan faalt élke @QuarkusTest op "Failed to start quarkus" — een melding die de oorzaak niet noemt. Eén ss -ltn bespaart dat debug-rondje

Subagents

Suggestie Waarom hier
kotlin-stijl-reviewer De regels over lege regels rond multi-line blokken en zelfstandige control-statements beslaan zestig regels CLAUDE.md mét voorbeelden. detekt controleert er niets van
migratie-reviewer Surrogate PK, FK op de surrogate en niet op de business-key, RESTRICT tenzij opzettelijk, geen @Lob byte[] op PostgreSQL, rollback-script aanwezig, test-cleanup child-first. Zes conventies die stuk voor stuk pas laat pijn doen
ci-workflow-reviewer De valkuilen zijn hier hard geleerd: impliciete success() kijkt door needs-van-needs heen en sloeg de deploy stil over, image-tags moeten uniek per commit, project-ids staan op twee plekken. Generieke Actions-kennis vangt dat niet
openapi-adr-reviewer Spectral dekt de ADR-ruleset, niet de eigen invarianten: geen BSN in de spec, HAL _links, API-Version, en of het foutcontract echt in de OpenApiContractTest staat
test-dekkings-reviewer De teststrategie is expliciet over inputvariatie (bij collecties altijd 0, 1 én n) en over de val dat alleen @QuarkusTest-coverage meetelt voor de 90%-gate

Skills

Suggestie Waarom hier
/nieuw-issue De meest foutgevoelige prose-regel die we hebben: issues in een ándere repo, exact drie labels, functionele niet-technische titel, en koppelen aan de juiste groep-issue via GraphQL omdat gh daar geen commando voor heeft
/nieuwe-migratie Scaffoldt V(N+1) plus het rollback-script ernaast, met de JPA-conventies erbij. Sluit aan op de guard uit deze PR: blokkeren is pas nuttig als het juiste pad makkelijk is
/zad-debug Dwingt de volgorde af die de gids voorschrijft: eerst tag en replicas in het gerenderde manifest, dán pas de UI-fouttekst geloven. Precies andersom als je op de melding afgaat
/demo-starten podman-preparepodman-upsmoke, met de valkuilen die niet in de scripts staan: hostnet bindt loopback, en een kale 400 is Host-validatie en geen netwerkfout
/warnings-triage Vergelijkt build-output met de drie bewust geaccepteerde warnings, zodat "nieuw en onverklaard" zichtbaar wordt in plaats van te verdrinken

MCP-servers

Suggestie Waarom hier
context7 Live docs voor Quarkus 3.39, Kotlin 2.4 en Hibernate 6. Deze pom heeft fijnmazige BOM-pinning (jackson vóór de Quarkus-BOM, json-schema-validator op 2.0.7) waar versiegedrag echt uitmaakt
Playwright Er is UI: demo-console en de proeftuin-berichtenbox. Demo-gedrag wordt nu met de hand geverifieerd; klikpaden en screenshots zijn precies wat een runbook niet kan garanderen
PostgreSQL MCP Read-only tegen de lokale dev-database om flyway_schema_history en magazijn-data te inspecteren tijdens demo-debugging, zonder docker compose exec psql-gedoe

Plugins

Suggestie Waarom hier
pr-review-toolkit Al beschikbaar. Let op: die agents bewerken en stashen in je werkboom — eis read-only of laat ze in een /tmp-kopie werken
hookify Helpt de resterende prose-regels uit CLAUDE.md omzetten naar hooks, nu het patroon staat
Eigen plugin van deze .claude/-set moza-poc, moza-fsc-testnet en deze repo delen conventies (NL/EN-grens, PII-regels, ZAD-deploy). Wil je deze agents en skills in meer dan één repo, dan is bundelen goedkoper dan kopiëren

Hoort hier een issue bij in MinBZK/MijnOverheidZakelijk, zeg het dan — die maak ik niet uit
mezelf aan.

🤖 Generated with Claude Code

https://claude.ai/code/session_012EtTFzuvUinGmBM2ZRs71v

@ericwout-overheid ericwout-overheid left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ready for review.

Comment hierboven kan (selectief) eventueel ook meegepakt, of een issue voor gemaakt. Overlegpuntje denk ik.

@ericwout-overheid
ericwout-overheid marked this pull request as ready for review September 7, 2026 06:39
De ZAD-gids beschreef nog dat een reconcile een door OM uitgeschakeld
component niet reactiveert, en dat de deployment herscheppen de enige
werkende fix is. Dat klopt sinds RC-37 (2026-08-06) niet meer, en het is
een dure fout: het stuurt naar een DELETE die voor projecten met de
postgresql-database-service de databasegegevens wist.

Een rollout heft de uitschakeling nu op. Twee mechanismen, met
verschillende reikwijdte: update-image en een upsert van een bestaande
deployment lopen over ActionEvent.REDEPLOY en wissen elke uitschakeling
ongeacht de reden, ook met een ongewijzigde tag; een door een mens
gestarte (her)verwerking heft via de disabled-image-sweep alleen een
image-pull-uitschakeling op. Herscheppen blijft staan als het zware
alternatief voor wanneer de uitschakeling meteen terugkomt.

Geverifieerd op mpfm-w3h/pr-288/democonsole, dat uitstond door een
transiënte timeout op de pull-through-mirror: update-image met dezelfde
tag zette het component weer aan, zonder dataverlies.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JFxVFC2NDRtW5HqbpX4nXY
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant