← Back to Methodology
Methodology · Integrity checks

What "Verified" does and doesn't prove

Every .red.md verification runs up to seven integrity checks — six consistency checks and an ES256 signature check — before any behavioral analysis. This page states exactly what those checks guarantee, what they cannot prove, the edge cases, and what the recorder captures beyond the seven scored signals. Anything stronger than what's written here is an overclaim.

The seven checks

The first five recompute the same published hash — a fast, deterministic, non-cryptographic triple-accumulator function (provChainHash in src/provenance/util.mjs) — over different slices of the bundle. The SHA-256 seal repeats the bundle seal with a cryptographic hash. The signature check verifies an ES256 JWS. Checks for fields a file doesn't carry (v1 exports, unsigned exports) are reported as not applicable, never silently passed.

CheckWhat it recomputesWhat a pass means
Bundle sealHash of the whole bundle JSON minus the seal fieldNo part of the bundle — events, manifests, metadata — differs from what was sealed at export.
Session chainEach manifest's prevChainHead against the prior manifest's chainHeadNo session manifest was removed from the middle of the history or reordered.
Document body hashHash of the manuscript text above the annotation blockThe prose in the file is the prose the recording ended with.
Manifest integrityEach manifest's chainHead from its own contentsNo field inside any individual manifest was edited.
Event chain (bundle v2, 2026-06-11)Rolling hash chain over every event (h_i = H(h_{i-1} ‖ event_i)), whole-stream plus a per-session head sealed inside each manifestNo event was altered, inserted, or removed — and if one was, the break is localized to a session instead of "something changed." v1 exports: reported as not-applicable.
SHA-256 seal (bundle v2)Cryptographic hash over the same seal-free bundle JSON as the fast sealRaises the cost of collision games on the fast hash. Attached on async export paths; absent (not-applicable) on unload-time exports and v1 files.
Signature (signed exports, 2026-06-11)ES256 JWS over the whole annotation payload — document metadata, events, manifests, and both seals — against Red Stet's published public keysThe export was produced by the Red Stet signing pipeline and not modified since. Unsigned exports: reported honestly as intact-but-not-authenticated, never as verified-authentic.

All seven checks run entirely in the browser, against the file on the reviewer's machine, with zero network access — the public signing keys are inlined into the verifier page at build time rather than fetched. Anyone can recompute every check: the hash functions, the chain math, and the verification logic are open source.

The honest guarantee — consistency, not authenticity

The consistency checks (seal, chain, body hash, manifests, event chain, SHA-256) prove the file is internally consistent — that the document, events, and session manifests you are looking at agree with each other and with the hashes computed at export. They detect accidental corruption, truncation, and casual editing. They do not by themselves prove who produced the file or that a skilled party didn't regenerate the hashes after editing: the hash math is published, by design, so that anyone can recompute it — including someone who has modified the events and wants the seals to match again.

Resistance to deliberate forgery is the signature check, live in the standalone verifier since 2026-06-11: an ES256 JWS over the whole annotation payload, verified in-browser against Red Stet's published public keys (inlined into the page at build time — no network). On a signed export, the verdict reads "Verified — signed and internally consistent" and means exactly that: produced by the Red Stet signing pipeline, unmodified since. On an unsigned export — anonymous exports, the Docs extension's v0 local exports, files produced by tooling like the public sample generator — the verdict says "internally consistent (unsigned)" and the signature row states plainly that the file is intact but not authenticated. The verifier never upgrades an unsigned file to "authentic."

Remaining above the signature: the Sigstore Rekor transparency-log anchor (proof-of-when; badge renders when a record carries one, client-side inclusion-proof verification still to come) and the EAV encryption layer (proof the events stayed confidential in transit and at rest). A reviewer who needs authenticity should ask for the signed export; one who needs authenticity and a public timestamp should ask for the signed, anchored record.

Edge cases a reviewer should know

  • A bundle with no session manifests passes the chain checks vacuously. No manifests means no chain to break. The verifier says so explicitly when it happens. A bundle stripped of its manifests carries no session-level evidence — treat it accordingly. (Live exports avoid the common case: exporting mid-session synthesizes a manifest so the bundle carries the current session's summary.)
  • The body hash covers the manuscript text, not the rendered document. Markdown formatting, images referenced by URL, and anything outside the text layer are out of scope.
  • The checks say nothing about the behavioral analysis. Integrity and fingerprint are independent layers: a tampered-then-resealed unsigned bundle would pass the consistency checks and produce a fingerprint of whatever the editor wrote into it. The fingerprint is evidence about the recorded process; the checks are evidence the record is the one that was exported — under the limits stated above.

What the recorder captures beyond the scored signals

The seven scored signals are documented on their own pages. The recorder captures more than the scorer currently reads, and a methodology section that publishes its formulas should also publish its raw-data surface. Recorded today, not scored in the composite:

  • Session-manifest summary statistics — inter-key interval histograms, typo-correction counts, sentence-start pause median/p95, scroll totals, quick/long tab-away counts, read-selection counts, and per-pointer-kind usage time (kindUseMs). These travel in each session manifest as the "evidence summary."
  • Key hold durations — keyup events record how long each printable key was held. Unscored; a candidate signal (see Combined fingerprint → Signals under evaluation).
  • Input-provenance anomaly events — text insertions that arrive without a plausibly matching keydown are logged with their timing offset. Recorded for future analysis of synthesized input; not currently scored or surfaced.
  • Clipboard content — paste, copy, and cut events record their text content for replay fidelity, with sensitive material (card numbers, API keys, SSNs and similar) redacted at capture time via the paste gate, under the writer's explicit choice. Document snapshots record length, a hash, and 40-character head/tail samples.
  • A local author-profile baseline — the app aggregates per-identity session summaries across documents into a cumulative typing-rhythm baseline, intended to reduce false positives (a session matching its author's history downgrades isolated flags) and to surface sharp divergences from a stable history. This runs locally, is not part of the verifier's composite, and its methodology will get its own page before any divergence flag ships to reviewers.

The privacy treatment of all recorded data is covered in the privacy policy and the recorder consent surface. The rule this page adds: nothing the recorder captures stays undocumented here, whether or not it is scored yet.

Shipped strengthening (2026-06-11) and what remains

Four items from this page's original "planned" list shipped together as bundle format v2 plus the verifier signature check:

  1. Signature verification in the standalone verifier — shipped. ES256, in-browser, keys inlined at build time. The "intact ≠ authenticated" gap on this page now closes for signed exports.
  2. Per-event hash chain — shipped (bundle v2). Whole-stream rolling chain plus per-session heads sealed inside each manifest; tampering localizes to a session. Honest scope unchanged: it localizes edits; it does not prevent regeneration without the signature.
  3. SHA-256 seal alongside the fast hash — shipped (bundle v2, async export paths). Hardening, not a guarantee change: authenticity still comes from signatures, not better hashes.
  4. Scoring-weights version in the bundle — shipped (bundle v2, weightsVersion). The verifier notes when a bundle was exported under different weights than it is being scored with; the version table lives on the combined fingerprint page.

Still ahead:

  1. Signed exports everywhere. Signing requires a signed-in session today; anonymous exports and the Docs extension's local exports are unsigned (and reported as such). Extending signing to the extension via the same pipeline is the gate for its public release.
  2. Client-side Rekor inclusion-proof verification (EAV-2) — the anchor badge currently reflects server-side verification state.
  3. EAV-1 encryption layer — confidentiality of the event stream at rest, per docs/EAV_SPEC.md.

The rule stands: the published guarantee changes only when the implementation does, and this page is the changelog.