Integriteten i revisjonskjeden
Hver administrativ handling som endrer tilstand i fremforge-organisasjonen din, som endringer i SSO-konfigurasjonen, overstyringer av push-beskyttelsen, oppdateringer av branchbeskyttelsen, endringer i fakturering og SCIM-klargjøring, registreres i en revisjonslogg. fremforge går et steg lenger enn en vanlig logg: hver oppføring er kryptografisk kjedet til den forrige, og toppen av kjeden WORM-forankres (Write-Once-Read-Many) i T Cloud Public OBS-lagring med Object Lock hvert 2. minutt.
Resultatet: du kan oppdage enhver manipulering av revisjonsloggen, og du kan verifisere det selv uten å stole på fremverks ord.
Denne siden beskriver hva kjeden garanterer, hva den ikke garanterer, og hvordan du utfører verifiseringen fra ende til ende. Den tekniske forpliktelsen står i DPA vedlegg A.7.
Garantien
For hver oppføring i revisjonsloggen som registreres for organisasjonen din, lagrer fremforge:
Selve hendelsen (aktør, handling, tidsstempel, felt).
En
prev_hash, hashen av den forrige oppføringen for organisasjonen din.En
hash, SHA-256 over den kanoniske JSON-en for oppføringen.Kanoniseringen er eksakt, og rekkefølgen nedenfor er alfabetisk etter nøkkel, ikke rekkefølgen feltene er listet i andre steder på denne siden. En verifikator som hasher dem i en hvilken som helst annen rekkefølge, får en annen digest og konkluderer, feilaktig, med at kjeden er brutt:
sha256( {"action":…,"actor":…,"created_at_iso":…,"fields_json":…,"prev_hash":…,"tenant_id":…} )Ingen mellomrom.
prev_hasher den bokstavelige verdiennullved kjedens epoke.created_at_isoer tidsstempelet somYYYY-MM-DDTHH:mm:ss.sssZ.fields_jsoner nyttelasten som en JSON-streng, innebygd som en streng og ikke som et nestet objekt, slik at den gjengis byte for byte i stedet for å serialiseres på nytt. Den siste detaljen er den som lurer folk: parser du nyttelasten og serialiserer den på nytt, vil ikke digesten din stemme med vår.
Siden hashen for hver oppføring inkluderer den forrige hashen, bryter en endring i en hvilken som helst oppføring kjeden
fremover. GET /orgs/{org}/audit/chain returnerer de rå radene, slik at du kan oppdage det selv;
GET /orgs/{org}/audit/integrity rapporterer gjennomgangen vi gjorde.
I tillegg skriver en egen forankringsjobb hvert 2. minutt (tenant_id, latest_hash, count, timestamp) til T Cloud Public OBS med Object Lock-oppbevaring på 1095 dager (3 år), i COMPLIANCE-modus. Forankringsobjektet er fysisk umulig å slette innenfor oppbevaringstiden; lagringslaget avviser slettinger fra alle, også fra fremverk. En angriper som på en eller annen måte endret hele kjeden i databasen, ville fortsatt måtte forholde seg til forankringene i OBS, som ikke stemmer overens.
Åpenhet om hull. Intervallet på 2 minutter er målet; vi lover ikke en kontraktsfestet RPO på ≤2 min for forankringen av kjeden. Hvis T Cloud Public OBS ikke kan nås (regionalt vedlikehold, nettverkshendelse), prøver forankringsjobben igjen ved neste tikk og registrerer hullet i kjedens metadata. Det verste observerte vinduet før alarmen for brudd i kjeden går, er 12 minutter (intervall + terskelen ANCHOR_STALE). Hull dokumenteres i neste hendelsesrapport på statussiden og nevnes i DPA §A.7 om revisjonslogging.
Hva dette fanger opp
| Trussel | Fanget opp? |
|---|---|
| Innholdet i én revisjonsrad endres (aktør, handling, felt) | ✓, hash_mismatch på den raden |
| Én rad slettes fra midten av kjeden | ✓, prev_hash_mismatch på raden etter |
| Hele kjeden skrives om av en angriper med full skrivetilgang til databasen | ✓ hvis omskrivingen skjedde for mer enn ~10 min siden (12 minutter i verste fall), stemmer ikke WORM-forankringen |
| Hele kjeden skrives om + WORM-bøtten manipuleres også | Object Lock i lagringslaget avviser fysisk skrivingen til OBS; ville kreve kompromittering på T Cloud Public-siden |
| En administrativ handling som ikke sender noen revisjonshendelse i det hele tatt | Dette er et hull i dekningen, ikke et brudd i kjeden; se «Hva dette ikke fanger opp» |
Hva dette ikke fanger opp
- Hull i dekningen. Hvis en kodesti endrer tilstand uten å sende en revisjonshendelse, er kjeden taus. Vi dekker rutene som endrer tilstand, i vedlegg A.7; vi gjennomgår rutene hvert kvartal for å bekrefte at dekningen holder.
- Historikk fra før vedlegg A.7. Revisjonshendelser som ble sendt før forankring av kjeden ble slått på for organisasjonen din, har en
pre-chain-epoch-markør og er uttrykkelig IKKE en del av den verifiserbare kjeden. - Lesehendelser. Kjeden registrerer bare endringer. En lekkasje av lesetilgang (noen ser data de ikke skulle sett) vil ikke vises som en oppføring i kjeden. Revisjonsloggen registrerer lesingen der ruten sender en hendelse, men dekningen av ruter som bare leser, er en egen garanti, ikke en garanti fra kjeden.
Verifiser kjeden selv
Dette er en lokal ny beregning, ikke en avlesning av en status. fremforge audit-verify laster ned
de rå radene fra GET /orgs/{org}/audit/chain, hver med sin hash og prev_hash, og
beregner hver digest og hvert ledd på nytt på din maskin. Deretter henter den vår egen vurdering og
sammenligner. Avslutningskoden er ditt resultat; uenighet mellom de to rapporteres og
får kommandoen til å feile.
Forskjellen betyr mer enn det kan se ut som. Alt ovenfor denne seksjonen beskriver en garanti mot noen som når databasen, men ikke API-et: WORM-forankringen er i Object Lock COMPLIANCE-modus, så en manipulert database kan ikke bringes til å stemme med den. Ingenting av dette begrenser selve API-et, og frem til august 2026 ble krysskontrollen mellom gjennomgangen av kjeden og forankringen utført av den samme parten som rapporterte svaret. Lokal verifisering er det som gjør garantien kontrollerbar for deg, i stedet for noe vi bare påstår.
Forankringen er signert, og det er du som verifiserer signaturen, ikke vi. Hver forankring skrives med en
DSSE-konvolutt signert med den samme Ed25519-nøkkelen som SLSA-byggeproveniensen vår, og den offentlige halvdelen
er publisert på
www.frem.sh/.well-known/slsa-trust-root.json.
fremforge audit-verify henter denne tillitsroten direkte fra www.frem.sh, ikke fra
API-et, og det finnes ingen reserveløsning med en nøkkel som API-et leverer; en signatur som sjekkes mot en nøkkel
den reviderte parten ga deg, beviser ingenting. Deretter sjekker den at konvoluttens subject-digest
er lik sha256(anchor_head), slik at en konvolutt som er kryptografisk gyldig for en annen
forankring, avvises i stedet for å godtas.
To ærlige forbehold:
- Forankringer skrevet før 2026-08-04 er usignerte og rapporteres som
NOT CHECKED. Det finnes ingen signering i ettertid: verdien av en forankring er at den ble skrevet på et bestemt tidspunkt under Object Lock, og å skrive om historikken for å legge til en signatur ville motvirke nettopp det. - Signering er med vilje ikke fatal på vår side. Hvis signeringen feiler, skrives forankringen
likevel; en usignert forankring er langt bedre enn ingen forankring, fordi forankringen er
sikkerhetsnettet som avslører manipulering. Vi har en alarm på det (
AUDIT_ANCHOR_UNSIGNED, Major), slik at forringelsen er synlig og ikke stille, ogaudit-verifyrapportererNOT CHECKEDi stedet for å late som.
Bruk fremforge-CLI-en:
# Install (one-liner — see /cli/ for manual download and SHA-256 verification)
curl -sSfL https://cli.frem.sh/cli/install.sh | sh
# Configure auth — generate a PAT at https://frem.sh/user/settings/applications
# with the audit:read scope.
export FREMFORGE_TOKEN='<your PAT>'
# Verify the chain for your org
fremforge audit-verify acme --humanUtdataene ser slik ut:
✓ local verification: ok
(hashes recomputed on this machine — the server was not asked)
walk_mode: tail
rows_walked: 1284
verified_count: 1280
pre_chain_epoch_count: 4
chain_broken_count: 0
tenant_erased_count: 0
payload_redacted_count: 0
last_verified_hash: a2b3c4...
✓ WORM anchor (OBS Object Lock):
anchor_head: f8e9d0...
chain_tip_at_anchor: a2b3c4...
count_at_anchor: 1280
timestamp: 2026-05-05T18:00:00.000Z
age_seconds: 120
agrees_with_local_walk: true
signature: VERIFIED (keyid fremforge-slsa-builder-v1)
against the trust root fetched from www.frem.sh, not from this API —
so the anchored tip is the tip that was anchored.
server verdict: ok
server agrees with the local walk.Uten --human skriver CLI-en ut rå JSON for skripting, inkludert begge vurderingene og eventuell
uenighet mellom dem:
# Exit 0 only if YOUR walk was clean and ours agreed
fremforge audit-verify acme || echo "verification failed: $?"Avslutningskodene, alle utledet fra den lokale gjennomgangen:
0: kjeden ble verifisert, og vår vurdering stemte overens2: delvis: enten finnes detchain-broken-markørrader (vi skrev revisjonsraden, men kjedetransaksjonen feilet, så raden er bevart for synlighetens skyld, og kjeden mangler et ledd der), eller grensen for antall rader avkortet gjennomgangen, så deler av kjeden ble ikke sjekket. Merk at vi rapportererokpå en avkortet gjennomgang, mens CLI-en ikke gjør det; å bekrefte rader ingen har gått gjennom, er nøyaktig den typen overdrivelse denne kommandoen finnes for å unngå.3: brutt: den nyberegnede hashen for en rad stemmer ikke med den lagrede hashen, ELLER radensprev_hashstemmer ikke med den løpende kjeden. Utdataene inneholder rad-ID-enfirst_breakog årsaken.4: forankringen stemmer ikke: toppen som er WORM-forankret, finnes ikke i kjeden din, noe som betyr at den forankrede raden ble slettet eller endret. Merk at dette er en sjekk av inneholdelse: en aktiv organisasjon der de nyeste radene ennå ikke er forankret, er normalt og består.5: vi var uenige: gjennomgangen din var ren, men vår vurdering var det ikke. Som regel en rad som ble lagt til mellom de to kallene. Kjør på nytt for å bekrefte; hvis det vedvarer, ser vi noe du ikke ser.
Retningen på en uenighet er ikke symmetrisk, og CLI-en sier hvilken den fant. At vår
vurdering er verre enn din, skyldes som regel timing. At vår vurdering er bedre enn
din, altså at vi sier ok der din egen utregning sier broken, er nettopp tilfellet hele denne mekanismen
finnes for å avdekke, og det rapporteres som en hendelse, ikke som en advarsel.
Hva vi gjør internt
Toppen av kjeden forankres hvert 2. minutt i WORM-lagring, og forankringskjeden verifiseres uavhengig på nytt etter en kontinuerlig plan: hver organisasjons forankringskjede gjennomgås fremover fra starten og sjekkes for kontinuitet. Ethvert avvik, eller enhver organisasjon der forankringen blir foreldet (eldre enn ~10 minutter; 12 minutter i verste fall), varsler vakthavende umiddelbart, som en tidlig indikator på at skrivingen av forankringer har stoppet. Virkningen for kunder dekkes av DPA §11A, og hull dokumenteres på statussiden vår etter en hendelse.
Pseudonymisering under GDPR
Når du bruker retten til sletting, blir revisjonshendelsene for organisasjonen din pseudonymisert, ikke slettet: feltet actor blir [erased], og fields_json tilbakestilles til {}. Leddet i kjeden (hashen) beholdes, slik at kjeden fortsatt kan verifiseres; personopplysningene fjernes.
Det betyr at en kjøring av fremforge audit-verify mot en slettet organisasjon vil vise
tenant_erased_count > 0, og disse radene rapporteres separat i stedet for som brudd: en
pseudonymisert rad stemmer med vilje ikke lenger med sin egen hash, mens leddet til
den neste raden fortsatt sjekkes. De fem tellerne (verified_count, pre_chain_epoch_count,
chain_broken_count, tenant_erased_count, payload_redacted_count) summerer ikke til
rows_walked: én rad kan være både slettet og ha redigert nyttelast, og telles da under begge.
Kjeden er intakt; innholdet er fjernet. Selve radene slettes ikke når oppbevaringsvinduet på 3 år for WORM-forankringen utløper; ingen jobb sletter dem i dag (rettet 2026-10-08: denne siden sa tidligere at de ble slettet).
Uavhengig verifisering
Revisorer kan be om en gjennomgang av kjeden fra ende til ende under NDA; send e-post til compliance@frem.sh for den tekniske vurderingspakken.