Hoppa till innehållet
ErsviaErsviaSystemarkitekturdokument

9. Arkitekturbeslut

Besluten dokumenteras som ADR:er i docs/adr/. Här sammanfattas de med status, krav, alternativ och konsekvenser. TestVioras tre öppna arkitekturbeslut (TV-ADR 1–3) besvaras i 9.2.

9.1 Beslutade ADR:er#

ADR Beslut Status Krav Alternativ som valdes bort Konsekvenser Verifieras av
0001 Modulär monolit med zoner En deploybar Api-host med moduler (IModul), ett projekt och ett schema per modul, två zoner Beslutad (F0) KRAV-71, KRAV-78 Mikrotjänster från start (för dyr drift för ett litet team); en monolit utan gränser (blir ny teknisk skuld) En modul kan brytas ut till egen tjänst utan att kontrakten ändras. Zonerna körs som separata driftsättningar av samma image. ModulgransTester
0002 Kontrakt först OpenAPI 3.1 och AsyncAPI i contracts/, kompatibilitetsfasad för legacyformat, ProblemDetails med stabil felkod Beslutad (F0), genomförs i F1 KRAV-71 Kod först med genererad OpenAPI (instabila kontrakt) Brytande ändringar kräver ny version. Kontrakten publiceras i API-portalen. tests/Ersvia.Tests.Kontrakt, OpenAPI-diff
0003 Regler är versionerad data Beslutstabeller, åtta primitiver, 42 mallar, fyra ögon, facittest Beslutad (F0), genomförs i F6–F7 KRAV-19 till KRAV-23 Regler i kod (mål 2 nås inte); en generell regelmotor av BRMS-typ som Drools (svår att förstå för verksamheten, risk 2) Belopp med Belopp och explicit Avrundningsregel. Regionpaket innehåller bara parametrar och sammansättningar. Golden-tester per mall, FsCheck
0004 Bitemporal versionering Valid time och transaction time på allt som styr ersättningen, giltigVid och kandVid i API:erna Beslutad (F0) KRAV-3, KRAV-22, KRAV-36, KRAV-55, KRAV-73 Bara giltighetstid (kan inte svara på "vad visste vi?"); händelselogg med event sourcing överallt (för komplext) Historiken växer append-only. Exclusion constraints i PostgreSQL. BitemporalTester, BitemporalEgenskaper
0005 Reproducerbarhet med manifest och hashkedja Manifest med versions-id, motorversion och underlagssnapshot. SHA-256 över kanonisk JSON. Hashkedja. Beslutad (F0) KRAV-22, KRAV-36, KRAV-55, KRAV-67 Spara bara resultat (kan inte reproduceras) Samma manifest och underlag ger samma resultat. All tid från IKlocka. IntegritetTester
0006 Händelsedrivet med transactional outbox Outbox per modulschema, minst en gång-leverans, idempotenta mottagare. Händelsenamn ersvia.<Handelse>.v<n>, kanaler ersvia.{huvudman}.<modul>.v<n>, interna jobb ersvia.intern.* Beslutad (F0), reviderad 2026-11-11 KRAV-71 Direkta anrop mellan moduler (stark koppling); meddelandekö utan outbox (förlorade händelser) Händelsetyper med versionssuffix. Publiceraren kan bytas mot Kafka eller Integrationstjänsten. OutboxOchRevisionTester
0007 AI-gränser IChatClient, bara ersättningszonen, pseudonymiserade data, aldrig belopp, alltid utkast, avstängningsbart, eval-svit Beslutad (F0), genomförs i F10 Mål 2 och 4, KRAV-7, KRAV-45, KRAV-47 AI som beräknar eller beslutar; leverantörsbundet SDK i modulerna MCP-verktygen är läsande eller skapar utkast. Lokal modell är standard. tests/Evals
0008 Säkerhet och revisionslogg mTLS med SITHS, OIDC/SAML, roll och vårdgivare, hashkedjad revisionslogg per tenant Beslutad (F0) KRAV-6, KRAV-66, KRAV-67, TV-regel 12 Loggning bara i applikationsloggar (går att manipulera) Persistent logg och e-arkivleverans kommer i F2 och F12. OutboxOchRevisionTester.Revisionsloggen_ar_hashkedjad
0009 Enhetlig domän och öppna standarder Overenskommelse = Avtal | Uppdrag, termbankens begrepp, HSA-id och NVID som externa identiteter (primärnyckeln preciseras i ADR 0011), Peppol, FGS Beslutad (F0) KRAV-1, KRAV-37, KRAV-75, KRAV-76, KRAV-79 Separata flöden för egen regi Egen regi får budgetjustering. Identifierare utan å/ä/ö. InvariantGlobalization. HsaIdTester
0010 Produkt för flera regioner Huvudman är tenant, regionpaket, adaptrar per region, gemensamt regelbibliotek Beslutad (F0) KRAV-76, KRAV-79 Ett Stockholmsunikt system Standardhuvudman i konfigurationen är exempel. E2E körs mot "Region Exempel". RegionoberoendeTester
0011 Bitemporal persistens, outbox per schema och radnivåsäkerhet Ersvia.BuildingBlocks.Persistens: en tabell per bitemporal entitetstyp (giltig daterange, registrerad tstzrange, data jsonb, hashkedja), exclusion constraint med btree_gist, oföränderlighetstrigger, IBitemporalLager<T> i minne och PostgreSQL, outbox och revisionslogg per schema, RLS med app.huvudman, EF-migrationer per modul. Id-modell: vg-, ve-, ok-, bn-, fm-, eg- primära, HSA-id och övriga som bitemporala alias. Beslutad (F2) KRAV-3, KRAV-16, KRAV-17, KRAV-18, KRAV-22, KRAV-36, KRAV-67, KRAV-76 En tabell per entitet med egna kolumner (fler migrationer per regeländring); event sourcing Samma FsCheck-modell mot båda lagren. Listfrågor filtrerar i minnet (räcker för masterdata och avtal, inte för vårdhändelser). Idempotensnycklar i processens minne i MVP. Integrationstester med Testcontainers (as-of, rättelse, constraint, triggrar, RLS, outbox, åtkomstlogg)
0012 Vårdhändelser med partitionering, inskickslivscykel och portar vardhandelse en rad per version, PARTITION BY RANGE (period); oföränderlighetstrigger; idempotens i samma transaktion; tre statusdimensioner; asynkron validering med FOR UPDATE SKIP LOCKED; faktureringsmånad med brytpunkt och frysning; portar via kompositionsroten Beslutad (F4) KRAV-6 till KRAV-10, KRAV-14, KRAV-15, KRAV-61, KRAV-67 Generiska _version-tabeller (för långsamt för 25 miljoner per år) Väntande som dokument. GVR v2-fasaden i F9 mappar mot IVardhandelser. VardhandelseIntegrationTester, VardhandelseLasttest (4,2 min för 70 000)
0013 Regelmotorn som rent bibliotek Ersvia.Regelmotor utan I/O; elva primitiver inklusive episod; beslutstabeller med träffpolicy (unik, forsta, prioritet, alla, summa); uttryck som JSON eller formel; nio körfaser i fyra körnivåer med DAG; trace och resultathash; 34 mallar som täcker alla 42 regeltyper; facit och testbevis Beslutad (F3) KRAV-19 till KRAV-23, KRAV-36; NK1, NK40 Generell BRMS (Drools) som motor; kodade specialmallar per regeltyp Nya former med sammansatt. Kvar till F6/F7: mätning vid flera tidpunkter, riskpott i tandvård, LOL-undantag över tak 2, arvoden som passerar tak 1 mitt i ett besök. tests/Golden (51 facitfiler), tests/Ersvia.Tests.Unit/Regelmotor
0014 Listning med intervall-lagring och regler per regionpaket Listning som bitemporalt intervall ({pseudonym}|{listningstyp}), låst ögonblicksbild med SHA-256, listningsregler som data per regionpaket bakom IListningsregelkalla, portar i kompositionsroten, ICarelistingProducent och IStatligListningstjanst Beslutad (F5) KRAV-12, KRAV-18, KRAV-22, KRAV-24, KRAV-36, KRAV-67, KRAV-76; NK17–NK19, NK22 Listning per vårdgivare och dag (cirka 900 miljoner rader per år) Listfrågor och aggregering i minnet; ögonblicksbildens poster som dokument; flyttas vid lasttestet i F6 ListningIntegrationTester, tests/Ersvia.Tests.Unit/Listning
0015 Beräkning med låst manifest, ackumulerade regler och fakturamottagare som regionpaketsdata Portar i Berakning.Kontrakt (regler, masterdata, överenskommelser, vårdhändelsebild, listningsbild, FUMS/FUL) med adaptrar i BerakningKopplingar; manifest med versions-id och hash för regler, tabeller, masterdata, överenskommelser, kodverk, konfiguration, vårdhändelsebild, listningsbild, kostnadsunderlag, tidigare körningar och motorversion; regelval per vårdgivare via ersättningsgrund och omfattning, avtalsparametrar som JSON merge patch; ackumulerade regler i ett andra pass; fakturamottagare med beslutstabell (FIRST) i regionpaketet; omräkning med differensrader, torrkörning krävs för stängd period (BE-5004); skuggkörning och simulering sparas inte som gällande Beslutad (F6) KRAV-24 till KRAV-38, KRAV-40, KRAV-55, KRAV-64, KRAV-65; NK19, NK27 Läsa bitemporala tabeller per rad; specialkod per avtal Körningen är synkron (202 med avslutat jobb); efterregistrerade händelser räknas inte i inkommande faktureringsmånad (F8); momskompensation omfattar inte ackumulerade regler; rader och trace som dokument BerakningLasttest (4,5 min för 2 miljoner händelser), facit maj 2026, Region Exempel i CI
0016 Portal, AI-tjänst och MCP-server Tre värdar (Ersvia.Api, Ersvia.Mcp med MCP och /ai/*, Ersvia.Portal); portal och AI-tjänst anropar Api via Ersvia.Klient; tema per regionpaket; OIDC med roller; IErsviaAi ovanpå IChatClient med Anthropic, lokal och Fake; AI-register, pseudonymiseringsfilter, beloppsvakt, art. 50 och hashkedjad AI-revisionslogg; regelassistent som bara skapar utkast; MCP med läsverktyg och ett utkastverktyg Beslutad (F11a) KRAV-5, KRAV-69, KRAV-77; NK26, NK40 AI i portalen; AI-leverantörens SDK direkt i modulerna AI-revisionslogg som fil tills F12; portalsidor för Beräkning, Granskning, Fakturering och Avstämning är platshållare (F11b); axe-tester utanför dotnet test tests/Ersvia.Tests.Ai (37), portaltester (25), PortalOchAiTester
0017 Målrelaterad ersättning och Granskning som moduler ovanpå Beräkning Indikatorer och kontrollregler versioneras som regler (bitemporalt, fyra ögon, facit) men i egna moduler; måluppfyllelse, årsavstämning och ansökningar; bokföring via BokforTillaggAsync; deterministiska kontrollregler; riskpoäng som profilering, av som standard; ärenden med återkrav, ränta, preskription och kvittning; justeringar och attest i två steg; riskregister och årsrapport Beslutad (F7; numrerad om från 0016) KRAV-41 till KRAV-49, KRAV-21 till KRAV-23, KRAV-67; NK3–NK7, NK26, NK27 Indikatorer i Regelverk; AI för urval Beloppsnivåer i matriserna och referensräntor är exempelvärden; kvittning verkställs i F8 Enhets- och integrationstester för Malrelaterad och Granskning
0018 Uppföljning, exporter, parallellkörning och skuggning Modulerna Uppfoljning, Migrering och Drift; exportpaket med manifest (CSV, Parquet, JSON); personnummerkontroll före utlämnande; bitemporal budget; publicering med cellundertryckning; parallellkörning med deterministisk klassning; legacy-körningar med eget manifest; skuggning via GVR-fasaden; integrationslogg Beslutad (F10) KRAV-62, KRAV-63, KRAV-67, KRAV-68, KRAV-72, KRAV-73, KRAV-75, KRAV-79 Direktläsning av vårdhändelser i Uppföljning; synkron skuggning i drift Skuggningskön i minnet tappar anrop vid omstart; leveranser som base64-dokument; KPP- och patientregisterlayout tolkad Golden-test för fördelningen, integrationstester
0019 Fakturering, avstämning och utlämningsexport Underlag per vårdgivare × fakturamottagare × faktureringsmånad; MOMSK-AVTAL på allt fakturerat; förslag → godkännande/invändning → attest i två steg → Peppol BIS 3 med kvittens; ostridiga rader betalas ut; faktureringsmånad = mottagningsmånad; utlämningsexport i patientdatazonen bakom IIdentitetsutlamning; billing:claim som avsändare och mottagare; avstämning med drill-down via trace; VF-.prn och AF-Excel i Kompatibilitet Beslutad (F8, F9b) KRAV-38, KRAV-39, KRAV-50 till KRAV-61; NK8, NK9, NK21, NK33 Personnummer i fakturaunderlag; egen kopia av raderna i Avstämning Regionspecifika namn och Peppol-adresser i regionpaketet; belopp per vårdhändelse är en fördelning; .prn och billing:claim-XML ska verifieras mot verkliga filer och XSD Enhets-, kontrakts- och integrationstester; paritet VF och AF
0020 Fysisk zonseparation och drift IModul.Zon och Ersvia:Zon med värdarna Ersvia.Patientdata och Ersvia.Api; zonbrygga med mTLS, vitlista och personnummervakt; databasroller per zon; INyckelkalla/KMS; Docker-images och Helm (OpenShift restricted SCC, nätpolicyer, cert-manager, Route, HPA, PDB, CronJobs); OTel; WAL/PITR med RPO ≤ 5 min och återläsningstest; FGS-paket, export och bitemporal gallring. Tillägg F12a: VAL-export med personnummer i klartext från patientdatazonen. Tillägg F12b: F8-adaptrarna uppdelade per zon med de nya portarna IVardhandelsestatusunderlag (patientdata → ersättning, orsakstexter tvättade), IAfUnderlag, IKompatibilitetFakturering och IKompatibilitetReferens (ersättning → patientdata); personnummervakten gäller åt båda håll (422 GEN-0503); vårdhändelsebildens hash avser indata, så att reproduktionen blir bit för bit; låst listningsbild återanvänds (LI-5013) Beslutad (F12a), tillägg F12b KRAV-18, KRAV-67, KRAV-68, KRAV-70, KRAV-75, KRAV-79; NK19, NK22, NK24 Bara logiska zoner; en databasroll Zonbryggan är synkron HTTP (kan ersättas av händelsebuss); AF-rapporten gör zonhopp patientdata → ersättning → patientdata; i compose går zonbryggan utan mTLS Arkitekturtester för zonportar, ArgumentvaktTester, ZonvardTester, E2E i delat zonläge (24/24), fullstack-smoke (15/15), återläsningstest, Trivy och SBOM i CI
0021 GUI v2: designriktning Appskal med smalt toppfält, Ctrl+K, rollväljare och sidomeny per arbetsflöde; startsidor per roll (kakan ersvia.roll, bara visning); tokens v2 med neutrala ytor och accent bara för åtgärder, Inter från design/fonts; komponentbibliotek (Kpikort, Datatabell, Dialog, toasts m.fl.); WCAG 2.2 AA utan inline-skript; SAD-sajten i samma riktning Beslutad (GUI v2) KRAV-5, KRAV-69, KRAV-77 Färgat sidhuvud per region; ett skal utan arbetsflödesgrupper Tilläggsbeslutet (K52) bekräftas i en modal dialog; regionpaket som vill ha färgat sidhuvud avråds axe 67 granskningar, 0 överträdelser; sad-sajt.mjs; 54 bUnit-tester
0022 Vertical slices i enkla moduler, DDD-lager i rika Modulär monolit, portar och adaptrar och ren regelmotor behålls. DDD-lager i Regelverk, Berakning, Fakturering, Granskning, Listning, Vardhandelser, Malrelaterad och Overenskommelse; vertical slices (Features/<Namn>/ med request, handler, validering och endpoint) i Kodverk, Masterdata, Uppfoljning, Rapportering, Simulering och Drift. Kodverk är omgjord som mönster Beslutad (efter SAD v7) KRAV-71, KRAV-78 Samma fyra lager i alla moduler; vertical slices överallt (rika domäner tappar sitt skydd) Routes, operationId och kontrakt oförändrade; delad kod i Infrastructure/, Domain/ och Kontrakt/; övriga slice-moduler görs om en i taget ModulstilTester, ModulgransTester, RouteKontraktTester

Dubbletterna av ADR 0012 är omnumrerade (1d377a2): 0012 vårdhändelser, 0013 regelmotor och 0014 listning. Dubbletten av 0016 är omnumrerad i SAD v5: 0016 portal och AI (F11a, committad först) och 0017 målrelaterad och granskning (F7).

9.2 Svar på TestVioras öppna arkitekturbeslut#

TV-ADR Fråga Förslag till beslut Motivering
1 (fysisk) Ska ersättningssystemet driftas i regionens eget datacenter eller som tjänst hos en leverantör? Containrar på Kubernetes/OpenShift med Helm, molnneutralt Fungerar i båda fallen, så beslutet kan skjutas upp utan att koden påverkas. Datastrategin 2027–2031 talar för on-prem.
2 (utveckling) Ska avtalssystemet eller ersättningssystemet vara källan för avtal och ersättningsgrunder? Avtalssystemet är källa för överenskommelser och vårdutbud (KRAV-4). Ersvia äger ersättningsgrunder och regelversioner. I MVP kan avtal också registreras i Ersvia. Avtalet är juridiskt dokument hos avtalssystemet. Regelverket måste vara versionerat och testbart, vilket bara Ersvia kan garantera.
3 (utveckling) Ska analysdatabasen få vårdhändelser direkt från insamlingen eller bara utfall? Båda, i separata exporter: validerade vårdhändelser och listningsstatistik från patientdatazonen, utfall från ersättningszonen Ersvia ersätter GVR och ListOn, som i dag levererar till VAL. Mål 6 kräver att uppföljningen bygger på samma data som ersättningen.

9.3 Kommande beslut#

Id Fråga Behövs till Underlag
ADR (F12) Val av meddelandeplattform i produktion (in-process, Kafka eller Integrationstjänsten) F12 Regionens integrationsstrategi
ADR (F11b/F12) DPIA och k-anonymitet före AI (AI-registret är beslutat i ADR 0016) F12 NK26, kontroll 3 R5
ADR (F12b) Signering av images och uppdelning av F8-adaptrarna per zon F12b NK24, ADR 0020
ADR (kommande) Rotation av pseudonymiseringsnyckeln (källan är beslutad i ADR 0020) Införande Regionens nyckelhantering
ADR (kommande) Godkänd AI-modell och driftzon F11 Regionens AI-policy
ADR (kommande) Portalens teknik: Blazor server eller WebAssembly, och white-label-modell F11 Användartest
ADR (kommande) Strategi för ICD-11 (mappning och dubbelkodning) Före 2029 E-hälsomyndigheten
Ersvia SAD · version b706ca6 (2026-11-11) (med ändringar som inte är incheckade) · byggd 2026-11-11 · Ändringslogg · Diagramgalleri · Källa: docs/arkitektur/kapitel/09-arkitekturbeslut.md

Sök i dokumentet

100 % Ladda ned SVG