Alle dokumenter

Tekniske og organisatoriske sikkerhetstiltak

Oppdatert: 28. september 2026

Vedlegg 2 til databehandleravtalen. Beskriver tiltakene etter personvernforordningen artikkel 32.

Hver påstand skal kunne peke på en fil i repoet. Står det noe her som ikke stemmer med koden, er det koden som har rett og dette dokumentet som må rettes. Det som mangler, står i eget avsnitt nederst — ikke utelatt.

Sist oppdatert: 28.09.2026.


1. Hvor opplysningene ligger

LeddLeverandørLokasjon
DatabaseNeonAWS eu-central-1, Frankfurt
ApplikasjonVercelfra1, Frankfurt (prosjektinnstilling)
Arkiv av godkjente rapporter (PDF/A)Vercel Blob, privat tilgangfra1, Frankfurt (valgt da lageret ble opprettet, ikke kontrollert på nytt)
Konvertering til PDF/AVercel Sandbox, med Vercels eget bilde vercel/sandbox/ubuntu og uten lagrede kopier (snapshots)fra1, Frankfurt (standard for prosjektet fra 28.09.2026. Før det: iad1, USA)
SpråkmodellVercel AI Gateway, videre til OpenAIGatewayen kan behandle forespørselen i hvilken som helst Vercel-region. Modellen kjører i USA
E-postResendSendes fra eu-west-1, Irland. Resend lagrer konto- og e-postdata i USA

Databasen, applikasjonen og arkivet ligger i EU. Språkmodellen, søket hos Serper og e-posten hos Resend sender opplysninger ut av EØS. Det står i vedlegg 3 (underleverandorer).

Vercel Blob kan mellomlagre private filer i regionale knutepunkter i Vercels nettverk.

2. Tilgangskontroll

Innlogging (packages/auth/src/auth.ts)

  • E-post og passord. Ingen innlogging via tredjepart.
  • E-postadressen må bekreftes før kontoen kan brukes, og før en invitasjon til et foretak kan godtas. Bekreftelseslenken varer i 24 timer.
  • Passord på minst 8 tegn.
  • Sesjonen varer i 30 dager. Informasjonskapselen er Secure i produksjon. En tilbakekalt sesjon kan virke i inntil 5 minutter (hurtigbuffer).
  • Sesjonen lagrer brukerens IP-adresse og nettleser (session).
  • Forespørsler til innloggingen begrenses per minutt: 5 innlogginger, 3 registreringer, 3 forespørsler om nytt passord. Begrensningen lagrer IP-adressen (rate_limit).
  • Handlinger i appen begrenses per bruker og time (apps/web/lib/grense.ts).
  • Utestenging: etter 10 feil passord på 15 minutter er adressen stengt resten av vinduet. Det telles også for adresser uten konto, så svaret avslører ikke hvem som har konto (packages/auth/src/auth.ts).
  • Et foretak kan ikke slettes (disableOrganizationDeletion), så sakene følger femårsfristen også når et foretak slutter.

Adskillelse mellom meglerforetak

  • Hver sak tilhører ett foretak (sak.organization_id), og alle andre saksopplysninger henger under saken.
  • Hvert oppslag på en sak filtrerer på foretaket i den innloggede sesjonen (apps/web/lib/sak/les.ts). En sak i et annet foretak svarer «finnes ikke».
  • Foretaket hentes fra sesjonen på serveren, aldri fra forespørselen.
  • Når et medlem fjernes, nullstilles det aktive foretaket i alle personens sesjoner for det foretaket (fjernMedlem i apps/web/app/(innstillinger)/innstillinger/medlemmer/handlinger.ts). Hurtigbufferet kan holde tilgangen åpen i inntil 5 minutter.

Roller i foretaket (packages/auth/src/tilgang.ts)

RolleKan
MeglerOpprette og lese saker, kjøre søk, lage rapport. Godkjenne rapporten i egne saker når saken ikke har avvik eller mistanke
HvitvaskingsansvarligDet samme, pluss godkjenne alle rapporter (også saker med avvik eller mistanke, og andre megleres saker), styre medlemmer og se forbruk
EierDet samme, pluss slette foretaket

Tilgangen sjekkes på serveren i hver handling (auth.api.hasPermission). Regelen for godkjenning står i apps/web/app/(app)/saker/[id]/handlinger.ts.

Retten til å slette saker finnes i rollene, men ingen handling i appen sletter en sak. Saker slettes bare av slettejobben (punkt 7). Et foretak kan bare slettes gjennom endepunktet i Better Auth. Det finnes ingen knapp for det i appen.

Verids egne ansatte

  • Plattformroller gir ingen tilgang til saker.
  • Den eneste veien inn er innsyn i en brukers konto. Innsyn krever en begrunnelse, varer høyst 30 minutter og logges i driftlogg.
  • Under innsyn er disse handlingene stengt: godkjenne en rapport, sende en sak til kontroll, kontroll av person, kontrasignering (apps/web/app/(app)/saker/[id]/kontroll-handlinger.ts) og å sende en melding om mistenkelig forhold til Økokrim (apps/web/app/(app)/saker/[id]/okokrim/handlinger.ts).
  • Administrasjonsendepunktene i Better Auth er stengt over HTTP.

3. Dataminimering

  • Fødselsnummer lagres ikke. Det finnes ingen kolonne som tar imot et fødselsnummer eller et individnummer (packages/db/src/skjema.ts). Nummeret valideres og fjernes før et resultat lagres (packages/pipeline/src/personvern.ts).
  • Fødselsnummer sendes aldri til en språkmodell eller en søketjeneste.
  • Lenken til kundeerklæringen er 192 tilfeldige bit og lagres bare som SHA-256. Lenken virker i 14 dager og aldri etter signering.
  • Rolleindeksen lagrer bare sha256(navn + fødselsdato) og organisasjonsnumre.
  • Kopien av aksjonærregisteret lagrer ikke postnummer eller poststed, og kan bare slås opp per foretak — ikke per person.

4. Kryptering

  • All trafikk mellom nettleser og applikasjon, og fra applikasjonen til databasen og kildene, går over TLS.
  • Nettleseren får beskjed om å bruke bare HTTPS i to år (HSTS, punkt 8).
  • Databasen og arkivet er kryptert på disk hos leverandørene (Neon og Vercel).
  • Arkivet i Vercel Blob har privat tilgang. En fil kan ikke hentes uten nøkkel.
  • Hemmeligheter (databasenøkler, API-nøkler) ligger som miljøvariabler hos Vercel, ikke i koden.

5. Revisjonsspor

  • Tabellen hendelse logger hvem som gjorde hva og når: sak opprettet, part lagt til, søk kjørt, sjekklistepunkt utført, rapport godkjent, rolle endret, kundeerklæring åpnet og signert, og mer.
  • At hendelse bare skrives til, håndheves av en trigger i databasen (migrering 0021_hendelse_bare_skriving.sql, testet på en kopi og kjørt i produksjon 28.09.2026). Den avviser endring, direkte sletting og TRUNCATE. Tillatt er bare sletting når saken slettes, og at slettejobben bytter ut e-postadressen i foretakshendelser eldre enn fem år (punkt 7).
  • Hendelser på en sak slettes med saken. Slettingen selv logges uten personopplysninger.
  • Verids egne driftshandlinger (innsyn, utlogging av økter) logges i driftlogg, som ikke slettes med saken.
  • Signeringen av kundeerklæringen lagrer IP-adresse, by, land og nettleser. By og land kommer fra Vercels egne hoder. Verid bruker ingen egen tjeneste for oppslag av IP-adresser.
  • Hver rapport bærer en SHA-256 av bevisgrunnlaget og av PDF-en, så en endring etter godkjenning kan påvises.

6. Logger

  • Feil logges som navn: melding, uten innholdet i forespørselen (apps/web/lib/logg.ts). Det er fordi feil fra språkmodellen bærer hele spørsmålet, og feil fra databasen bærer parameterne.
  • Forbruksboken logger bare feilkoden og meldingen fra Postgres, ikke hele feilobjektet (packages/db/src/forbruksbok.ts).
  • Verid bruker ingen analyseverktøy eller feilsporingstjeneste. Ingen tredjepart får data om hvordan appen brukes.
  • E-post fra Verid inneholder ingen personopplysninger om partene, bare adressen til eiendommen og en lenke. Unntaket er e-posten til kunden med kundeerklæringen. Den har kundens fornavn, meglerens navn og e-postadresse, foretakets navn, adressen til eiendommen og en lenke som virker. Kundens e-postadresse går til Resend.

7. Sletting

  • Saker slettes fem år etter at oppdraget er avsluttet (hvitvaskingsloven § 30). Fristen er en generert kolonne i databasen (sak.slettes_etter).
  • Klokken starter først når megleren merker saken «oppdrag avsluttet» (apps/web/app/(app)/saker/[id]/handlinger.ts). Gjør ingen det, blir saken ikke slettet.
  • En jobb kjører hver natt kl. 03:17 UTC og sletter saker med utløpt frist, med alt som henger under dem (apps/web/app/api/cron/slett-utlopte). Slettingen er hard.
  • Jobben sletter først sakens mappe i arkivet, rapporter/<sakId>/ i Vercel Blob (slettArkiv i apps/web/lib/kjoring/arkiv.ts), og så radene i databasen. Kan filene ikke slettes, blir saken stående, og jobben prøver igjen neste natt.
  • Skriptet packages/db/scripts/slett-utlopte.ts kan bare vise hva som ville blitt slettet. Det sletter ingenting.
  • E-postadresser i foretakshendelser eldre enn fem år erstattes med en markør.

8. Nettleseren

Sikkerhetshoder på alle sider (apps/web/next.config.ts):

  • Content-Security-Policy: frame-ancestors 'none'; base-uri 'self'; form-action 'self'; object-src 'none'
  • Strict-Transport-Security: max-age=63072000 (Vercel setter også hodet). Uten includeSubDomains og preload, med vilje.
  • Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=(), browsing-topics=()
  • X-Frame-Options: DENY
  • X-Content-Type-Options: nosniff
  • Referrer-Policy: strict-origin-when-cross-origin

9. Språkmodeller

  • Brukes på tre steder: sortering av søketreff, forslag til risikovurdering med utkast, og forslag til svar (apps/web/lib/kjoring/modell.ts).
  • Modellen får navn, fødselsdato eller organisasjonsnummer, statsborgerskap, søketreff (tittel, lenke, utdrag), teksten i observasjoner og sjekkliste, meglerens fritekstsvar og treff fra OpenSanctions (navn, fødselsår, lister). Aldri fødselsnummer.
  • Modellen svarer i fast skjema. Begrunnelsen for hvert søketreff trykkes i rapporten, merket som modellens. Risikoklassen settes alltid av et menneske (personvernforordningen artikkel 22).
  • Hvert kall går gjennom Vercel AI Gateway med nullretensjon (providerOptions.gateway.zeroDataRetention: true). Vercel oppgir OpenAI som «nullretensjon med sikkerhetslagring»: forespørsler som blir merket for misbruk, kan likevel bli lagret. Gatewayen lagrer ikke spørsmål og svar, men lagrer metadata om forespørselen.
  • Modellen (openai/gpt-5.6-luna) kjører i USA.

10. Hendelser og brudd

  • Verid varsler behandlingsansvarlig uten ugrunnet opphold, og senest 48 timer etter at Verid ble kjent med bruddet. Varselet sier hva som skjedde, hvilke opplysninger og hvor mange registrerte det gjelder, og hva som er gjort. Rutinen står i rutine-for-brudd.
  • Kontakt: se KONTAKT_EPOST i apps/web/lib/metadata.ts.
  • Sårbarheter meldes etter ansvarlig-varsling. Kontakten står også i /.well-known/security.txt (RFC 9116), som går ut 28.09.2027. En test feiler 30 dager før (apps/web/lib/security-txt.test.ts).

Kjente mangler

Dette er ikke på plass per 28.09.2026. Listen er en del av dokumentet med vilje: en kunde som leser vedlegget, skal vite hva som gjenstår.

MangelRisikoPlan
Ingen totrinnsinnlogging (TOTP eller passnøkkel)Et lekket passord gir tilgang til foretakets sakerLegg til Better Auth twoFactor, påkrevd for hvitvaskingsansvarlig
Slettefristen starter bare når megleren merker saken «oppdrag avsluttet»En sak som aldri blir merket, blir aldri slettetPåminnelse om saker som ikke er avsluttet, og en rutine hos foretaket
En megler kan åpne en kollegas sak hvis hen kjenner id-en. Listen viser bare egne sakerTilgang innenfor samme foretak er videre enn listen viserAvgjør om dette er ønsket. Hvis ikke: filtrer hentSak på ansvarlig megler
Ingen radnivåsikkerhet (RLS) i PostgresAdskillelsen mellom foretak hviler på applikasjonskoden aleneVurder RLS på sak og tabellene under
Neon holder historikk i bare 24 timerEn feil som oppdages etter et døgn, kan ikke rulles tilbakeVurder lengre historikk (betalt plan)
OpenAI kan lagre forespørsler som blir merket for misbruk, og modellen kjører i USASpørsmål med navn kan bli lagret hos OpenAI i USADokumenter overføringsgrunnlaget (vedlegg 3), eller bytt til en modell i EU
Serper har ingen kjent juridisk enhet og ingen databehandleravtaleSøk med fullt navn går til USA uten grunnlagBe om enhet og avtale skriftlig, eller bytt leverandør
Ingen funksjon for å eksportere sakerUtlevering når avtalen slutter må gjøres for håndVerid lager eksporten manuelt til funksjonen finnes