Arkivering fra Elektronisk Stoffkartotek (IOM-725)

Arkivering fra Elektronisk Stoffkartotek (IOM-725)


Status: Jobb 1 er kodemessig ferdig og merget i develop, men satt på vent. Scheduler skal ikke aktiveres i produksjon før to klient-/leverandør-side-blokkere er løst (se "Pause-status og blokkerere" nedenfor). Ende-til-ende-flyten er verifisert mot sikt_test-tenant (KeyService → WPS-token → eksponeringer → SDS-metadata → SDS-fil → S3 → P360-sak + dokumenter). workplacesafety-ext-konnektoren er på v2.0.1. Flyten er herdet basert på en strukturert review: tre kritiske bugs (K1 tidsvindu env-styrt via property, K2 Slack-trigger fyrer på alle feilstier inkl. SIF stille feil, K3 try/on-error-continue på både tenant- og item-nivå) og seks should-fix-punkter (B1–B6) rettet. Mule runtime bumpet fra 4.6.7 til 4.9.17 for å matche CloudHub-prod. Loki er nå log-destinasjon (Humio-affiliasjon fjernet). Loggformat-konvensjon LEVEL [flow/step] action — key=val. Next: <hint> innført på tvers av Jobb 1-flowene. Graciøs WPS SDS-degradering implementert: item arkiveres uten vedlegg ved WPS-feil, slik at eksponeringen alltid blir arkivert (60-års-bevaringsplikten gjelder eksponeringen, ikke SDS-en). Jobb 2 (substitusjon) og Jobb 3 (risikovurdering) er ikke startet — konnektoren er låst inntil de eventuelt krever nye operasjoner.

Pause-status og blokkerere

Jobb 1 er kodemessig ferdig (merget i develop), men er satt på vent og skal ikke driftsettes i produksjon før følgende klient-/leverandør-side-blokkere er løst. Disse er identifisert sammen med fagsiden i Miro-tavlen for IOM-725:

  1. Manglende kontakt kort på P360-saken. Kontakt-kortet krever oppslag på fødselsnummer for å lenke saken til riktig kontakt (eksponert person). Sikt har ikke tilgang til fødselsnummer for ansatte hos institusjonene i denne integrasjonskonteksten, og kontakt-kortet kan derfor ikke fylles ut maskinelt. Uten kontakt-kort er saken arkiv-teknisk ikke fullstendig — selv om alle andre felter, vedlegg og kategorisering er på plass. Vi anser derfor Jobb 1 som ufullstendig som tjeneste-leveranse inntil dette er avklart.

  2. WPS-filter FromDate/ToDate virker ikke. Flyten bygger tidsvindu (jobb1.exposures.window) og sender det som filter til /api/exposures/by-filter, men Workplace Safety returnerer ikke korrekt avgrenset resultat. Saken er meldt inn til Workplace Safety via Zendesk. Det er teknisk mulig å mocke filteret eller filtrere klient-side i Mule, men i samtale med klienten er det besluttet å vente på riktig API-fiks i stedet for å bygge work-arounds som må reverseres senere — særlig fordi de selv ikke ser saken som høyt prioritert.

Konsekvens: scheduler-cron for Jobb 1 skal ikke aktiveres i prod-miljø før begge blokkerere er løst. Test-kjøringer mot sikt_test-tenant er fortsatt OK for verifikasjon. Når blokkererne er løst er det fortsatt mulig at små justeringer kreves (kontakt-kort-mapping, korrigert filter-payload) — dette skal vurderes i en re-aktiveringsrunde.

Innledning

Dette integrasjonsprosjektet automatiserer overføringen av HMS-dokumentasjon fra Workplace Safety (Elektronisk Stoffkartotek) til organisasjonens sentrale arkivløsning, Public 360. Løsningen er utviklet som en MuleSoft scheduler-drevet integrasjonsapplikasjon med navnet workplacesafety-p360-archiver, som orkestrerer forretningslogikk og datatransformasjon mellom fagsystemet og arkivet ved bruk av Public 360s Simple Integration Framework (SIF) API.

Gjennom bruk av standardiserte metadata-mappings definert av Sikt og Arbeidsutvalget (AU) for dokumentasjonsforvaltning, sørger integrasjonen for at tre spesifikke dokumenttyper — ferdigstilte substitusjonsvurderinger, registrerte eksponeringer med tilhørende sikkerhetsdatablader (SDS), og gjennomførte risikovurderinger — blir arkivert med korrekt juridisk og vitenskapelig kontekst. Teknisk realiseres dette ved å utnytte Public 360s Simple Integration Framework (SIF) API for automatisert opprettelse av saker og dokumentjournalføring.

Embed draw.io Diagram

Til arkivering benyttes p360-arkiv-appen, en UH-IT-fellestjeneste som proxyer SIF API mot Public 360.

Nøkkel info

Egenskap

Verdi

Kommentar / Beskrivelse

Egenskap

Verdi

Kommentar / Beskrivelse

Initiering av flyt

Tidsstyrt (Scheduled Polling)

Integrasjonen trigges nattlig via en Scheduler for å polle ferske data fra Workplace Safety API (/api/exposures/by-filter) for det siste døgnet.

Flyt mønster

Semi-synkron / batch

Data leses inn i batch per organisasjon (estimert < 100 elementer per kjøring). Selve arkiveringen mot P360 skjer sekvensielt for hvert enkelt element i Items-arrayet.

Bruk av meldingskø

Nei

Meldingskø er ikke vurdert som nødvendig. Amazon S3 benyttes som teknisk mellomlagring (buffer) og backup for datafiler og vedlegg før de overføres til Public 360.

Open API

Nei

Løsningen er en intern integrasjonstjeneste. Workplace Safety: OAuth 2.0 client-credentials per institusjon mot https://auth-{institusjon}.workplacesafety.no/connect/token. P360 (via UH-arkiv-gatewayen): API-nøkkel X-Gravitee-Api-Key. Interne datastores bruker username/password fra Mule secure properties.

IntArk

Ikke brukt i denne integrasjonen

Sikt-fellestjenesten IntArk benyttes ikke i denne integrasjonen. P360-trafikk går via UH-IT-gatewayen gw-sikt.intark.uh-it.no — merk at vertsnavnet inneholder strengen 'intark', men dette er UH-IT sin API-gateway (Gravitee-basert), ikke Sikts IntArk-tjeneste.

Logging og overvåking

Grafana/Loki

Integrasjonen sender logger og audit-spor til Grafana/Loki-plattformen for monitorering og feilsøking via Grafana. Loggformat følger konvensjonen LEVEL [flow/step] action — key=val. Next: <hint>, slik at hver linje sier hva som skjer og hva som forventes å skje videre.

Denne tabellen oppsummerer de arkitektoniske valgene for workplacesafety-p360-archiver, der S3 fungerer som et sikkert lagringspunkt for binærdata under prosessering, mens selve arkivreferansen (Source of Truth) forblir i Public 360.

Bakgrunn

Hovedformålet med løsningen er å sikre etterlevelse av norske regulatoriske krav, herunder Arkivloven og Noark 5-standarden. Digital transformasjon av kjemikaliehåndtering krever at data forblir tilgjengelige, autentiske og brukbare over svært lang tid. Dette er spesielt kritisk for eksponeringsregistre, hvor det foreligger et lovmessig krav om 60 års bevaringstid for å sikre dokumentasjonens integritet over generasjoner, for eksempel ved spørsmål om yrkessykdom.

Interessenter

Prosjektet er et samarbeid mellom flere sentrale aktører for å sikre standardisering i sektoren:

  • Sikt (Kunnskapssektorens tjenesteleverandør): Koordinerer anskaffelse og standardisering av systemene.

  • Arbeidsutvalget (AU) for dokumentasjonsforvaltning: Har definert de spesifikke metadata-mappingene som integrasjonen må følge for å sikre juridisk gyldighet.

  • Lokale HMS-ansvarlige: Ansvarlige for datakvalitet i kildesystemet (Workplace Safety).

  • Dokumentasjonsforvaltere: Mottakere av arkivverdig materiale i Public 360.

Brukerhistorie

Som organisasjon har vi behov for automatisk og sikker arkivering av HMS-dokumentasjon for å redusere manuelt arbeid og sikre juridisk etterlevelse. Løsningen dekker tre separate og uavhengige behov:

  1. Jobb 1: Arkivering av registrerte eksponeringer med tilhørende sikkerhetsdatablader (SDS) for å ivareta ansattes rettigheter.

  2. Jobb 2: Arkivering av ferdigstilte substitusjonsvurderinger for å dokumentere utfasing av farlige kjemikalier.

  3. Jobb 3: Arkivering av gjennomførte risikovurderinger for å dokumentere virksomhetens forebyggende sikkerhetsarbeid.

Systemer/tjenester

Integrasjonsløsningen workplacesafety-p360-archiver fungerer som det sentrale bindeleddet mellom fagsystemet for kjemikaliehåndtering og organisasjonens arkivløsning. Løsningen består av følgende komponenter:

  • Workplace Safety (WPS / Elektronisk Stoffkartotek): Fungerer som kildesystem (Source). Systemet forvalter data om kjemikalier, sikkerhetsdatablader (SDS) og gjennomførte vurderinger. Data hentes ut via Workplace Safety API (kilde for rådata om eksponeringer og kjemikalier), som gir tilgang til moduler for substitusjon, risikovurdering og eksponeringslogger.

  • Public 360 (P360): Fungerer som målsystem (Target) for arkivering. Integrasjonen kommuniserer med P360 gjennom Simple Integration Framework (SIF) API (mottaker for journalføring). Dette rammeverket muliggjør automatisert opprettelse av saker og dokumentjournalføring i henhold til Noark-standarden. En teknisk nøkkelfunksjon er bruken av "recno" (record numbers) for å identifisere korrekte dokumentkategorier og statuser i arkivet.

  • Amazon S3: Fungerer som midlertidig lagringsplass og backup for binærdata under prosessering.

  • PdfGenerator (Java): En egendefinert Java-komponent basert på 'openhtmltopdf' som transformerer JSON-data til statiske PDF-filer for langvarig lagring.

  • MuleSoft workplacesafety-p360-archiver: Selve integrasjonsmotoren, utviklet som en scheduler-drevet integrasjonsapplikasjon (Mule 4.9.17, samme som CloudHub-prod). Dets oppgave er å orkestrere prosessen: hente data fra Workplace Safety (via workplacesafety-ext-konnektoren), transformere metadata og filer (Base64-koding) via DataWeave, og utføre de nødvendige kallene mot P360 SIF API i riktig rekkefølge. API-et håndterer også logikk for feilhåndtering, spesielt viktig siden SIF API kan returnere HTTP 200 selv om en operasjon har feilet internt.

Detaljert liste av alle involverte systemer/tjenester — hva utveksler data? Fra hvor / til hvor?

System

Data

Brukt API (endepunkter)

System

Data

Brukt API (endepunkter)

Workplace Safety (Kartotek)

OAuth2 token-request

POST https://auth-{institusjon}.workplacesafety.no/connect/token (scopes per jobb: exposure, sds, substitution, risk_assessments). API-base er per institusjon: https://{institusjon}.workplacesafety.no/v{versjon} (f.eks. https://sikt.workplacesafety.no/v1.2.7). Per-institusjon URL-felter (identityBaseUrl, apiBaseUrl) og KeyService-instans (instance) ligger som felt i configDb.orgs[i].ArkivWorkplacesafety[env] og leses per kjøring; dette gjør det mulig å rute én institusjon via eget gateway (intark, gravitee, …) uten konnektor-endringer. Klient-credentials hentes fra Sikts KeyService av workplacesafety-ext-konnektoren.

Workplace Safety (Kartotek)

Henter eksponeringsoppføringer filtrert på siste døgn

POST /api/exposures/by-filter (med limit, from, to) — NB: from/to-filtrene returnerer ikke korrekt avgrenset resultat, meldt inn til WPS via Zendesk. Se "Pause-status og blokkerere".

Workplace Safety (Kartotek)

Henter SDS-metadata inkl. downloadLink for kjemiske substanser

POST /api/sds/by-productIds

Workplace Safety (CDN/blob-lager)

Laster ned faktisk SDS-fil

GET payload.downloadLink[0] (ekstern URL returnert fra forrige svar)

configDb (Amazon DocumentDB)

Henter Slack-blacklist

configDB.slack-blacklists

configDb (Amazon DocumentDB)

Henter aktiv per-tenant arkiveringskonfig

configDB.orgs

oai-db

Skriver auditInfoMap til audit-loggen ved slutten av hvert item

oai-GenAudit

Amazon S3

Laster opp PDF-datafil og SDS-vedlegg

bucket mule-prod-buckets, prefix workplacesafety-${env}/exposureRecords/

UH-arkiv (P360-proxy)

Sender ferdig sak/dokument-payload til arkivering i Public 360 via SIF

POST https://gw-sikt.intark.uh-it.no/uh-arkiv/arkiver/{environment}/p360 (med X-Gravitee-Api-Key)

Slack

Sender feilrapport ved status ≠ success (orgs på blacklist hoppes over)

Slack-kanal mule-prod

Grafana/Loki

Strukturert kjørelogg + audit-spor

Loki HTTP appender (loki.platon.sikt.no)

Flytdiagram — Jobb 1

Diagrammet under viser hvordan komponentene fra tabellen over kalles i tid for én iterasjon av Jobb 1, fra scheduler-trigger via Workplace Safety og S3 til arkivering i Public 360, med audit-spor til oai-db og betinget feilrapport til Slack.

draw.io Diagram

Data-flow 'Entity Relationship Diagram' (ERD) — Jobb 1

Diagrammet under viser hvordan datastrukturene transformeres fra Workplace Safety-eksponeringen via S3-mellomlagring til Public 360-saker og dokumenter, samt hvordan ConfigDbOrg leverer default-verdier og AuditInfoMap akkumulerer status på tvers av stegene.

Embed draw.io Diagram

Tilgangsstyring og logging

  • Autentisering: Workplace Safety: OAuth 2.0 client-credentials per institusjon mot WPS' IdentityServer (https://auth-{institusjon}.workplacesafety.no/connect/token). Reelle scopes (per WPS-kontaktperson): exposure, sds, substitution, risk_assessments — bestilles per jobb. Per-institusjon klient-credentials (clientId og clientSecret) lagres kun i Sikts KeyService og hentes ut av workplacesafety-ext-konnektoren ved kjøretid; ingen WPS-credentials lagres i selve appens secure properties. Per-institusjon URL-er for token- og API-endepunkt lagres som felter (identityBaseUrl, apiBaseUrl) i configDb.orgs[i].ArkivWorkplacesafety[env], sammen med KeyService-instans-ID-en (instance); konnektorens operasjoner mottar disse per kall, ingen URL-er er hardkodet i appens konfig. P360 (via UH-arkiv-gatewayen): API-nøkkel-autentisering med X-Gravitee-Api-Key. Interne datastores (configDb, oai-db) bruker username/password fra Mule secure properties (secure2.properties med ${action} som dekrypteringsnøkkel).

  • Logging: All aktivitet logges med en unik correlationId for å kunne spore en melding fra kilde til mål. Loggformat følger konvensjonen LEVEL [flow/step] action — key=val. Next: <hint>, slik at hver linje sier hva som skjer, hvilke nøkkelverdier som er involvert, og hva som forventes å skje videre. ERROR-linjer inkluderer i tillegg State: (hva fullførte før feilen) og Next: (recovery-handling) for raskere feilsøking.

  • Audit-spor: Flyten skriver auditInfoMap til Sikts oai-db audit-tabell ved slutten av hver iterasjon, både ved suksess og feil. Kildesystemet (Workplace Safety) oppdateres ikke fra denne integrasjonen.

Forretningsregler

Mapping

Integrasjonen workplacesafety-p360-archiver benytter følgende logikk ved opprettelse av sak for eksponering:

Verdiene under er default-verdier per organisasjon, hentet fra configDb-noden ArkivWorkplacesafety.${mule_env}. De kan variere mellom tenants og overstyres per org.

  • Tittel-generering: Sakstittelen bygges dynamisk ved å kombinere stoffnavn fra kildesystemet, år/måned for eksponering, og fritekst fra fagsystemets tittelfelt for å sikre unik identifikasjon.

  • Arkivklassifisering: Alle eksponeringssaker klassifiseres med primærkode a.f.05 (Føre tilsyn med helse, miljø og sikkerhet) i arkivdel 3-integrasjon øvrig.

  • Tilgangsbegrensning: På grunn av personopplysningsvern skjermes saken med tilgangskode U.off og hjemmel Offl § 13, og tilgang begrenses til gruppen Integrasjon stoffkartoteket.

  • Mapping for eksponering (Jobb 1):

    • Tittel: {Substansnavn} - {ÅÅÅÅ MM} - {Tittelfelt}.

    • Skjerming: Alle eksponeringssaker merkes med tilgangskode U.off og hjemmel Offl § 13 jfr Fvl § 13.1.

    • Arkivkode: Benytter primærklassifisering a.f.05 (Helse, miljø og sikkerhet).

    • Kontakt-kort: Ikke implementert maskinelt. P360-saken skal lenkes til riktig kontakt (eksponert person) via et kontakt-kort, men dette krever oppslag på fødselsnummer som Sikt ikke har tilgang til i denne integrasjonskonteksten. Saker arkiveres dermed uten utfylt kontakt-kort, og må behandles manuelt for fullstendig arkiv-leveranse. Se "Pause-status og blokkerere".

  • Datoformat: WPS returnerer exposureDate som MM/dd/yyyy (US-format), mens andre dato-felt i samme respons kommer som ISO-8601 — inkonsistens er rapportert til WPS via Jira-kommentar. Flyten parser exposureDate som MM/dd/yyyy og konverterer til arkivvennlig yyyy MM for sakstittelen. Spesialtegn som er ulovlige i P360-filnavn (< > : " / \\ | ? *) strippes fra tittel før den brukes som filnavn.

Behandlingstid/responstid og volum

  • Volum: Estimert lavt volum per natt (typisk under 100 elementer per organisasjon).

  • Frekvens: Nattlig batch-kjøring for å minimere belastning på API-ene i arbeidstiden.

Feilhåndtering, konsekvenser av feil og overordnet risikoanalyse

  • SIF API Validering: SIF API kan returnere HTTP 200 med status: "success" selv når enkelte dokumentopplastinger har feilet (kun sak-opprettelsen lyktes). Flyten overstyrer derfor auditInfoMap.docsToP360.status til "error" dersom failedDocs > 0, slik at audit-loggen og Slack-varslingen ser den faktiske feilen. Original gateway-status bevares i gatewayStatus for sporbarhet.

  • Slack-trigger på alle feilstier (K2): auditInfoMap sub-flowen sjekker datafilToS3.status, docsToP360.status og toppnivå auditInfoMap.status — slik at SIF-stille-feil-stien (200 + failedDocs > 0) faktisk fyrer Slack-alarm. Tidligere ble bare datafilToS3.status sjekket, og overstyringen i punktet over hadde derfor ingen Slack-effekt.

  • Try på tenant- og item-nivå (K3): WPS-toppkallet er pakket i <try>/<on-error-continue> — ved KeyService- eller WPS-utfall fyrer én Slack-alarm per tenant og foreach hopper, slik at flyten fortsetter til neste org i stedet for å stoppe Jobb 1. Hvert item inni foreach er pakket i tilsvarende <try> — uventede feil i sub-flowene (PDF, S3, P360-retry uttømt) registreres som status: "error" i audit, fyrer Slack via K2, og foreach fortsetter til neste item.

  • Graciøs WPS SDS-degradering: WPS SDS-API har observert intermittente HTTP 5xx (transient WPS-side-feil, edge-cases på productId, etc.). Sub-flowen vedleggToS3 har en egen <try> rundt SDS-metadata-oppslag og SDS-nedlasting med on-error-continue som lister alle WPS-connector-feiltyper eksplisitt. Ved enhver WPS-feil settes sdsAvailable=false og item-en arkiveres uten SDS-vedlegg. Eksponeringen selv er arkiveringspliktig (60 års bevaringstid) og bør lagres til P360 uavhengig av om SDS-vedlegget kan hentes — vedlegget kan re-arkiveres senere når WPS er friskt. S3- og file:write-feil propagerer fortsatt opp til item-level try (de indikerer bredere infrastrukturproblem).

  • Retry-mekanisme: SIF-kallet i docsToP360 har <until-successful> med maxRetries=3, millisBetweenRetries=5000 (totalt ~15 s worst-case per item). Ved tekniske feil (nettverk/timeout) forsøkes på nytt umiddelbart; vedvarende feil propagerer til item-level try beskrevet over.

Kommentarer

  • PDF/A: Det bør vurderes å oppgradere PDF-generatoren til å produsere PDF/A-standard for å garantere lesbarhet i hele 60-årsperioden.

  • IntArk: Sikt-fellestjenesten IntArk benyttes ikke i denne integrasjonen — P360-trafikk går via UH-IT-gatewayen gw-sikt.intark.uh-it.no (UH-IT sin Gravitee-baserte API-gateway, ikke Sikts IntArk-tjeneste). Status for Sikt-IntArk som fellestjeneste er ikke verifisert i denne dokumentasjonen.

  • Kontakt-kort og fnr-tilgang: P360-arkivposter for eksponering bør normalt inneholde et kontakt-kort som lenker saken til den eksponerte personen. Dette krever fødselsnummer-oppslag som Sikt ikke har tilgang til i denne integrasjonskonteksten. Behandling som mulig retning videre: enten skaffe en autorisert kanal for fnr-oppslag (krever rettslig grunnlag/avtale med institusjonene), eller akseptere at kontakt-kortet fylles ut manuelt i en etterprosess. Se "Pause-status og blokkerere".

Relaterte ressurser

  • Jira: IOM-725 — overordnet migrerings- og utviklingsticket

  • Jira: IOM-811 — migrering fra CloudHub 1.0 til Docker og Platon

  • Confluence: Migrering fra CloudHub 1.0 til Docker — tekniske notater — A-til-Å teknisk dokumentasjon av CE/Docker-migreringen (gotchas, Dockerfile, neste steg mot Platon)

  • Miro-board (Agata): https://miro.com/app/board/uXjVJhoc7pg=/