Van database naar betrouwbaar register
Een gemeente ontdekt dat een WOZ-waarde jarenlang fout is vastgesteld. De oppervlakte van een woning is destijds verkeerd ingevoerd en daarmee viel ook de waarde te hoog uit. De medewerker corrigeert de fout: hij opent het systeem, past de waarde aan en slaat op. De database bevat nu de juiste waarde.
Toch is er een probleem. De foutieve waarde is jaren verstrekt – aan de eigenaar, aan de belastingdienst, aan een notaris bij een eigendomsoverdracht. Op die foutieve waarde is OZB berekend, een bezwaarschrift ingediend en een koopprijs gebaseerd. Allemaal rechtshandelingen die steunen op wat het register destijds verstrekte. Nu die waarde is overschreven, is het bewijs weg. Een bezwaarcommissie die wil weten wat het register op het moment van bezwaar verstrekte, krijgt geen antwoord.
Dat is geen ongelukkig detail, maar een gevolg van een ontwerpkeuze: een systeem dat informatie bijhoudt als actuele stand, kan achteraf niet meer verantwoorden wat het eerder wist. Dit verhaal bouwt, stap voor stap, de architectuur op die dat probleem structureel oplost – de architectuur die de handreiking betrouwbare registers beschrijft. Elke stap ligt op zichzelf voor de hand, maar samen laten ze zien waarom een betrouwbaar register op cruciale punten verder gaat dan een database met een interface. Onderweg linken we door naar de hoofdstukken van de handreiking waar elk onderwerp in detail staat, en komen de aannames die een database-achtergrond meebrengt vanzelf aan bod – van "een register is toch een database?" tot "historie bewaar ik toch in een logtabel?".
Een register is meer dan een database
Het startpunt is het meest gangbare beeld van een register: een database, met daaromheen een schil die verwerkt (process) en publiceert (publish). De database is het hart; de schil eromheen is grotendeels techniek. Dat beeld werkt voor systemen die alleen hoeven te vertellen wat er nu geldt.
De eerste stap in de handreiking is bescheiden: vóór het register komt een aparte stap Capture. Verzoeken, meldingen, notificaties en berichten van andere bronnen worden eerst erkend en vastgehouden als wat ze zijn – input van buiten – voordat ze het register binnengaan als commando. Dat lijkt een detail, maar het is het eerste teken dat een register meer doet dan opslaan: het houdt bij wát er is binnengekomen, niet alleen wat daarvan uiteindelijk is verwerkt. Wat een register wel en niet is, staat beschreven in hoofdstuk 2 (definitie en scope).
Commando's zijn geen CRUD
Zodra Capture eenmaal instroom onderscheidt van verwerking, dringt een vraag zich op: wat ís een commando dan precies? Het meest voor de hand liggende antwoord – een CRUD-operatie, eventueel met een paar bitemporele velden erbij – blijkt bij nader inzien niet te voldoen.
Een commando is een businessfunctie: het drukt uit wát er in de werkelijkheid is gebeurd of vastgesteld – een verhuizing, een adoptie, een correctie – niet hoe een rij in een tabel verandert. Dat onderscheid lijkt semantisch, maar is architectonisch: een CRUD-operatie beschrijft een mutatie op de huidige stand, een businessfunctie beschrijft een gevolg met een eigen betekenis, ongeacht wat de huidige stand toevallig is.
Maar een businessfunctie die alleen een gevolg optekent, is nog niet compleet. De volgende stap voegt een link toe tussen het verwerken van het commando en wat er wordt opgeslagen: context die het "waarom" vasthoudt, niet alleen het "wat". Die link is de kiem van twee dingen die verderop in dit verhaal terugkomen: herkomst (waarom is dit vastgesteld, door wie, op basis waarvan) en bitemporaliteit (wanneer gold dit, los van wanneer het is vastgelegd).
Historie is meer dan een logtabel
Deze stap toont wat er gebeurt als je die link serieus neemt: de historie van het woonadres van persoon p5 wordt niet bijgehouden als één rij die wordt overschreven, maar als een raster van systeemtijdstip tegen geldigheidstijdstip. Elk event (e1 t/m e18 – gevonden, verhuisd, geadopteerd, opnieuw verhuisd, emigratie, gecorrigeerd) opent of sluit een balk (a1 t/m a6) in dat raster.
Dat raster beantwoordt een vraag die een logtabel niet kan beantwoorden. Een logtabel legt vast wanneer de registratie veranderde – systeemtijdstip. Maar een overheidsregister moet ook kunnen zeggen wat er geldig was in de werkelijkheid op een moment in het verleden, naar de kennis van dát moment. Kijk naar e18 (corrected): die corrigeert met terugwerkende kracht wat het register over een eerdere periode stelde, zonder dat de oorspronkelijke balken (a1 t/m a4) verdwijnen. De foutieve periode blijft zichtbaar – als gecorrigeerd gemarkeerd, niet gewist. Dat is precies wat in de WOZ-anekdote aan het begin ontbrak. Meer over deze twee tijdsassen: hoofdstuk 6 (conceptueel registermodel) en de verdieping temporaliteit in projecties.
Van gebeuren naar gevolg
Om het raster uit de vorige stap daadwerkelijk te kunnen vullen, splitst de Store zich: naast de vertrouwde Database komt een append-only journaal, hier Effects genoemd. Voor wie uit event sourcing komt: een effect is wat daar een event heet. In de handreiking heet dit journaal het gevolgenjournaal, en wat erin komt is een gevolg: niet zomaar een feit in een applicatiemodel, maar iets wat het register vaststelt en waarop het aanspreekbaar is.
Deze stap trekt de lijn door: alles wat bij Capture binnenkomt, "bezinkt" uiteindelijk in het effect (de gele pijl onderaan, settles in effect) – niet alleen het resultaat van de verwerking, maar ook de herkomst ervan. Dat is het verschil tussen een effect en een gewone event-sourcing-event: het effect draagt de herkomst met zich mee, niet als bijzaak maar als kern van de vastlegging. Meer over het gevolgenjournaal: hoofdstuk 8 (verdieping gevolgenjournaal).
De bitemporele opslag herzien
Het raster is hetzelfde als zonet, met één verschil: de bitemporele historie van p5's adres wordt nu gevoed vanuit Effects, niet vanuit een direct gemuteerde Database. Dat is geen cosmetische wijziging. Zolang elke wijziging als apart gevolg in het journaal staat, is het raster reconstrueerbaar – ook achteraf, ook na een correctie. Een database die je overschrijft, kan dat niet bieden.
Bijhouden en leveren als aparte verantwoordelijkheden
De Database uit de vorige stappen is hier volledig vervangen. In plaats daarvan levert Effects, via een project-stap, meerdere projecties – elk toegesneden op een ander doel of een andere afnemer. Publish bevraagt niet langer één centrale tabel, maar één van deze projecties. Dat is de scheiding die de handreiking bijhouding en verstrekking noemt: bijhouden (vastleggen wat er gebeurd is, in het gevolgenjournaal) en leveren (informatieproducten samenstellen voor afnemers, via projecties) zijn twee verschillende verantwoordelijkheden met elk hun eigen model.
Zo herschikt, valt het register in vier heldere verantwoordelijkheden uiteen: binnenhalen (Capture), verwerken tot een gevolg (Process), vastleggen (hier Account genoemd – het gevolgenjournaal) en leveren (Publish, via projecties). Geen van deze stappen is meer "de database met wat techniek eromheen" – elke stap heeft een eigen taak en een eigen verantwoording. Meer over deze scheiding: hoofdstuk 5 (datalaag) en hoofdstuk 9 (verdieping projecties). De technische uitwerking van de bitemporele opslag van payloads in projecties staat in de verdieping over de bitemporele payloadstore.
Herkomst, twijfel en de volledige keten
Deze stap trekt de link van zonet helemaal door. Een commando komt niet uit het niets: het volgt uit een zaak (case), die op zijn beurt is gevoed door documenten, een notificatie, een formulier of een certificaat, en die wordt getoetst aan wet en beleid door een verantwoordelijke verwerker. Elke schakel in die keten – wet & beleid, workflow, verwerker – is zelf een vastgelegd, verifieerbaar gegeven (de validatie-iconen hiernaast). Dat is precies de herkomst die de handreiking vraagt: niet alleen wát is vastgesteld, maar ook op basis waarvan, door wie, en volgens welke werkwijze. Zie hoofdstuk 9, paragraaf Herkomst.
De laatste stap laat zien wat er gebeurt als iemand twijfelt aan wat het register verstrekt. Een terugmelding doorloopt dezelfde Capture-route als elk ander bericht (1), leidt tot een onderzoek, en dat onderzoek raakt zowel de betrokken projectie (2, zodat afnemers de twijfel kunnen zien) als het gevolgenjournaal (3, ter onderbouwing) – om uiteindelijk, als het onderzoek daartoe aanleiding geeft, een nieuw commando te worden (4): een correctie. Geen van deze stappen overschrijft iets; elke stap voegt een nieuw, herleidbaar gevolg toe. Dat geldt net zo goed voor onttrekking: een gegeven intrekken is geen DELETE, maar een vastlegging dat het met ingang van een bepaald tijdstip niet meer geldig is. Dit is dezelfde volgorde – terugmelden, onderzoeken, corrigeren – als in hoofdstuk 7 (verdieping registerbreed) en de verdieping correctie van gevolgen.
Zolang dat onderzoek loopt, kan het register niet zeggen dat het gegeven klopt – maar ook niet dat het fout is. Die tussenpositie is precies wat de projectie in stap (2) laat zien: een gegeven kan onderschreven zijn, in onderzoek zijn of betwist zijn, en die zekerheid is expliciet onderdeel van wat wordt geleverd. Een afnemer die weet dat iets in onderzoek is, kan daar rekening mee houden – en kan niet later beweren dat hij de twijfel niet kende. Dat vereist epistemische nederigheid: de erkenning dat kennis over de werkelijkheid beperkt, voorlopig en mogelijk onjuist is, verwerkt als architectuurprincipe in plaats van als uitzondering. Zie hoofdstuk 1 (aanleiding en doel).
Aanbevolen leesroute
Begin met hoofdstuk 1 (aanleiding en doel) voor het waarom en de context. Lees daarna hoofdstuk 2 (definitie en scope) voor de definitie van een capabel register. Hoofdstuk 6 (conceptueel registermodel) beschrijft de kern van de architectuur, inclusief tijdsdimensies en correcties. Hoofdstuk 9 (verdieping projecties) gaat dieper in op herkomst en de herhaalbare vraag.
De casus WOZ laat zien hoe correcties en betwijfeling in een capabel register worden verwerkt, inclusief de bitemporele tijdlijn. De casus BRP toont de rijkdom van gevolgen aan de hand van adoptie, huwelijk en correcties in een persoonsregistratie: een huwelijk is event-achtig, kiesrecht is state-achtig, en toch volgen beide hetzelfde architectuurvraagstuk over betrouwbare herkomst.