Hvelvet
Ingen funn er forseglet ennå. Den dagen tribunalet dømmer et funn til forsegling, vises hashen her samme dag — og innholdet forblir kryptert til en avforsegling.
Tribunalet forsegler funn som er systemisk viktige, men der bevisgrunnlaget ennå ikke bærer publisering. Det forseglede innholdet lagres kryptert og privat — det offentlige er beviset for at funnet fantes, i en gitt form, på et gitt tidspunkt. Forseglede funn identifiserer aldri privatpersoner.
Tre utfall
Hvert funn tribunalet behandler ender i nøyaktig ett av tre utfall, etter faste kriterier — ingen forsvinner sporløst, og et avvist funn beviser at filteret virker like mye som et publisert funn gjør.
Publisert
Strengt flertall av de fire dommerne stemmer for å publisere; uavgjort taper konservativt. Funn som navngir en person krever i tillegg full benk og gjennomført kontradiksjon før publisering.
Forseglet
Systemisk viktig, men bevisgrunnlaget bærer ikke publisering ennå — enten fordi bevisene modnes, eller fordi påstandens skarphet overgår det som i dag er dokumentert. Forsegles bare når ingen enkeltperson navngis; artefaktet krypteres, hashen blir offentlig.
Avvist
Verken publisering eller forsegling når fram — deriblant automatisk for ethvert funn som navngir en person uten å nå publiseringsstandarden. Avvisningene begrunnes og publiseres i sin helhet, akkurat som et funn som slipper gjennom. Avvist to ganger uten en ny kilde, lukkes saken.
Avforseglinger
En avforsegling er en ny publiseringsbeslutning, ikke en mekanisk utløser: tribunalet prøver artefaktet på nytt mot dagens fakta. Bekreftelse og avkreftelse publiseres begge — med samme synlighet.
Ingen forseglinger er åpnet ennå. Den første avforseglingen — enten den bekrefter eller avkrefter det forseglede funnet — publiseres her, med lenke til hele artefaktet.
Etterprøv selv
Alt du trenger er en terminal med node og git. Instruksene under er de samme som er publisert i det offentlige ankerarkivet — et forseglet funn kan først etterprøves fullt ut når det avforsegles eller publiseres, for det er da det kanoniske artefaktet blir offentlig. Fram til da kan du kontrollere at hash, ankerforpliktelse og tidsstempel allerede står fast.
Akkurat nå er ingen funn publisert eller avforseglet — steg 1 under har derfor ingen ekte FUNN-ID å sette inn ennå, og kommandoen vil svare 404. Det er ikke en feil på denne siden; det er den ærlige tilstanden. Steg 4 (ankerforpliktelsen i det offentlige arkivet) kan du derimot kontrollere allerede nå, for hvert forseglet funn over.
Publiserte og avforseglede funn serveres som kanonisk JSON fra API-et. Feltet canonical i svaret er selve artefaktet som ble hashet.
curl -s https://www.folkefakta.no/api/findings/FUNN-ID -o svar.jsonHashen tas over en kanonisk serialisering, ikke over rå JSON. Protokollregelen, ordrett fra protokollfilen (scripts/institution/lib/canonical.js): "JSON with object keys sorted by UTF-16 code-unit order, arrays in given order, no whitespace, hashed as SHA-256 over UTF-8 bytes." Altså: objektnøkler sortert i UTF-16-kodeenhetsrekkefølge (vanlig JavaScript-sortering), arrayer i sin opprinnelige rekkefølge, ingen mellomrom — rekursivt gjennom hele objektet. Snutten under er et byte-for-byte-portert uttrekk av selve protokollfilen, inkludert sperrene den håndhever: den kaster et unntak på NaN, Infinity, undefined, funksjoner og objekter som ikke er rene JSON-objekter, i stedet for å kode dem stille om til noe annet. Lagre den som kanonisk.js og kjør den eksakte kommandoen:
// node kanonisk.js < svar.json | shasum -a 256
function kanonisk(v) {
if (v === null) return 'null';
const t = typeof v;
if (t === 'boolean' || t === 'string') return JSON.stringify(v);
if (t === 'number') {
if (!Number.isFinite(v)) throw new Error('kanonisk: non-finite number');
return JSON.stringify(v);
}
if (t !== 'object') throw new Error('kanonisk: unsupported type ' + t);
if (Array.isArray(v)) return '[' + v.map(kanonisk).join(',') + ']';
const proto = Object.getPrototypeOf(v);
if (proto !== Object.prototype && proto !== null) throw new Error('kanonisk: only plain objects allowed');
const keys = Object.keys(v).sort();
return '{' + keys.map((k) => JSON.stringify(k) + ':' + kanonisk(v[k])).join(',') + '}';
}
var raw = '';
process.stdin.on('data', function (c) { raw += c; });
process.stdin.on('end', function () {
var svar = JSON.parse(raw);
process.stdout.write(kanonisk(svar.canonical || svar));
});Delta
Oppskriften over er ekte — kjør den selv. Har du et spor et forseglet funn bør vurdere?
node kanonisk.js < svar.json | shasum -a 256 skriver ut heksadesimalhashen. Snutten er den samme koden som verify.js i ankerarkivets README og i docs/institution/verifisering.md — bare navnet på funksjonen er oversatt. Den er pinnet mot de samme testvektorene som protokollfilen selv (scripts/institution/lib/canonical-vectors.json), og en test feiler hvis denne siden og den publiserte dokumentasjonen noen gang skiller lag.
Resultatet skal være tegn for tegn likt sha256-verdien på denne siden — og sha256-linjen i filen vault/FUNN-ID.txt i ankerarkivet. Stemmer det ikke, er innholdet endret etter forseglingen. Det er hele poenget med hvelvet: et avvik er et bevis, ikke en bortforklaring.
Hashene skrives ved forsegling til et offentlig append-only ankerarkiv — bare hasher og journalrøtter, ingen kode, intet innhold. Klon det og se når posten faktisk ble skrevet til historikken. Commit-datoen er depoteierens påstand om tidspunkt; neste steg viser hvorfor du ikke må stole blindt på den.
git clone https://github.com/monscorps/folkefakta-anker
cd folkefakta-anker
git log --follow -- vault/FUNN-ID.txtAnkerforpliktelsen som er oppgitt for hver forsegling ovenfor, skal finnes i denne historikken og inneholde nettopp den filen.
Dette er beviset som er uavhengig av depoteieren: en .ots-fil forankrer postfilen til Bitcoin-blokkjeden. To måter å sjekke den på — dra postfilen og .ots-nabofilen inn på opentimestamps.org, eller bruk kommandolinjen:
ots verify vault/FUNN-ID.txt.otsFerske .ots-bevis kan i en periode vise "pending" — beviset er sendt til en kalendertjeneste, men ennå ikke bekreftet i en Bitcoin-blokk. Det gjelder blant annet det nyeste beviset i arkivet i dag. Det blir gyldig og verifiserbart automatisk når blokken kommer, uten at noen i Folkefakta gjør noe. Fram til da er tidsstempelet for den posten sporbart i git-historikken, men ikke uavhengig bevist.
Git-historikk under depoteierens kontroll er i prinsippet forfalskbar av depoteieren: den som har skriverettigheter, kan i teorien slette og skrive om historikken. Det er derfor OpenTimestamps-bevisene finnes — de gir en uavhengig, offentlig etterprøvbar tidsstempling av en post, som hvem som helst kan kontrollere selv, uten å stole på GitHub eller på Folkefakta (se steg 5 over for hva beviset konkret forankrer i).
Den operative databasen bak Folkefakta er mutable: rader kan endres, rettes og slettes — blant annet fordi persondata skal kunne slettes på ekte. Ankerarkivet beviser derfor ikke at databasen til enhver tid er "riktig". Det beviser om historikken har endret seg siden forrige ankring. En hash som ikke lenger stemmer, er bevis for at noe er endret — ikke bevis for hva som opprinnelig var sant.
Ankerforpliktelsene er per i dag usignerte (nøkkelen som er publisert i allowed_signers er passordbeskyttet, og den ubemannede ankringsjobben verken har eller skal ha passordet). Sjekk git log --show-signature på en aktuell commit for å se om signering er aktiv akkurat nå — og les datostemplene deretter.
Hele tillitsmodellen og de nøyaktige postformatene står i ankerarkivets README — samme instruks som på denne siden.