Gå til innhold

ADR-016: Vedlikeholdt read-only replika av ERS/masterdata⚓︎

Kai bygger én vedlikeholdt, read-only projeksjon av ERS/masterdata, oppdatert av én daglig synk-jobb (eneste skriver) etter Mimir-ETL-en. Synken erstatter lazy per-sak-materialisering og statusfiltrert discovery-polling; «hvilke saker som skal kjøres» blir et eget seleksjonssteg.

Kontekst⚓︎

Dagens Sak er en tynn stopgap (5 ERS-skalarer, hentet lazy via EnsureCaseAdapter; discovery via statusfiltrert Mimir-poll i ErsDiscoveryJob). For å hjelpe saksbehandleren mellom ERS-status 0 og 3 trengs prosjekt, søker, beløp og resultater — ikke bare status + ID-er.

Kilden er døgn-statisk: ERS dumpes daglig → Mimir bygger production.gold.* hver morgen, og gull er immutabelt resten av dagen (kildesystemer). Da jakter intra-dag-polling, discovery og lazy-materialisering på endringer som ikke finnes før neste morgen.

Beslutning⚓︎

  • Vedlikeholdt replika. Sak, VirkemiddelMasterdata og Vurdering er read-only projeksjoner i Kais Postgres. Norsk domenespråk (ADR-015); ACL vokter ERS' tekniske skjema, ikke vokabularet.
  • Én daglig SyncJob = eneste skriver. Kjører etter ETL, freshness-guardet: leser gulls dump-dato, hopper + varsler hvis ikke nyere enn forrige synk. Bulk-upsert; ingen annen kode skriver replikaen. Erstatter ErsDiscoveryJob + EnsureCaseAdapter (begge fjernes).
  • Seleksjon er eget steg. En SelectionJob leser replikaen (Postgres, ikke Mimir), filtrerer Kai-aktive virkemidler + RUN-statuser + søknadsdato, og enqueuer pipeline-arbeid. Domenepolicy, skilt fra all-status-replikaen.
  • Additiv mot virkemiddel-registeret. virkemidler-tabellen (#20975) er urørt — fortsatt FK-mål + autoritativ for Kai-navn/Kai-aktiv. VirkemiddelMasterdata er en ny replika nøklet på samme virkemiddel_id med kun masterdata (+ Enova-aktiv, et eget begrep fra Kai-aktiv).
  • Behovsstyrt projeksjon, ikke konsument-gating. Felt tas inn fordi saksbehandleren vil ha det; regler konsumerer Fakta (Runde 3). Settet vokser via skjema-versjon-disiplin.

Ikke-mål⚓︎

  • Replikert fakta-ekstraktor + pipeline-rewiring (Runde 3).
  • Kolonne-nivå «frys vs. fersk» (ikke-problem: immutable re-synkes som no-op).
  • Status-basert avgrensning av replikaen (all-status; status filtreres kun i seleksjonen).
  • Å oversette alle ~50 ERS-kolonner.

Konsekvenser⚓︎

  • Kilden treffes én gang i døgnet, deterministisk; Sak blir rik og ferdig-materialisert (ingen fetch-latens per forespørsel).
  • Replika og seleksjon er frikoblet: seleksjon kan re-kjøres uten re-synk; hoppet synk → seleksjon er trygg no-op (processed-store dedup).
  • Pris: replikaen må følge ERS-skjemaendringer (skjema-versjon), + en synk-jobb m/ freshness-guard å drifte.
  • Forkastet: intra-dag-polling/lazy-materialisering (ikke-eksisterende intra-dag-endringer); berike virkemidler in-place (blandet skriver, reverserer #20975-designbeslutning 1); streng konsument-gating (ville avvist nesten hele Runde 2-projeksjonen).

Verifisering⚓︎

  • [ ] Arkitekturtest: ingen ERS-skjemanavn i Domain; Databricks kun i Infrastructure.
  • [ ] ErsDiscoveryJob + EnsureCaseAdapter fjernet; SyncJob (freshness-guardet) + SelectionJob på plass.
  • [ ] virkemidler urørt; VirkemiddelMasterdata additiv.
  • [ ] dotnet build Kai.slnx grønt.

Bygger på ADR-015 og kildesystemer; forutsetter #20975. Design: docs/superpowers/specs/2026-06-30-ers-masterdata-replika-berikelse-design.md.