The Vault
No findings have been sealed yet. The day the Tribunal seals one, its hash appears here the same day — and the content stays encrypted until an unsealing.
The Tribunal seals findings that are systemically important but whose evidence does not yet carry publication. Sealed content is stored encrypted and private — what is public is the proof that the finding existed, in a given form, at a given time. Sealed findings never identify private individuals.
Three outcomes
Every finding the Tribunal hears ends in exactly one of three outcomes, decided by fixed criteria — nothing disappears without a trace, and a rejected finding proves the filter works just as much as a published one does.
Published
A strict majority of the four judges votes to publish; a tie loses conservatively. Findings that name a person additionally require the full bench and completed contradiction rights before publication.
Sealed
Systemically important, but the evidence does not yet carry publication — either because the evidence is still maturing, or because the sharpness of the claim exceeds what is documented today. Only seals when no individual is named; the artifact is encrypted, the hash becomes public.
Rejected
Neither publication nor sealing is reached — including automatically for any finding that names a person without meeting the publication standard. Rejections are reasoned and published in full, exactly like a finding that gets through. Rejected twice with no new source, the case closes.
Unsealings
An unsealing is a fresh publication decision, not a mechanical trigger: the Tribunal re-hears the artifact against current facts. Vindication and disproof both publish — at equal prominence.
No seals have been opened yet. The first unsealing — whether it vindicates or disproves the sealed finding — publishes here, with a link to the full artifact.
Verify it yourself
All you need is a terminal with node and git. The instructions below are the same ones published in the public anchor repository — a sealed finding can only be fully verified once it is unsealed or published, because that is when the canonical artifact becomes public. Until then, you can check that the hash, the anchor commitment, and the timestamp are already on the record.
Right now, no finding is published or unsealed — so step 1 below has no real FINDING-ID to substitute yet, and the command will answer 404. That is not a bug on this page; it is the honest state. Step 4 (the anchor commitment in the public repository), by contrast, you can already check today, for every sealed finding above.
Published and unsealed findings are served as canonical JSON from the API. The canonical field of the response is the artifact that was hashed.
curl -s https://www.folkefakta.no/api/findings/FINDING-ID -o svar.jsonThe hash is taken over a canonical serialization, not over raw JSON. The protocol rule, verbatim from the protocol file (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." That is: object keys in UTF-16 code-unit order (plain JavaScript sort), arrays in their original order, no whitespace — recursively through the whole object. The snippet below is a byte-for-byte port of the protocol file itself, including the guards it enforces: it throws on NaN, Infinity, undefined, functions and any object that is not a plain JSON object, rather than silently encoding them as something else. Save it as kanonisk.js and run the exact command:
// 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));
});Take part
The recipe above is real — run it yourself. Do you have a lead a sealed finding should weigh?
node kanonisk.js < svar.json | shasum -a 256 prints the hex hash. This is the same code as verify.js in the anchor repository README and in docs/institution/verifisering.md — only the function name is translated. It is pinned against the same test vectors as the protocol file itself (scripts/institution/lib/canonical-vectors.json), and a test fails if this page and the published documentation ever drift apart.
The result must match, character for character, the sha256 value on this page — and the sha256 line in vault/FINDING-ID.txt in the anchor repository. If it does not, the content changed after sealing. That is the entire point of the vault: a mismatch is evidence, not an excuse.
Hashes are written at seal time to a public append-only anchor repository — hashes and ledger roots only, no code, no content. Clone it and see when the record actually entered the history. The commit date is the repo owner’s claim about time; the next step shows why you need not take it on faith.
git clone https://github.com/monscorps/folkefakta-anker
cd folkefakta-anker
git log --follow -- vault/FINDING-ID.txtThe anchor commitment listed for each seal above must exist in this history and contain exactly that file.
This is the proof that is independent of the repo owner: an .ots file anchors the record file to the Bitcoin blockchain. Two ways to check it — drag the record file and its .ots neighbor onto opentimestamps.org, or use the command line:
ots verify vault/FINDING-ID.txt.otsFresh .ots proofs can read "pending" for a while — the proof has been submitted to a calendar service but not yet confirmed in a Bitcoin block. That is true of the newest proof in the repository today. It becomes valid and verifiable automatically once the block lands, with no action from anyone at Folkefakta. Until then, that record’s timestamp is traceable in git history but not independently proven.
Git history under the repo owner’s control is, in principle, forgeable by the repo owner: whoever holds write access can in theory delete and rewrite the history. That is exactly why the OpenTimestamps proofs exist — they give independent, publicly verifiable timestamping of a record, checkable by anyone without trusting GitHub or Folkefakta (see step 5 above for what the proof anchors to).
The operational database behind Folkefakta is mutable: rows can be changed, corrected, and deleted — among other reasons because personal data must be genuinely erasable. The anchor repository therefore does not prove the database is currently "correct". It proves whether history has changed since the last anchoring. A hash that no longer matches is evidence that something changed — not evidence of what was originally true.
Commits in the anchor repository are currently unsigned (the key published in allowed_signers is passphrase-protected, and the unattended anchoring job neither has nor should have the passphrase). Check git log --show-signature on any given commit to see whether signing is active right now — and read the datestamps accordingly.
The full trust model and the exact record formats are in the anchor repository’s README — the same instructions as on this page.