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.
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.
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.
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.
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.
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.
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.
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.
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.
“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.
| Signal | What it tells you | Live today |
|---|---|---|
| Origin record | Earliest publication of this claim in the register, with source and date | derivable now, not yet surfaced |
| Record count | How many separate sources carry the claim | up to 20 for one assertion |
| Corroborated assertions | Claims with more than one independent source | 64 |
| Independent domains | Repetition across distinct publishers, not just pages | computed at query time |
| Repetition interval | Time from origin to first repetition — how fast a claim travels | new field, Phase 3 |
| Chain of custody | Ordered list of every record, each with its own verifiable hash | data 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:
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.
Keyless: claim lookup, search, domain stats, licence records, release manifests, and a verification endpoint returning an inclusion proof.
A one-line embed stating origin and record count: origin: epa.ie · 4 records. Every badge is a durable citation of the register.
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
| Dimension | State at 17 Sep 2026 | Evidence |
|---|---|---|
| Public site | Live at factprovenance.org; all routes 200, dark full-bleed UI, favicon, content negotiation on claim URLs | curl 200 on / and /claim/1 |
| Register | 1,465 claims from 16 domains extracted from fetched pages | count = 1465 |
| Licence gate | 1,174 public / 291 withheld — only 21 withholdings are genuine licence exclusions; 270 are hostname bugs | domain analysis |
| Claim identity | Digest is per-page, not per-claim: 1,465 claims share 207 hashes | distinct digest = 207 |
| Origin view | Data exists (dates + sources) but nothing surfaces an origin line or propagation list yet | no route exists |
| Nightly growth | Newest Common Crawl release auto-followed; page budget steps 60 → 400 per domain, +40 a night | nightly, 03:00 UTC |
| Work in flight | Licence-gate rebuild + badge/stamp endpoints running on a build node | build node, job service |
| Identity layer | Specified and proven on live data; not yet deployed | root sha256:d3c53ce1… |
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
- 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.
- Extract — deterministic rules pull candidate claims (figures, dates, superlatives, attributions) with surrounding context. No LLM: same input, same output, forever.
- Gate — licence resolver decides public or withheld per domain from a licence record with URL and date. Unknown licence is withheld, never guessed.
- Identify — assertion id (normalised text) and record id (assertion + canonical source) computed per row; page digest kept beside them as fetch evidence.
- 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.
- 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.
- Distribute — badges and embeds, dataset releases for mirrors, open API for tooling.
| Layer | Now | Next step |
|---|---|---|
| Store | SQLite, single file, WAL | Postgres past roughly a million records or when writers contend; SQLite stays as the portable mirror |
| Serve | One Python service under systemd, a commercial DNS and TLS provider | Static export of claim pages to a CDN so reads never touch the origin |
| Crawl | Nightly cron, stepping budget | Per-domain concurrency, robots.txt honouring, backoff on 429 |
| Identity | Page digest only | Assertion and record ids, Merkle manifest, Ed25519 signature (§07) |
| Attribution | Data present, no view | Origin 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.
| Level | Hashed over | Answers | Live prototype |
|---|---|---|---|
Assertion fp1-… | Normalised claim text only | What is being claimed | 1,161 from 1,465 claims |
Record fp1-… | Assertion id + canonical URL + date + kind | Who published it, where | 1,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
fp2and 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.
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.
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.
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.
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.
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.
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.
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.
| Bucket | Count | Reading |
|---|---|---|
| Withheld — genuine licence exclusion | 21 | Two news domains, all rights reserved. Correctly excluded. |
| Withheld — hostname bug | 270 | Openly 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
| Stage | Register size | Store | Monthly | Gate to pass |
|---|---|---|---|---|
| Now | 1.5k claims, 16 domains | SQLite, one instance | $12 | Licence gate correct; badges live |
| Next | 50k–100k claims, 100–300 domains | SQLite + static export to CDN | $12–24 | Identity and origin shipped; crawl polite and resumable |
| Then | 1M claims, ~1k domains | Postgres + object storage for raw bytes | $40–80 | Serving cost per request near zero; origin computed per assertion at build time |
| Further | 10M+ claims | Postgres + columnar exports; batch work on spare capacity | metered | Mirrors 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
| Risk | Severity | Mitigation |
|---|---|---|
| A named origin claims defamation, or suffers harassment because of the register | High | §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 record | High | Every 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 challenge | High | Licence 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 register | Medium | Deterministic 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 pages | Medium | Frozen 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 claim | Medium | Propagation list states sequence, never authorship; no ranking of sources by “spread”; no API field that reads as a score |
| Single-maintainer bus factor | Medium | Open licence, documented pipeline, signed manifests and mirrors so the register survives us |
| Crawl blocks or rate limits | Low | robots.txt honoured, backoff, per-domain politeness, cached raw fetches; a blocked domain is skipped, not worked around |
| Hosting or DNS takedown | Low | Static 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
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.
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.
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.
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.
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
| Metric | Now | Target |
|---|---|---|
| Public claims | 1,174 | ~1,444 after Phase 1 |
| Assertions with a computed origin record | 0 surfaced | 100% after Phase 3 |
| Corroborated assertions (more than one source) | 64 | reported per release as coverage grows |
| Assertions travelling across independent domains | not yet measured | measured and published each release |
| Claims with a per-claim cryptographic identity | 0 | 100% after Phase 2 |
| Domains with a licence record and evidence URL | 16 identified | 100% of public sources |
| Third-party badges live | 0 | first external embed within two weeks of Phase 1 |
| Independent verification of a release by an outsider | 0 | first 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
| # | Action | Owner | State |
|---|---|---|---|
| 1 | Licence-gated rebuild: licence records per domain, gate by licence rather than host list, release the 270 false withholdings | build node | running |
| 2 | Badge, stamp, embed and verification endpoints, with the badge block on claim pages | build node | running |
| 3 | Independent verification of both by the primary maintainer: recount on the box, SVGs parsed, every route curled, licence evidence spot-checked | primary maintainer | pending landing |
| 4 | Cryptographic identity workstream: two-level ids, legacy map, Merkle manifest, signing key, anchor, verification proof — spec written, tested reference implementation ready | spec ready | awaiting go |
| 5 | Origin & 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 claim | primary maintainer | not 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.