Skip to content

Bitemporal model voor dso_artikel

Onder de pointer-method-architectuur wijst canonical.instrument_versions.content_refs naar de bron-specifieke article-store. Voor DSO is dat canonical.dso_artikel. Maar dso_artikel zelf moet bitemporal-append-only zijn — anders breekt de invariant dat een instrument-versie wijst naar onveranderlijke article-tekst. ADR-0027 lost dat op.

Het probleem

OzonSyncService.ts:337-340 gebruikt:

sql
INSERT INTO canonical.dso_artikel (...)
VALUES (...)
ON CONFLICT (regeling_id, w_id) DO UPDATE SET
  inhoud = EXCLUDED.inhoud,
  ...

Bij elke sync wordt inhoud overschreven. Article-tekst-historie gaat verloren. Als instrument-versie X wijst naar dso_artikel(regeling_id, w_id), en versie Y wijzigt dat artikel, dan wijst de oude pointer ineens naar de nieuwe tekst — historisch klopt het niet meer.

De vier temporal-kolommen

ADR-0027 introduceert het bitemporal-model voor dso_artikel:

KolomWat het zegt
valid_fromWanneer de juridische geldigheid van dit artikel-versie begint (bekendmakings-datum)
valid_toWanneer de geldigheid eindigt (volgende versie's valid_from, of NULL voor de huidige versie)
transaction_fromWanneer wij deze rij hebben geregistreerd
transaction_toWanneer wij deze rij hebben gecorrigeerd / vervangen (NULL voor de actuele)

Twee tijdsassen:

  • Valid time — wanneer geldt het artikel volgens de wet?
  • Transaction time — wanneer wist Databank het?

Bitemporal beantwoordt vragen als "wat was volgens onze gegevens op datum X de wettelijke werkelijkheid op datum Y?" — onmisbaar voor historische BOPA-toetsingen en juridische audit-trails.

Append-only

Bij een nieuwe voorkomen van een regeling:

  1. Voor artikelen waarvan inhoud is gewijzigd: nieuwe rij met valid_from = voorkomen.beginInwerking en transaction_from = now(). De oude rij krijgt valid_to = voorkomen.beginInwerking en transaction_to blijft NULL.
  2. Voor artikelen waarvan inhoud ongewijzigd is: geen nieuwe rij — de bestaande rij blijft staan, valid_to wordt verlengd naar het volgende voorkomen.

Geen UPDATEs op inhoud. Ooit. De ON CONFLICT DO UPDATE SET inhoud constructie wordt vervangen door fingerprint-detectie + conditional-INSERT.

De active_in_force matview

Consumers willen meestal "de huidige geldige versie", niet bitemporal-predicaten in hun queries. ADR-0027 specificeert een matview active_in_force die dso_artikel filtert op valid_to IS NULL AND transaction_to IS NULL. Voor 95% van de read-queries hoeft de complexity van bitemporal niet door te lekken.

Waarom dit gating-werk is

Zonder ADR-0027 kan WI-FRBR-011 (DSO instrument-canary, het projecteren van DSO naar FRBR) niet veilig landen. De instrument_versions.content_refs pointer zou wijzen naar een artikel-rij waarvan de inhoud op elk moment kan worden overschreven. Phase 0a van ADR-0032 (de migration-plan) sequenceert ADR-0027 expliciet vóór WI-FRBR-011.

Open punten

  • IMOW-satelliet temporaliteit — ADR-0027 v1 maakt alleen dso_artikel bitemporal. De IMOW-tabellen (dso_regelvooriedereen, dso_activiteit, dso_locatie, etc.) blijven current-snapshot. Open: of wijzigingen waarin een artikel-activiteit-binding wijzigt ook historie nodig hebben.
  • Performance bij grote her-syncs — bij ~1.000-4.000 artikelen per regeling en duizenden regelingen vergt fingerprint-detectie miljoenen vergelijkingen per full-resync. Voorzien: eerst voorkomen-tijdstipRegistratie vergelijken (cheap filter), pas fingerprint als die is doorgegroeid.
  • Schema-misnoemer: dso_artikel.regeling_id is TEXT en houdt een AKN-URI, niet een numerieke FK naar dso_regeling.id. Hernoemen naar regeling_identificatie in dezelfde migratie die bitemporal-kolommen toevoegt.

Onderliggende ADRs en docs

  • ADR-0027 — bitemporal dso_artikel (nog niet geshipped — issue #4158)
  • ADR-0032 — strangler-fig migration plan (sequenceert ADR-0027 vóór WI-FRBR-011)
  • docs/handoffs/2026-05-05-architecture-audit.md §6 — ON CONFLICT DO UPDATE als wrong-turn
  • docs/handoffs/2026-05-05-dso-ozon-problem-statement.md — volledige design-context met gm1721-voorbeeld

Intern handboek — niet voor externe publicatie