LIVE · AUDIT-KÆDE · EU-HOSTET
SYSTEM · 99,99 % OPPETID
v 1.0 ↗ FREMSTILLET I EU

Begreber

Hvad en Session, en bevisrække og en Audit-kæde faktisk er, med så få ord som muligt. Læs dette én gang, og API-referencen vil give mening.

Organisation

Den øverste tenant. Én org svarer til én kundekonto. Alle andre ressourcer (sessioner, beviser, audit-events, brugere) er scoped til en Org via row-level security på de underliggende Postgres-tabeller. En fejl i applikationskoden kan ikke krydse tenants — databasen vil afvise forespørgslen.

En Org har: medlemmer (brugere med rollebaseret adgang), branding (logo / farver / PDF-footer), et faktureringsabonnement, valgfri KYB-data om den juridiske enhed, valgfri SSO-konfiguration og en opbevaringspolitik.

Medlem, Rolle, Tilladelse

En Medlemskab er sammenkædningen mellem en User og en Org. En bruger kan have medlemskaber i flere orgs og skifte mellem dem (den aktive org følger med som et JWT-claim).

Hver Org opretter fire systemroller ved oprettelse:

  • org_admin — fuld kontrol. Fakturering, medlemmer, branding, opbevaring.
  • inspector — kan udføre inspektioner, registrere beviser, underskrive rapporter.
  • observer — skrivebeskyttet adgang til sessioner + audit-data.
  • auditor — skrivebeskyttet adgang plus tilladelse til kædeverifikation.

Org-administratorer kan oprette brugerdefinerede roller ved at sammensætte tilladelseskataloget. Tilladelser slug-tjekkes i view-laget + krydstjekkes af RLS i DB-laget.

Session

Én inspektion. Faktureringsenheden (du betaler pr. lukket session) og bevisenheden (en audit-kæde er pr. session, ikke pr. org).

En session har: en operatør (dit teammedlem, der startede den), en eller flere deltagere (feltbrugeren plus valgfrie observatører), samtykkestatus, valgfri GPS-position, valgfrie noter, en audit-kæde og — når den er lukket — TSA-forankrede tidsstempeltokens.

Deltager

Én person i en session. Der er én operatør pr. session og mindst én feltbruger; valgfrie yderligere observatører understøttes. Feltbrugere deltager via en engangs-signeret URL (ingen konto påkrævet); operatører + observatører er medlemmer af Org'en.

Bevis

Et stykke registreret bevis under en session. Typer:

  • snapshot — stillbillede fra feltbrugerens kamera.
  • annotation — tegning lagt oven på et snapshot eller whiteboard.
  • whiteboard — Excalidraw-lærred i sessionen eksporteret som PNG + tilstand.
  • clip — kort videosegment.
  • document — uploadet fil (bruges af chat-laget til PDF-til-underskrift).

Hver bevisrække har en SHA-256 af sit binære indhold, gemt i audit-kæden. Manipulation af filen bagefter får verifikationen til at fejle.

Audit-kæde

Den kryptografiske rygrad. Hver event i en session — oprettelse af session, samtykke, GPS-registrering, bevisregistrering, annotering, whiteboard-lagring, underskrift, sessionens afslutning — udsender en AuditEvent række med:

{
  "session": "<uuid>",
  "sequence": N,
  "occurred_at": "<iso8601>",
  "kind": "evidence.snapshot_added",
  "actor": { "user": <id|null>, "participant": <id|null> },
  "payload": { /* event-specific */ },
  "prev_hash": "<sha256 of previous event>",
  "hash": "<sha256 of canonical_json of this event>"
}

Den første event bruger prev_hash = "0" * 64 (genesis). Hver efterfølgende event bruger den forrige events hash som prev_hash og øger sequence med 1. En Postgres advisory lock serialiserer skrivninger pr. session; en append-only-trigger blokerer UPDATE + DELETE på tabellen.

TimestampToken (TSA-forankring)

Ved sessionens afslutning (og ved operatørudløst "stamp nu") indsendes det aktuelle kædehoved til tre uafhængige tidsstemplingsmyndigheder:

  • YodaLedger — Tezos blockchain-forankring. ~15-20 minutters finalitet. Asynkron; vi får et callback, når blokken er bekræftet.
  • FreeTSA — RFC 3161-tidsstempel. Synkron; token returneres med det samme. Kan udskiftes med en betalt QTSP (DataSure) for eIDAS Art. 42-overholdelse.
  • OpenTimestamps — Bitcoin-forankring via OpenTimestamps kalenderprotokollen. Asynkron; opgraderingsstien kører på en Celery-sweep.

Tre er ved design — hvis én TSA forsvinder, forankrer de to andre stadig kæden. En revisor kan verificere mod hvilken som helst af dem uafhængigt ved hjælp af offentlige block explorers / verify-endpoints.

Underskrift (SES / AES / QES)

Tre eIDAS-niveauer, alle på den samme audit-rapport-PDF:

  • SES (Simpel elektronisk underskrift) — understøttet af audit-kæde, intet signeringscertifikat. Egnet til interne optegnelser.
  • AES (Avanceret elektronisk underskrift) — identitetsbundet signeringscertifikat, PAdES B-T-forankret. Egnet til de fleste B2B-kontrakter.
  • QES (Kvalificeret elektronisk underskrift) — højeste eIDAS-niveau, juridisk sidestillet med en håndskreven underskrift i hele EU. Låst bag KYB-verifikation af den udstedende organisation.

Kampagne (valgfri)

En logisk gruppering af sessioner til samlet rapportering — "Q2 2026 motorskader" eller "Byggeplads A afleveringsfejl". Sessioner kræver ikke en kampagne; det er en rapporteringsmulighed.

Webhook

En kunderegistreret URL, der modtager HMAC-signerede event-POST'er. Event-typer: session.created, session.completed, participant.joined, participant.left, evidence.added, recording.ready, audit.anchored, signature.completed, plus en webhook.test til leveringsverifikation.

Signatur: Stripe-stil t=...,v1=... header med HMAC-SHA256 over <timestamp>.<body>. SDK'ets constructEvent() helper verificerer i konstant tid med en 5-minutters clock-skew-tolerance.