Sikkerhet i Done HRM

Versjon 1.14 — 6. oktober 2026 · gjelder hr.done.ai i produksjon

Done HRM lagrer personalopplysninger for flere selskaper i samme system: kontaktinformasjon, ansettelsesvilkår, lønn, fravær med helseopplysninger, undersøkelsessvar og signerte kontrakter. Dette dokumentet beskriver hvordan disse dataene er beskyttet, på tre nivåer. Hver del begynner med hva som gjelder i praksis, og går deretter inn i hvordan det er løst teknisk.

1. Lagring og sikkerhetskopi

Primær lagring og behandling skjer i EU, kryptert både der data lagres og når de sendes. Databasen, applikasjonen og filene ligger i Frankfurt, og e-post sendes fra Nederland. Tre av leverandørene er amerikansk eide selskaper som kjører i EU-regioner. Får en av dem tilgang fra USA, for eksempel ved support, håndteres det etter personvernforordningens kapittel V. Ingen data lagres på brukernes egne maskiner utover en informasjonskapsel for innlogging. Filer som kontrakter og attester ligger aldri på offentlige adresser: hver nedlasting går gjennom systemet, som først sjekker hvem som spør.

De mest følsomme opplysningene, lønn, er i tillegg kryptert med en egen nøkkel som ikke ligger i databasen. Skulle noen få tak i en kopi av databasen, er lønnsfeltet uleselig uten den nøkkelen.

Tjenesten sender ikke personopplysninger til noen leverandør av kunstig intelligens. Funksjonene som bygger på kunstig intelligens er sperret på servernivå i produksjon. Systemet lagrer heller ingen passord — innlogging skjer via Done ID, som er felles for alle Done-produkter, og som også håndterer tofaktor og passordpolicy.

Ikke bekreftet ennå: Hvor Vercels mellomlager for private filer fysisk ligger, er ikke bekreftet av leverandøren. Speilet av filene ligger i samme fillager som filene selv; signerte kontrakter finnes også hos Done Signatory. Databehandleravtalene med Neon, Vercel og Lettermint er akseptert på nett og ikke arkivert.

2. Skillet mellom selskaper

Alle selskaper deler ett system og én database. Skillet mellom dem er absolutt: for et selskap finnes de andre selskapene ikke. Det er ikke et filter som skjuler dem i skjermbildet — radene blir aldri hentet.

Dette håndheves på to uavhengige nivåer. Koden filtrerer alltid på selskap. I tillegg har databasen selv regler som gjør det samme, uavhengig av hva koden ber om. Skulle en utvikler glemme filteret i en fremtidig endring, gir databasen null rader, ikke alle selskapers rader. En glemt linje blir dermed en synlig feil, ikke en usynlig lekkasje.

Konsern og allianser er støttet: en kjedeadministrator i morselskapet kan se inn i datterselskapene. Innsynet går bare nedover. Datterselskaper ser aldri hverandre eller morselskapet.

Applikasjonslaget

  • Datamodell. Hver forretningstabell har en obligatorisk kolonne for selskap. Ingen tabell deles mellom selskaper uten den.
  • Sesjonsoppløsning. Ved hver forespørsel slås brukerens medlemskap opp. Listen over tilgjengelige selskaper er egne medlemskap pluss hele undertreet av datterselskaper hvis brukeren er kjedeadministrator. Aktivt selskap godtas kun hvis det finnes i denne listen.
  • Selskaps-ID kommer aldri fra klienten. Serverkoden leser den fra sesjonen og legger den i hver spørring og hver innsetting. Sender nettleseren med en selskaps-ID, ignoreres den.
  • Oppslag på ID. Alle oppslag krever både rad-ID og selskaps-ID. En gyldig ID fra et annet selskap gir «ikke funnet», ikke data.
  • Invitasjoner. Tilfeldig token på 32 tegn, gyldig i sju dager. Aksept krever at innlogget e-postadresse er identisk med den inviterte. Tokenet forbrukes atomisk, så to samtidige klikk gir ett medlemskap.

Databaselaget

PostgreSQL Row-Level Security er aktivert og tvunget på alle 35 tabeller som inneholder selskapsdata. Policyen er identisk på hver tabell og gjelder både lesing og skriving. Mangler selskapskonteksten, blir sammenligningen usann: null rader lesbare, all skriving avvist. Databasen feiler lukket.

  • Applikasjonsrollen. Applikasjonen kobler til som en rolle opprettet uten rett til å omgå Row-Level Security, uten superbrukerrettigheter og uten rett til å endre skjema. Det er avgjørende: databaseeieren omgår slike regler automatisk. De få systemoppslagene som må se på tvers av selskaper bruker en egen systemrolle — heller ikke den er eier. Eier-rollen er forbeholdt mennesker og migrasjoner, og applikasjonen nekter å starte hvis den finner seg selv som eier.
  • Kontekst per transaksjon. Selskaps-ID settes transaksjonslokalt, så konteksten kan ikke lekke mellom forespørsler — heller ikke gjennom tilkoblingspoolen.
  • Unntak, eksplisitt. Noen få operasjoner er ekte kryss-tenant og kan umulig ha selskapskontekst før oppslaget: kobling av en nyinnlogget bruker til sin ansattrad, oppslag av en invitasjon på token, mottak av signeringsresultat, de daglige jobbene og den daglige sikkerhetskopien. Disse bruker en egen, tydelig merket systemtilkobling, og bruken overvåkes av en statisk test.

3. Tilgang innad i et selskap

Innenfor et selskap ser ikke alle alt. En vanlig ansatt ser kollegakatalogen med navn, stilling, telefon og e-post, og sine egne data. En leder ser i tillegg full informasjon om sine egne ansatte, og bare dem. Superadministrator ser alt i selskapet.

Særlig følsomme opplysninger har egne regler. Kolleger ser at noen er borte, aldri hvorfor: fraværstype er en helseopplysning og vises kun for den det gjelder, nærmeste leder og administrator. Lønn vises aldri for andre enn den det gjelder, administrator, og eventuelt nærmeste leder hvis selskapet har slått det på.

Hva en leder «eier» avgjøres av organisasjonskartet, ikke av avdeling eller tittel. Rekkevidden er hele undertreet av ansatte som rapporterer til lederen, direkte eller indirekte.

Håndheving

  • Rekkevidde beregnes på serveren, per forespørsel. Samme beregning brukes både til å vise (rader utenfor rekkevidde hentes ikke) og til å handle (lagring avvises).
  • Rolle og orgkart er uavhengige, med vilje. Å stå som nærmeste leder i orgkartet gir ingen rettigheter uten lederrollen i systemet. Helseopplysninger er eksplisitt rollestyrt på toppen av orgkart-rekkevidden.
  • Vern i selve spørringen, ikke i skjermbildet. For en vanlig ansatt henter spørringen kun katalogfeltene. Fødselsdato, lønn, ansettelsesstatus og startdato forlater aldri databasen for den brukeren.
  • Synlighet per dokument. Én regel brukes overalt der dokumenter leses: nedlasting, dokumentlisten, ansattkortet, Min profil og den ansattes egen dataeksport. Bare administrator kan endre synlighet, og endringen logges.
  • Undersøkelser er enten anonyme eller åpne, og det står tydelig på svarskjemaet før man svarer. I anonyme undersøkelser lagres svarene uten kobling til person, og navn hentes aldri sammen med svar — heller ikke i eksport.

4. Hvordan vi vet at det virker

Beskrivelsene over er ikke bare intensjon. Den statiske vakten kjører automatisk foran hvert bygg; databasetestene kjøres i CI mot en midlertidig databasegren på hver endring, og aldri mot produksjon, siden de skriver rader.

  • «Feil selskap»-test. Logger inn som administrator i ett selskap og kaller hver side, handling og API-rute med IDer fra andre selskaper, 81 kall i alt. Kun et eksplisitt avslag teller som bestått; et krasj teller som feil. Testen kjøres med applikasjonsrollen, altså nøyaktig som produksjon.
  • Håndheving i databasen. For hver beskyttet tabell: uten selskapskontekst gir databasen null rader, med kontekst kun eget selskap, og forsøk på å flytte en rad til et annet selskap avvises av databasen selv.
  • Statisk vakt. Stopper deployen hvis en fil får nye databasespørringer mot selskapstabeller uten selskapsfilter, ut over en gjennomgått og begrunnet liste.
  • Synlighetsregelen. Egen test for dokumentsynlighet: administrator, opplaster, navngitt person, ansatt og leder, med og uten synlighet.
  • Oppstartskontroll. Serveren nekter å starte i produksjon hvis databaserollen den kobler til med kan omgå Row-Level Security, eller hvis en påkrevd hemmelighet mangler.
  • Løpende måling. Hvert avviste forsøk telles: avvist rolle, forsøk på tvers av selskap, nektet dokument-, rapport- og bildetilgang, feilet innlogging, invitasjon åpnet av feil mottaker, avvist signatur og feil jobb-token. Tallene oppsummeres ukentlig.

En ekstern gjennomgang i september 2026 bekreftet funnet fra vår egen kontroll: fra mai til 8. september koblet applikasjonen til som databaseeier, slik at policyene ikke ble evaluert. Perioden er vurdert mot personvernforordningens artikkel 33 i et eget notat. Oppstartskontrollen over gjør at feilen ikke kan gjenta seg stille.

Kjent begrensning: den som har eier-tilgang til databasen eller til driftsmiljøet ser alt, med unntak av lønn og sikkerhetskopiene, som krever nøkler som ikke kan leses ut derfra. Slik tilgang hindres ikke, men den oppdages: hver økt som databaseeier registreres hvert 15. minutt og avstemmes ukentlig mot loggen over nødtilgang og mot migrasjoner. De som har slik tilgang i dag er betrodde utviklere i Done, og det er få av dem.