Fact Provenance
PLAN v1.1
Public strategy · 17 September 2026

Rumours have no return address. We give them one.

This register does not decide what is true, and it is not in the truth business. It records where a claim came from: the first source we can find that put it into circulation, every source that repeated it afterwards, the licence it was published under, and the date we read it. Each record carries a cryptographic identity, so the trail can be checked by anyone and altered by no one — including us.

Claims held
1,465
from 16 source domains
Citable records
1,418
content-addressed, after Phase 2
Distinct assertions
1,161
64 of them corroborated today
Page hashes today
207
why origin is currently untraceable

01The thesis

Every rumour, every statistic, every “everyone knows” on the web is a sentence that has been copied more often than it has been checked. Almost none of the copies say where it came from. So the question people actually ask — who started this? — has no answer, and blame for a false claim lands nowhere, or on whoever happened to repeat it last.

The register answers that question with a paper trail: one record per source, one identity per claim, one chain from the earliest known publication to every repetition after it. Three things follow, and they are the whole point of the project:

  • Origin is marked. A claim gets a return address: the first source in the register that published it, dated, with the bytes we read.
  • Propagation is visible. Everyone who repeated it is listed in order, so copying is no longer indistinguishable from originating.
  • The trail cannot be quietly rewritten. Content-addressed ids and signed release manifests mean the record of who said what, when, is verifiable offline — by a journalist, a regulator, or the source named in it.

Truth is the source’s business. Provenance is ours. And provenance is what makes accountability possible — you cannot pin a rumour on anyone if you cannot say where it entered circulation.

02Why it hurts everyone

This is not a niche research problem. The absence of origin is a tax on every person who reads anything, and it lands hardest on the people with the least power to check.

Anyone reading
“Everyone says” is unfalsifiable

A claim with no source cannot be checked, only believed or dismissed. Whichever version gets repeated loudest and longest simply becomes the one in circulation.

Whoever is targeted
A rumour with no author cannot be answered

A person or business hit by a false claim has nothing to point at: no first publication, no chain of custody, no way to show the claim was copied rather than found.

Whoever got it right
The originator loses the credit

The body that did the work — the agency, the survey, the local reporter — is invisible once the number is loose, while the loudest repeater is treated as the authority.

Whoever publishes
Plagiarism is trivially easy

Copying a claim without its source is the default behaviour of the web, not the exception, because nothing makes the origin cheap to carry along.

Anyone building with text
Models launder rumour into fact

A false sentence repeated often enough becomes indistinguishable from a sourced one in a training corpus — and comes back out of the model with no citation at all.

Institutions
Nobody can evidence their own sourcing

Public bodies, courts, health services and newsrooms are increasingly asked to show where their facts came from. Doing that by hand, per case, is slow, expensive, and usually skipped.

The blunt version

Misinformation has no accountability because it has no provenance — it is one problem, not two. You cannot blame the right source if you cannot find the first one. Marking origin is what turns an unfalsifiable rumour into a traceable publication: a thing with a date, an owner, and a record anybody can re-check.

And the fix has to be free and public, because the value only exists if everyone can consult it. A provenance register behind a paywall answers the question for the people who already had it answered.

03Origin & propagation — the core feature

Two computed facts turn a pile of claims into a blame-capable register. Both come from the same identity layer, and both are stated as findings with evidence rather than as verdicts.

1 — Origin: the earliest record we hold

Every assertion (the claim itself, independent of who published it) collects all records that carry it, ordered by publication date. The earliest is the origin record: the first source in the register that put the claim into circulation, with its URL, its date, and the digest of the bytes we read. That is the return address.

Stated honestly, on every page

“First seen” means first seen by this register. Our crawl begins in September 2026 and covers a defined, listed set of domains. An origin record is the earliest publication we can evidence — not a claim that nothing came earlier. Absence of an earlier record is evidence about our coverage, never proof about the world. The register publishes its coverage and date range so nobody mistakes the edge of the dataset for the edge of reality.

2 — Propagation: everyone who repeated it, in order

After the origin record, every dated record sharing the assertion id is a repetition: same claim, different publisher, later date. The register lists them in sequence, counts them, and shows the gaps — the claim that went from one government page to twenty sites in a month, or the one that never travelled at all.

SignalWhat it tells youLive today
Origin recordEarliest publication of this claim in the register, with source and datederivable now, not yet surfaced
Record countHow many separate sources carry the claimup to 20 for one assertion
Corroborated assertionsClaims with more than one independent source64
Independent domainsRepetition across distinct publishers, not just pagescomputed at query time
Repetition intervalTime from origin to first repetition — how fast a claim travelsnew field, Phase 3
Chain of custodyOrdered list of every record, each with its own verifiable hashdata present, view is Phase 3

The propagation view is what makes the origin useful rather than merely interesting. “This started here and was copied 19 times” is a citable, checkable statement; “this is misinformation” is an opinion that invites a fight. We publish the first and refuse the second.

04The product

Four surfaces, each useful alone, all fed from one row in one database:

Surface 1
The index

Search and claim pages with an origin line, the propagation list and the licence. HTML for people, PROV-O JSON-LD or Turtle for machines, from the same URL.

Surface 2
The API

Keyless: claim lookup, search, domain stats, licence records, release manifests, and a verification endpoint returning an inclusion proof.

Surface 3
Badges & stamps

A one-line embed stating origin and record count: origin: epa.ie · 4 records. Every badge is a durable citation of the register.

Surface 4
Releases

Signed nightly manifest, periodic full dumps, mirrors able to verify everything without trusting our server.

Design principles

  • No model in the extraction path. Rule-based, deterministic, auditable, zero per-page token cost. The same page yields the same record in a year.
  • Point, do not rehost. Claim text, source URL, licence, date and fetch digest. Not page copies for redistribution.
  • No personal data. Claims are statements about the world; anything person-shaped is excluded by rule.
  • Nothing deleted, ever. Superseded records are marked and lineage kept, so a correction is itself part of the trail.
  • No verdicts. The register reports publication, date and repetition. It never says “false”, “misleading” or “disinformation” about a source.

05Where it stands

DimensionState at 17 Sep 2026Evidence
Public siteLive at factprovenance.org; all routes 200, dark full-bleed UI, favicon, content negotiation on claim URLscurl 200 on / and /claim/1
Register1,465 claims from 16 domains extracted from fetched pagescount = 1465
Licence gate1,174 public / 291 withheld — only 21 withholdings are genuine licence exclusions; 270 are hostname bugsdomain analysis
Claim identityDigest is per-page, not per-claim: 1,465 claims share 207 hashesdistinct digest = 207
Origin viewData exists (dates + sources) but nothing surfaces an origin line or propagation list yetno route exists
Nightly growthNewest Common Crawl release auto-followed; page budget steps 60 → 400 per domain, +40 a nightnightly, 03:00 UTC
Work in flightLicence-gate rebuild + badge/stamp endpoints running on a build nodebuild node, job service
Identity layerSpecified and proven on live data; not yet deployedroot sha256:d3c53ce1…
Known defect, found while specifying the crypto layer

The static export writes the digest with the algorithm prefix twice (sha256:sha256:…) while the API writes it once. The same field in two formats breaks naive consumers. Slated for the Phase 2 pass — exactly the kind of thing caught by re-deriving rather than trusting a report.

06Architecture

  1. Acquire — newest Common Crawl release, filtered to an allow-list of domains, plus direct fetch of licence and evidence pages. Raw bytes kept, fetch digest recorded.
  2. Extract — deterministic rules pull candidate claims (figures, dates, superlatives, attributions) with surrounding context. No LLM: same input, same output, forever.
  3. Gate — licence resolver decides public or withheld per domain from a licence record with URL and date. Unknown licence is withheld, never guessed.
  4. Identify — assertion id (normalised text) and record id (assertion + canonical source) computed per row; page digest kept beside them as fetch evidence.
  5. Attribute — per assertion: earliest dated record = origin, all later records = propagation, counts and intervals computed. A query over the same rows, not a second dataset.
  6. Publish — server renders HTML, PROV-O, JSON-LD and Turtle from one row; badges render from the same id; the nightly build commits a signed manifest.
  7. Distribute — badges and embeds, dataset releases for mirrors, open API for tooling.
LayerNowNext step
StoreSQLite, single file, WALPostgres past roughly a million records or when writers contend; SQLite stays as the portable mirror
ServeOne Python service under systemd, a commercial DNS and TLS providerStatic export of claim pages to a CDN so reads never touch the origin
CrawlNightly cron, stepping budgetPer-domain concurrency, robots.txt honouring, backoff on 429
IdentityPage digest onlyAssertion and record ids, Merkle manifest, Ed25519 signature (§07)
AttributionData present, no viewOrigin line, propagation list, repetition interval, chain-of-custody view

07Cryptographic identity

Origin attribution is worth nothing if the record of it can be edited afterwards. Today it can be: the digest hashes the whole page, so it identifies the page rather than the claim, every claim from one page shares one hash, and a refetch that changes a single byte orphans the lot. The fix is identity at two levels, both derived from content, so the identifier is the content.

LevelHashed overAnswersLive prototype
Assertion fp1-…Normalised claim text onlyWhat is being claimed1,161 from 1,465 claims
Record fp1-…Assertion id + canonical URL + date + kindWho published it, where1,418 records

Canonicalisation, versioned as fp1

  • Text: Unicode NFC, fold curly quotes and dashes, strip zero-width characters, collapse whitespace, trim.
  • URL: lowercase host, drop www./www2./m., drop default port, strip tracking parameters, sort query, drop fragment.
  • Date: ISO-8601 UTC or empty. Field order fixed; each id space domain-separated by a literal prefix so the two can never collide.
  • Rules frozen per version. An id embedded in someone else’s page must keep meaning the same thing; changing a rule means minting fp2 and keeping a legacy map.

What the two levels buy

Corroboration and origin stop being guesses: 64 assertions appear in more than one place, the most-travelled appears as 20 separate records, and the earliest of those is an origin with an owner and a date. A page-digest model cannot express any of it.

Commitment and proof — verified, not proposed

  • Each release builds a Merkle tree over the record ids: root sha256:d3c53ce1acf76b74… over 1,418 leaves.
  • Any single record is provable with an 11-hash inclusion proof (~352 bytes). Tested on 50 random records against the root, with forged records rejected, and small-tree tests passing at 1, 2, 3, 4, 5, 7, 8 and 9 leaves.
  • Tamper-evident: changing one character of one claim changes the root.
  • Append-only: each nightly manifest carries the previous manifest’s hash, so history cannot be quietly rewritten.
  • Attributable: the manifest is signed with an Ed25519 project key published at a fixed well-known path, with a key id so rotation is visible.
  • Externally anchorable to a public timestamp service, giving “this existed before date X” from a clock we do not control.
What the signature does and does not prove

It proves the register recorded a claim, unchanged, at a point in time, and names the source. It does not prove the claim is true, does not prove we read the page correctly, and does not prove the named source intended any harm. That boundary is printed on every claim page, because a provenance register mistaken for a truth machine is worse than none.

08Blame, done responsibly

Marking origin is the point of the project, and it is also the fastest way to build something that ruins innocent people’s lives. A register that says “this claim started here” is one careless design decision away from being a machine for accusing whoever is named first. These rules are part of the product, not a policy bolted on afterwards.

Rule 1
We mark publication, never intent

The register states who published a claim and when. It never characterises a source as a liar, a spreader or a culprit, and never uses the word disinformation about anyone.

Rule 2
A repeater is not an author

A source that repeated a claim may have been quoting it, reporting on it, or debunking it. The propagation list shows sequence, and says plainly that sequence is not authorship.

Rule 3
Coverage is published, so first-seen is never overstated

Every origin line carries the date range and domain list it was drawn from. The reader sees the edge of the dataset and judges the claim accordingly.

Rule 4
Right of reply, on the record

Any source named as an origin can respond. The response is stored, published alongside the record, and covered by the same identity and signing treatment.

Rule 5
Corrections are appended

A wrong origin is corrected in public and the old record stays visible with its lineage, because a register that hides its own mistakes cannot be trusted with anyone else’s.

Rule 6
Opt-out is one line, honoured nightly

A domain owner can withdraw; the build drops the records and the manifest records the withdrawal. Public accountability does not require anyone’s participation by force.

None of this weakens the project. It is what makes the output citable by journalists and defensible in a lawyer’s office — which is exactly where a provenance tool has to survive if it is going to hold anyone accountable at all.

09Licensing & legal posture

Public builds draw only on sources with a documented public licence: Wikipedia (CC BY-SA), Irish public sector (eGov/OGL), US federal (.gov, public domain), EU institutions (CC BY 4.0), plus named CC BY 4.0 publishers. News domains stay out of the public build entirely until explicitly cleared — the exposure there is real and the value is not worth it.

BucketCountReading
Withheld — genuine licence exclusion21Two news domains, all rights reserved. Correctly excluded.
Withheld — hostname bug270Openly licensed sources (ourworldindata.org 226, hse.ie 34, Teagasc 10) wrongly caught by a hand-kept host list. Fixing the gate releases them.
  • Attribution is enforced by the schema. Where a licence requires attribution or share-alike, the record carries the licence identifier and the attribution string; the public build refuses records whose attribution cannot be stated.
  • Our own metadata is released permissively — identifiers, URLs, licences, hashes, manifests, origin and propagation data — so mirrors and tooling have no friction. Claim text inherits its source’s licence and is marked as such.
  • Defamation and database rights reviewed before origin claims go public at scale. Naming an origin is a factual statement and we can evidence it; the page language, the reply mechanism and the coverage caveat keep it in the realm of fact rather than accusation.
  • No personal data. Claims are statements about the world, not about people. Anything person-shaped is excluded by rule and audited.

10Distribution & growth

  • Badges first. A one-line embed carrying the origin and the record count, linking back. Every badge is a durable citation of the register and a crawlable link. This is the growth engine; the API is the product for machines.
  • Dataset releases. Signed nightly manifests plus periodic full dumps, so mirrors, researchers and model builders consume without hammering the origin.
  • Origin checking for tooling. A small helper: given a passage, return the matching assertion, its origin record, its propagation list and its licence. This is the bridge from the register into retrieval and model pipelines — the natural place to fix rumour laundering at the source.
  • Reference ecosystems. Wikidata, open-data portals, academic libraries, data-journalism toolkits and fact-checking organisations are the natural places to be listed, cited and forked. Fact-checkers get the origin chain they currently assemble by hand.
  • Discoverability. Public claim pages, sitemap, open licence, and a dataset identifier so the register can be cited academically.

What we do not chase: no paid tier, no rate-limit business model, no news corpus, no truth verdicts. The register’s value rises with the number of independent users and mirrors, and both collapse the moment access is gated or the output becomes a judgement call.

11Scale & cost

StageRegister sizeStoreMonthlyGate to pass
Now1.5k claims, 16 domainsSQLite, one instance$12Licence gate correct; badges live
Next50k–100k claims, 100–300 domainsSQLite + static export to CDN$12–24Identity and origin shipped; crawl polite and resumable
Then1M claims, ~1k domainsPostgres + object storage for raw bytes$40–80Serving cost per request near zero; origin computed per assertion at build time
Further10M+ claimsPostgres + columnar exports; batch work on spare capacitymeteredMirrors take real read traffic; the origin is an origin again

Extraction is rule-based, so cost scales with bytes fetched rather than tokens, and the origin and propagation views are queries over rows we already hold. The dominant long-run cost is storage and bandwidth, and both fall once claim pages are exported statically.

12Risks

RiskSeverityMitigation
A named origin claims defamation, or suffers harassment because of the registerHigh§08 rules: publication not intent, coverage published, right of reply on the record, corrections appended, opt-out honoured nightly, no verdict language anywhere in the UI
First-seen is read as “the origin of the rumour” when it is only our earliest recordHighEvery origin line carries the dataset’s date range and domain coverage; the caveat sits on the page, not in a footnote
Copyright or database-rights challengeHighLicence allow-list only; point-don’t-rehost; per-domain opt-out; news excluded from public builds
A wrong attribution damages trust more than an empty registerMediumDeterministic extraction, evidence URL and fetch digest on every record, corrections appended with lineage, independent re-derivation of every landed change
Silent canonicalisation change breaks ids embedded in other people’s pagesMediumFrozen versioned rules; a new version mints new ids and keeps a legacy map so old URLs resolve
Register used as a weapon against a source that merely repeated a claimMediumPropagation list states sequence, never authorship; no ranking of sources by “spread”; no API field that reads as a score
Single-maintainer bus factorMediumOpen licence, documented pipeline, signed manifests and mirrors so the register survives us
Crawl blocks or rate limitsLowrobots.txt honoured, backoff, per-domain politeness, cached raw fetches; a blocked domain is skipped, not worked around
Hosting or DNS takedownLowStatic export and signed dumps: anyone can stand the register back up from a mirror and verify it

13Ownership & governance

  • Neutral project, not a company asset. Its own name and domain, with a plain “built by” line to the originating studio. Credibility with libraries, newsrooms and public bodies depends on that separation.
  • One append-only decision log. Licence policy, id version, key rotation, opt-outs and corrections are recorded with their evidence, so a future maintainer sees why as well as what.
  • Key custody. The signing key stays with the project owner; the public key is published; rotation is announced inside the manifest chain so it can never be mistaken for tampering.
  • Roles. One primary maintainer, with workstreams farmed out and every landed change independently re-derived by someone other than whoever built it. Self-reports are not evidence; claims are recomputed on the box.

14Milestones & KPIs

Phase 0
done · 16 Sep

Stand it up

Domain, DNS, hosting, nightly crawl, licence gate v1, UI with content negotiation. Delivered: live site, 1,465 claims, 16 domains.

Phase 1
in flight · 17–18 Sep

Trustworthy corpus, and embeddable

Rebuild the licence gate from licence records — kills the 270 false withholdings and takes the public set to roughly 1,444 — and ship badges, stamps, embeds and the verification endpoint. Exit gate: independent recount per domain, both SVGs parsed as XML, every new route returning exact content types, three licence evidence URLs spot-checked by hand.

Phase 2
spec ready · 18–20 Sep

Cryptographic identity

Assertion and record ids into the pipeline, legacy id map so existing URLs keep resolving, Merkle root per release, signed manifest chain, external anchor, proof in the verification endpoint. Exit gate: proofs recomputed independently on the box, a forged record rejected, one character changed flips the root, old claim URLs still resolve.

Phase 3
then · week of 21 Sep

Origin & propagation views — the point of the project

Origin line on every claim page (earliest dated record, with coverage stated), propagation list in date order, repetition interval, chain-of-custody view with a verifiable hash per step, and the origin fields in the API and on the badge. This phase is what makes the register accountable rather than merely interesting.

Phase 4
October

Scale and standing

Hundreds of domains and tens of thousands of claims, politeness and resumability, first signed public dataset dump with a citation identifier, first mirror, first badge in the wild, and a legal review of the origin language before it is promoted.

KPIs we will report

MetricNowTarget
Public claims1,174~1,444 after Phase 1
Assertions with a computed origin record0 surfaced100% after Phase 3
Corroborated assertions (more than one source)64reported per release as coverage grows
Assertions travelling across independent domainsnot yet measuredmeasured and published each release
Claims with a per-claim cryptographic identity0100% after Phase 2
Domains with a licence record and evidence URL16 identified100% of public sources
Third-party badges live0first external embed within two weeks of Phase 1
Independent verification of a release by an outsider0first one after the first public dump

15What is not ready

  • Origin and propagation are visible nowhere. The dates and sources needed to compute them are in the register, but no page or badge shows an origin line or a repetition list. Today the register cannot answer the question the project exists to answer.
  • Coverage is thin and narrow. 16 domains, mostly Irish and European, crawled from September 2026. “First seen” therefore means first seen by us, in a small window — the §03 caveat is load-bearing until the corpus is much wider.
  • The licence gate is wrong for 270 records — withheld though openly licensed. Until Phase 1 lands the public register understates the corpus by roughly 20%.
  • No badge or stamp route is live. The endpoints are being built now; there is no embed surface at all today.
  • Per-claim identity does not exist in production. The two-level scheme and Merkle commitment are proven on the real data, but the pipeline still stores page digests, and one export path double-prefixes the digest field.
  • Nothing is signed and nothing is anchored. No published key, so today’s releases cannot be independently verified.
  • No right-of-reply or opt-out mechanism exists yet. §08 is a specification, not a shipped feature, and must ship with — or before — the first public origin claim.
  • No legal review of origin language at scale. Naming a first publisher is a factual, evidenced statement; the wording and the reply path still need sign-off before promotion.
  • No public dataset dump, no citation identifier, no mirror — nothing yet survives the origin going away.
  • Scale path untested. SQLite on a single instance is fine at 1.5k claims and unproven past a few hundred thousand.

16Next five actions

#ActionOwnerState
1Licence-gated rebuild: licence records per domain, gate by licence rather than host list, release the 270 false withholdingsbuild noderunning
2Badge, stamp, embed and verification endpoints, with the badge block on claim pagesbuild noderunning
3Independent verification of both by the primary maintainer: recount on the box, SVGs parsed, every route curled, licence evidence spot-checkedprimary maintainerpending landing
4Cryptographic identity workstream: two-level ids, legacy map, Merkle manifest, signing key, anchor, verification proof — spec written, tested reference implementation readyspec readyawaiting go
5Origin & propagation: origin line, ordered chain of custody, repetition interval, origin fields in API and badge; right-of-reply and opt-out before the first public origin claimprimary maintainernot started
The register is only useful if it outlives us and can be checked without us — and it is only responsible if it names where a claim came from without ever pretending to name who is guilty.