ADR-022: ERS-status velger regelsett, tilsagnet avgrenser dokumentpakken⚓︎
ERS-status velger regelsettet, som i dag: 0/1 gir søknadsreglene, 5 gir sluttrapporteringsreglene når en sluttrapport finnes. Tilsagnet — Enovas utgående tilskuddsbrev, journalpostkategori
TIi Websak — avgrenser hvilke dokumenter regelsettet kjøres på: søknadsreglene får det søker sendte inn før tilsagnet, sluttrapporteringsreglene det som kom inn fra tilsagnet. En ny sak har ikke tilsagn, og søknadsreglene kjøres straks på alt søker har sendt inn. Det er ett dokumentutvalg per regelsett, uavhengig av om kjøringen er automatisk, manuell eller utløst av en beslutning; utvalget skjer ved henting. Reekstraksjon er alltid manuell.
Kontekst⚓︎
Kai velger i dag regler og dokumenter slik (verifisert på origin/main 15.09.2026):
- Regelsett = ERS-status per regel. 89 regel-YAML-er under
src/Enova.Kai.Application/Rules/deklarererers_statuser— 24 med[0, 1](søknad), 44 med[5](oppfølging), 21 med[0, 1, 5].WorkflowGraphRunner.AppliesTohopper over regler der sakens status ikke står iRegel.ApplicableErsStatuses. Ved manuell kjøring velger en administrator hvilken ERS-status saken kjøres som. - Stadium = ERS-status.
ErsStatuspolicy.StadiumFor(0/1 →Søknad, 5 →Gjennomføring, øvrige →Annet). Beslutninger slås opp per stadium-slug iRunCaseWorkflowHandler. - Dokumenter = alt inngående.
WebsakDocumentLister.ListAndStoreOriginalsAsynctar alle inngående journalposter minus fire standarddokumenter, dedupliserer på (journalpost, filnavn), og alt CU-ekstraheres. - En sak kjøres én gang.
polling_processed_caseshar unik nøkkel(Saksnummer, Step); en sak vurdert i søknadsfasen kommer aldri tilbake (#22130). - Ny analyzer gir ny CU-kjøring.
FetchDocumentsJobbruker alltid nyeste analyzer-id fraanalyzers.lock.json, ogFactsExistsAsyncnøkler på analyzer-id — en lagret analyse med eldre id regnes som manglende.
Det gir tre problemer:
- ERS-status sier ikke hvilke dokumenter som hører til hva. En sak i status 5 har både søknadsdokumenter, delrapporter, dialog og (etter hvert) sluttrapport i samme arkivsak. Kjøringen blander dem — den opprinnelige feilen i #21742 («sak i status 5 kjøres med sluttrapporteringsregler, finner ikke energiattest, gjør rare ting med fakturaene»). Det samme skjer når søknadsreglene kjøres manuelt på en sak som har gått videre i ERS: de får med alt søker har sendt inn etter tilsagnet.
- Tavlenotatene fra 24.08.2026 foreslo fire utvalg (regelsett × batch/manuell). Koden kjører
allerede manuelt uten ny dokumentasjon (beslutning-fan-out i
ReevalueringOutbox, reanalyse), så en beslutning ville fått et annet dokumentgrunnlag enn kjøringen den overstyrer. - Når saker slipper inn i utvalget igjen (#22126), vil en deployet analyzer automatisk reekstrahere alle tidligere analyserte dokumenter — ukontrollert CU-kost og et grunnlag som endrer seg uten at noen har bedt om det.
Verifisert i Websak test (14.–15.09.2026, se docs/architecture/websak-soknadsdata-xml.md):
- Hver innvilget sak har nøyaktig én
TI-journalpost (tilskuddsbrevet,U). 17 av 17 hentede saker i status 5 hadde den; 0 av 9 i status 0/1. Kartleggingsstøtte til borettslag og boligsameier ga 403 og er ikke verifisert. - Journalpostnummeret (år/løpenummer) er monotont med
Journaldatopå 46 journalposter; datoen mangler klokkeslett. - Sluttrapporten er
I/ kategoriE/ «Sluttrapport» i tittelen (24 avsluttede saker). Enovas påminnelser inneholder også ordet, men erU/ISS. - Energiattesten kom i en egen journalpost etter sluttrapporten på én av sakene (23/55515), og godkjenningen ventet på den.
Beslutningsdrivere⚓︎
- En ny sak skal vurderes straks, uten å vente på noe i arkivet.
- Regelsettet skal kjøre på dokumentene det faktisk skal vurdere — ikke på alt i arkivsaken.
- Samme sak, samme regelsett og samme arkivtilstand skal gi samme dokumentpakke, uansett hvordan kjøringen startet.
- CU-kost skal bare påløpe for dokumenter som skal vurderes, og aldri for reanalyse ingen har bedt om.
- Skillet skal være maskinlesbart og konsekvent i arkivet på tvers av virkemidler.
Alternativer⚓︎
| Alternativ | Hvorfor forkastet |
|---|---|
| A. Alt som i dag — ERS-status velger regelsett, alle inngående dokumenter | Regelsettet er riktig, men dokumentene er ikke: sluttrapporteringsreglene ser søknadsdokumentene, og en manuell søknadskjøring ser alt som kom etter tilsagnet. |
| B. Tavlas 2×2 — utvalg per regelsett × utløser (batch/manuell) | En beslutning eller reanalyse ville fått et annet grunnlag enn kjøringen den gjelder. Å modellere årsak i stedet for utløser fjerner symptomet, men ikke behovet: pakken kan bestemmes av regelsettet og arkivet. |
| C. Det interne vedtaket som grense | Vedtaket (X-journalpost) kategoriseres ikke konsekvent av saksbehandlerne; mellom vedtak og tilsagn gikk det 0–1 dag på de verifiserte sakene. |
| D. Utvalg ved evaluering (alt ekstraheres, regelmotoren filtrerer) | CU betales for dokumenter ingen pakke skal ha. |
| E. Automatisk reekstraksjon ved ny analyzer eller ny dokumentversjon | Ukontrollert kost og et grunnlag som endrer seg uten at saksbehandleren ser hvorfor. |
| F. Tilsagnet avgjør også regelsett og stadium (første utkast av denne ADR-en) | Fagansvarlig (PR 25510): søknadsreglene skal kjøres når saken kommer inn, uten krav om TI, og TI er bare aktuell for å begrense dokumentene. I tillegg ville alle 89 regelversjoner blitt bumpet, stadium måtte vises som ukjent til grensen var registrert, og nye saker ville ventet på en arkivsjekk. |
| G. ERS-status velger regelsett, tilsagnet avgrenser dokumentpakken, manuell reekstraksjon | Valgt. |
Beslutning⚓︎
1. ERS-status velger regelsett og stadium — som i dag⚓︎
- 0/1: søknadsreglene kjøres. En ny sak kjøres straks; det krever ingen
TI-journalpost. - 5: saken kan ha en sluttrapport. Kai sjekker arkivet; sluttrapporteringsreglene kjøres bare når en sluttrapport finnes og Enova ikke allerede har godkjent den.
- Manuell kjøring: administratoren velger fortsatt hvilken ERS-status saken kjøres som, og dermed regelsettet.
ErsStatuspolicy.KvalifiserendeStatuser([0, 1, 5]),ers_statuseri regel-YAML-ene ogErsStatuspolicy.StadiumForbeholdes.- Beslutninger gjelder per stadium, som i dag, og overlever at søker ettersender dokumenter.
- Avviste saker analyseres ikke. Utplukkingen (0/1 og 5) forutsettes å holde dem ute; hvilken ERS-status en avvist sak har, er ikke verifisert.
2. Tilsagnet avgrenser dokumentpakken⚓︎
- Grensen er journalposten med kategori
TI. UtenTIer søknadsprosessen ikke avsluttet, og alt søker har sendt inn hører til søknaden. - Rekkefølge avgjøres av journalpostnummeret (år/løpenummer), aldri av
Brevdato. - Regelsettet avgjør pakken, grensen avgjør innholdet. Søknadsreglene får søknadspakken, sluttrapporteringsreglene får sluttrapportpakken.
- Grensen betyr i praksis mest når søknadsreglene kjøres manuelt på en sak som har gått videre i ERS: da begrenser den dokumentene til det søker sendte inn før tilsagnet.
- En sak i status 5 uten tilsagn får ingen sluttrapportkjøring (sluttrapportpakken har ingen startgrense), men registreres som forsøkt-men-ikke-kjørt med merknad om at tilsagnet mangler (tidslinjen i #21736).
3. Ett dokumentutvalg per regelsett⚓︎
| Dokumentpakke | Innhold | Aldri med |
|---|---|---|
| Søknadspakken | Inngående journalposter før tilsagnet; uten tilsagn alle inngående | Standarddokumenter, e-postkroppen i dialog (vedleggene er med), alt etter tilsagnet (også søknad om utvidet prosjektperiode), tilskuddsbrev, signert retur og signert endring av tilskuddsmottaker |
| Sluttrapportpakken | Inngående journalposter fra tilsagnet til og med sluttrapporten (I / E / «Sluttrapport … ISSR‹n›»), pluss det som kommer inn fram til godkjenningsbrevet for nyeste sluttrapport («Informasjon til søker om godkjent rapport: ISSR‹n›», samme ISSR-nummer) eller avslutningsbrevet (U / ERS «Avslutningbrev»). En ny sluttrapport etter grensen åpner pakken igjen |
Søknadsdokumenter, delrapporter, søknad om utvidet prosjektperiode, signert retur, signert endring av tilskuddsmottaker, e-postkroppen i dialog (vedleggene er med) |
- Filterlisten er subtraktiv, og dialogfilteret virker på dokumentnivå: e-postkroppen
(
.docxpå produksjonsvarianten) utelates, vedleggene beholdes. 9 av 26 dialog-journalposter i arkivsveipet 18.09.2026 bar ekte ettersendt dokumentasjon. Spec2026-09-18-filterliste-dokumentutvalg-design.md. - Godkjenningsbrevet har samme tittel for delrapporter og sluttrapporter, og bærer rapportens
« - n»-suffiks. ISSR-nummeret må derfor stemme med nyeste sluttrapport; en delrapport godkjent
før sluttrapporten stenger ikke pakken (23/58805). Eldre saker lukkes med avslutningsbrev uten
godkjenningsbrev (23/35655). Spec
2026-09-17-sluttrapportpakke-ovre-grense-design.md. - Pakken er den samme enten kjøringen er automatisk, manuell eller utløst av en beslutning.
- Lik MD5 (
Checksumfra Websak) på søkers original — den eldste versjonen, ikke arkivets A-PDF, som får ny sjekksum ved hver konvertering: én kopi. Lik dokumenttittel og likt originalt filnavn i en senere journalpost med ulik MD5: nyeste journalpost gjelder. Tittel alene holder ikke — portalen kaller mange ulike rapporter «rapport» (spec2026-09-16-soknadspakke-versjonsvalg-design.md, F1 og F3). Flere sluttrapporter (også med ulike ISSR-numre) er én pakke. Uten kjent original gjelder ingen av reglene, og innenfor én journalpost gjelder bare lik MD5. - Delrapporter vurderes ikke inntil videre.
- Utvalget skjer ved henting. Bare dokumentene i pakken hentes og ekstraheres.
- Nytt dokument i en åpen pakke (søknad før tilsagnet, sluttrapport før godkjennings- eller avslutningsbrevet) hentes, ekstraheres automatisk, og regelsettet kjøres automatisk på nytt.
- Godkjent nyeste sluttrapport eller avslutningsbrev: pakken er lukket, ingen kjøring. En ny sluttrapport etter dette åpner pakken igjen. Gjelder også saker som står i status 5 i dag — det blir ingen egen tilbakekjøring.
4. Reekstraksjon er alltid manuell⚓︎
- Et dokument som allerede er analysert, analyseres aldri automatisk på nytt — heller ikke ved en nyere versjon (lik tittel og originalt filnavn i en senere journalpost, ulik MD5 på originalen) eller en ny analyzer/kategoriserer i lockfilen.
- Til det skjer, vurderes den analyserte versjonen, og saksbehandleren varsles i saksbildet (#22217).
- Saksbehandleren starter reekstraksjonen. Den gjelder bare de berørte dokumentene og bruker alltid nyeste analyzer; regelsettet kjøres på nytt etterpå.
- Alt som analyseres — automatisk eller manuelt — analyseres med nyeste analyzer. En pakke kan derfor midlertidig ha dokumenter analysert med ulike analyzer-versjoner.
- Ikke reekstraksjon: førstegangsanalyse av et dokument Kai aldri har sett, og fullføring av en
analyse som ble avbrutt (
PipelineReconciliationJobfase 1).
Løst spørsmål⚓︎
Sluttrapporteringsregler som leser søknadsdokumentet (sju regler med ers_statuser: [5], funnet i
PR 25523). Løst i #22127: en regel deklarerer hvilken dokumentpakke den leser (dokumentpakke:
søknad | sluttrapport | begge), hentingen henter unionen av pakkene regelsettet deklarerer, og hver
regel evalueres mot fakta fra sin pakke. Se spec 2026-09-21-dokumentpakke-per-regel-design.md.
Ikke-mål⚓︎
- Delrapporter — ingen regelkjøring og intet regelsett nå.
- Hvor ofte saker sjekkes for ettersendinger og sluttrapport. I test står 4 181 saker i status 5, hvorav 78 % har sluttdato mer enn 90 dager fram. Avgjøres separat når det er kjent om sluttrapporter kommer før sluttdatoen. Løst i #22126: alle åpne pakker sjekkes daglig i starten (standup 24.09.2026) — konfigurerbart under Kai:SakSeleksjon:Pakkesjekk, der sluttrapportpakker langt fra sluttdato kan settes til ukentlig hvis trafikken må ned.
- Dagens reanalyse-dialog for administratorer (
POST /cases:reanalyze, alltidtvingReekstraksjon: true, stadium → representativ ERS-status). Utsatt. - Å endre hvordan regelsett eller stadium velges — ERS-status beholdes med vilje.
- Bulk-reekstraksjon per virkemiddel — kan legges til senere om det blir for mange saker å starte én og én.
Konsekvenser⚓︎
Positive
- Hvert regelsett ser bare dokumentene det skal vurdere; feilen fra #21742 forsvinner ved konstruksjon.
- Nye saker kjøres som i dag, uten å vente på noe i arkivet.
- Regeldefinisjonene og stadium er uendret — ingen regelversjoner bumpes av denne ADR-en, og ingen saker skifter stadium i UI.
- En beslutning-utløst rekjøring får samme grunnlag som kjøringen den overstyrer, med mindre søker har sendt inn noe nytt.
- CU-kost påløper bare for dokumenter i en pakke, og aldri for reanalyse ingen har bedt om.
- Tavlas fire utvalg blir to (#22145, #22146); utløseren trengs ikke i pipelinen (#22144).
Negative / risiko
- Kai blir avhengig av at
TIføres konsekvent. En sak i status 5 uten tilsagn i arkivet får ingen sluttrapportkjøring, og en manuell søknadskjøring på den får alt inngående. Utvalget på 17 saker støtter premisset, men borettslag/boligsameier og saker før 2023 er ikke verifisert. - ERS-status og arkivet kan være i utakt (Mimir oppdateres én gang i døgnet). En sak i 0/1 som allerede har fått tilsagn, kjøres med søknadsreglene på det som kom inn før tilsagnet. Grunnlaget er da riktig, selv om statusen henger etter.
- Websak-kall øker. Saker i status 5 som tidligere var ferdige, må sjekkes igjen.
- Blandede analyzer-versjoner i en pakke til saksbehandleren har reekstrahert.
Følgeoppgaver (ADO): #22127, #22126, #22129, #22144, #22145, #22146, #22217.
Implementasjonsplan⚓︎
Berørte stier
| Område | Fil / sti | Endring |
|---|---|---|
| Dokumentutvalg | src/Enova.Kai.Application/Dokumentutvalg/Dokumentutvalgsvelger.cs |
Pakken velges av regelsettet (fra ERS-statusen kjøringen gjelder), ikke av om grensen finnes. Grensen avgrenser innholdet. |
| Tilsagnsgrense | src/Enova.Kai.Application/Dokumentutvalg/Tilsagnsgrensesøk.cs |
Avvisningsbrevet er ikke en grense; bare TI. |
| Versjonsvalg | src/Enova.Kai.Application/Dokumentutvalg/Dokumentversjonsvalg.cs |
MD5 og nyeste-versjon-reglene (#22145); rekkefølge etter journalpostnummer. |
| Dokumentliste | src/Enova.Kai.Infrastructure/DocumentExtraction/WebsakDocumentLister.cs |
To strategier (#22145, #22146); filterliste i src/Enova.Kai.Application/Dokumentutvalg/Journalpostfilter.cs (#22129); vakten som beholder en analysert versjon (før nedlasting). |
| Kommando/payload | RunCaseWorkflowCommand, CaseWorkPayload |
ERS-statusen som allerede bæres, gir regelsettet og dermed pakken ved henting. |
| Utplukking | src/Enova.Kai.Worker/Polling/SelectionJob.cs, ErsStatuspolicy.KvalifiserendeStatuser |
Uendret filter; status 5 gir arkivsjekk før kjøring. |
| Idempotens | polling_processed_cases, PollingProcessedCaseStore |
Ferdig-merke per (sak, dokumentpakke) i dokumentpakke_tilstand, med avtrykk og neste sjekk (#22126, spec 2026-09-24-rekjoring-per-dokumentpakke-design.md). |
| Ekstraksjon | src/Enova.Kai.Worker/Polling/FetchDocumentsJob.cs, ExtractDocumentJob.cs, IDocumentBlobStore.FactsExistsAsync, ISakDokumentEkstraksjonStore.TryBeginDocumentAsync |
Et dokument med lagret analyse — uansett analyzer-id — ekstraheres ikke automatisk. Bare manuell reekstraksjon forbigår dette (hindres fortsatt av FactsExistsAsync/TryBeginDocumentAsync for en slot som alt er analysert). |
| Varsel og knapp | apps/kai-app/, POST /cases:reekstraher (Enova.Kai.Api/Endpoints/Cases/Reekstraher/) |
#22217; endepunktet i #22618. |
Uendret: regel-YAML-ene (ers_statuser), Regel.cs, WorkflowGraphRunner.AppliesTo,
ErsStatuspolicy.StadiumFor og stadium i lesemodellene.
Migrering og utrulling
- Ingen ny lagring av grensen. Grensen finnes i arkivsaken som uansett leses ved henting.
- Deploy. Rekkefølgen api og worker deployes i kan ikke styres. Bare workeren migrerer
(
DatabaseMigrationHostedService), så en ny kolonne kan gi api-en42703i et vindu som lukker seg selv når workeren har migrert. Skal vinduet unngås, må det løses i koden (expand/contract), ikke med en rekkefølge. - Innsnevringen er slått på i #22127, PR 3.
Mønstre å følge
- Domenebegreper fra
CONTEXT.md(Tilsagn, Dokumentpakke, Dokumentutvalg, Reekstraksjon), jf. ADR-015. Dokumentpakke og Dokumentutvalg er foreløpige til begrepene er gjennomgått med brukerne. - Regeldefinisjonene forblir DB-authored og seedet (ADR-013/014); ingen manuell versjonskonstant.
- Websak-feltene (kategori, journaldato, sjekksum) kommer fra porten i #22143.
Unngå
- Å la tilsagnet avgjøre regelsett eller stadium.
- Å utlede «nyeste» fra
Brevdatoeller dokumentversjonensVersjon(alltid 1). - Å gjøre reekstraksjon til en bivirkning av henting, reconciliation eller deploy.
Tester
tests/Enova.Kai.Application.Tests/Dokumentutvalg— pakken følger regelsettet: søknadsregler på en sak med tilsagn gir søknadspakken; søknadsregler uten tilsagn gir alt inngående.tests/Enova.Kai.Infrastructure.Tests—WebsakDocumentListermed anonymiserte arkivsak-fixtures modellert på: søknad med ettersending (23/58155-mønster), innvilget sak med signert retur (26/26361), sluttrapport med separat energiattest etter (23/55515), avvist og ettersendt sluttrapport « - 1»/« - 2» (23/58805), to sluttrapporter med ulike ISSR (23/35655), delrapporter som filtreres bort. Fixtures skal GDPR-anonymiseres.tests/Enova.Kai.Worker.Tests— ny analyzer-id i lockfilen gir ingen CU-kjøring for dokumenter med lagret analyse; nytt dokument i åpen pakke gir ekstraksjon og ny kjøring.
Verifisering⚓︎
- [ ] En ny sak i status 0/1 uten
TIkjøres med søknadsreglene på alle inngående dokumenter (test). - [ ] Manuell kjøring med søknadsreglene på en sak med
TIfår bare dokumentene før tilsagnet (test). - [ ] Søknadspakken for en innvilget sak inneholder ikke tilskuddsbrevet eller «Signert tilskuddsbrev i retur» (fixture-test).
- [ ] Sluttrapportpakken inneholder ikke søknadsdokumenter eller delrapporter, og inneholder en energiattest sendt inn etter sluttrapporten men før godkjenningsbrevet (fixture-test).
- [x] Sluttrapportpakken stenges ved godkjenningsbrevet for nyeste sluttrapport eller ved avslutningsbrevet, og ikke av en godkjent delrapport (fixture-test, #22146).
- [ ] En sak med godkjent sluttrapport får ingen sluttrapportkjøring (test).
- [ ] En sak i status 5 uten
TI-journalpost får ingen sluttrapportkjøring og en merknad om manglende tilsagn (test). - [ ] Bytte av analyzer-id i lockfilen fører ikke til CU-kall for dokumenter som allerede har lagret analyse (test).
- [ ] Samme sak, samme regelsett og samme arkivtilstand gir samme dokumentpakke for automatisk kjøring, manuell kjøring og beslutning-utløst kjøring (test).
- [ ]
Tilsagnsgrensesøkbruker ikke avvisningsbrevet som grense (test). - [ ]
dotnet build Kai.slnxogdotnet test --solution Kai.slnxer grønne; migrasjonen forpolling_processed_caseser kjørt mot en lokal database (ingen test kjører en migrasjonsUp).
Revisit-triggere⚓︎
- Saker i oppfølging uten
TI-journalpost dukker opp i vesentlig antall (f.eks. borettslag/boligsameier eller eldre saker): vurder et alternativt grensesignal per virkemiddel. - Delrapporter skal vurderes: nytt regelsett og ny dokumentpakke; denne ADR-en utvides.
- Websak-kallvolumet fra arkivsjekkene blir et problem: avgjør sjekkfrekvens (ikke-mål over).
- Websak begynner å versjonere søkers dokumenter (
Versjon > 1): revurder «lik tittel og originalt filnavn i en senere journalpost, ulik MD5 på originalen» som definisjon på ny versjon.
Tilleggsinformasjon⚓︎
- Avklaringer: #22142 (kommentar 15.09.2026), #22130, fagansvarligs kommentar på PR 25510 (16.09.2026).
- Arkivstruktur og verifisering:
docs/architecture/websak-soknadsdata-xml.md. - Begreper:
CONTEXT.md— Tilsagn, Dokumentpakke, Dokumentutvalg, Reekstraksjon, Stadium, ERS-status. - Relaterte: ADR-012 (utplukking), ADR-013 (regelmotor), ADR-014 (regelgraf-versjonering, uendret av denne ADR-en), ADR-015 (begreper), ADR-016 (sak-replika).
- Tavlenotater:
docs/superpowers/specs/2026-08-24-regelsett-per-dokumentpakke-tavlenotat.pdf. - Implementasjon av utvalget (uten innsnevring): PR 25523, spec
docs/superpowers/specs/2026-09-16-dokumentutvalg-ved-henting-design.md.