Skip to content

WI-072: The obligation, before the content

WI-072: The obligation, before the content

Wikidata is CC0 and obliges nothing. Wikipedia is CC BY-SA, which obliges us to name the source and the licence wherever the material appears — a rendering requirement, not a footnote, and the reason ADR-0016 made provenance per field rather than per record. One game row can legitimately mix a CC0 designer list with a CC BY-SA description, and only one of those puts a line on the page.

None of that content exists yet, and this ships anyway. An obligation added after the content is one somebody has to remember. Added before, it is a thing the content has to satisfy.

Three guards

The databaseA CHECK refuses any CC-BY-SA-4.0 row with no source_url. A row we may not render is not a row we may hold — and the loader is only one of several ways a row arrives.
The APIrequiredCredits throws rather than returning an empty list. Returning nothing there is the dangerous answer: the page renders the material with no credit and nothing looks wrong.
The screenCredits render as links naming the source and the licence. A bare link is not attribution, and neither is a mention without one.

Credits are grouped per (source, url), not per field: three fields from one Wikipedia article is one credit, and a page repeating the same link three times reads like a bug.

Where the prose will come from is not decided

/api/ and /w/ are both Disallowed on en.wikipedia.org — verified verbatim, not inferred — so the REST API is out under the same reading that produced ADR-0023. Unlike WDQS there is a genuine sanctioned alternative, so a second exemption would be a convenience rather than a necessity, and it is not taken.

/wiki/{Title} is permitted, and ADR-0016 discourages scraping rendered pages. dumps.wikimedia.org has no robots.txt at all, but the abstract dumps have been retired and the remaining prose artefact is pages-articles at roughly 22GB. That is a real cost on somebody’s connection, so it is a decision rather than a default.

Definition of done

  • A CC BY-SA row with no source URL cannot be stored.
  • The same row is accepted once it can be credited.
  • CC0 is unaffected.
  • The game route returns credits, present and empty rather than absent.
  • The screen names the source and the licence, and links to it.
  • Every credit renders, not just the first.
  • Each check proven able to fail.
  • Gate green.

Verification

Terminal window
pnpm --filter @tabletop/db test
pnpm --filter @tabletop/catalogue test
pnpm --filter @tabletop/mobile test
pnpm gate

Seeded failures

SeedBit
Unattributable material returns no credit instead of refusing1
CC0 treated as requiring attribution4
One credit per field rather than per source2
Credits collected but never rendered3
The licence dropped from the credit line1
Only the first credit rendered1
The credit is not a link1
The database constraint dropped1
A NUL byte in a source file1

A NUL byte compiled clean

While editing attribution.ts, a script replaced one space in a template literal with \0. TypeScript compiled it, eslint passed it, vitest ran it, and every test went green. grep was the only thing that noticed, by refusing to search a “binary file”.

Nothing in the gate looked at bytes. scripts/check-source-bytes.mjs now runs first and does.

Two migrations, one of which did nothing

The first attempt hand-wrote 0007_attribution_constraint.sql. Drizzle reads migrations/meta/_journal.json, not the directory — so migrate skipped it entirely and reported success. The constraint was absent and a probe inserted an unattributable row without complaint.

Generated from schema.ts instead, which keeps the journal and the snapshot in step, and the drift probe able to see it (ADR-0020).

Not done here

Any actual Wikipedia prose. The three guards are in place and there is nothing yet for them to guard.