-
Notifications
You must be signed in to change notification settings - Fork 0
License Provenance
As of: 2026-07-19. HOLD — owner review, per the original commission.
Companion to readiness-audit.md (§9 there is the
short pointer; this file is the full findings + policy). Nothing here
changes CI behavior for existing code beyond the one new, currently-empty
lint job in §2 — it fires on zero real violations today and exists to
catch a future one.
The owner's ledger commission, in order: (1) a provenance column on the
extraction ladder — done, readiness-audit.md §1.1–1.3/§9. (2) a
one-time external-code sweep — done, §1 below. (3) a PROTECTED CORE
policy for federation/vote-system modules — §2. (4) an absorption
protocol for any future external-code intake — §3. (5) disclosure
mechanics (README region, NOTICE convention, site footer) — §4, built
now per the commission's own "cheap today, load-bearing the day any
absorption happens" framing, except the site footer piece, explicitly
routed elsewhere (§4.3). (6) a CLAUDE.md convention line — added
directly to CLAUDE.md's Tooling rules section in this same change; not
duplicated here.
Not "expected clean, confirmed clean." The sweep (every .py, .ts,
.tsx, .js, .jsx, .css, .html, .go, .sh file repo-wide,
outside node_modules/, .git/, and lockfiles, across MPCAutofill/,
frontend/, schemas/, image-cdn/, desktop-tool/,
cloudflare-static-site/, github-release-reverse-proxy/, docker/,
.github/) found 4 real external-origin items. None are a licensing
violation — nothing here is copyleft-incompatible with this repo's own
GPL-3.0 — but 2 of the 4 are missing full license-notice compliance, a
real, previously-unnoticed gap this pass closes rather than papers over.
flag-usa.svg, flag-canada.svg, flag-china.svg (frontend/public/),
vendored from lipis/flag-icons
(MIT), added in commit f048ca32. Already the ladder's own IV.5 finding
(readiness-audit.md §1.2) — cross-referenced there, not a new
discovery. Attribution present but incomplete: flags.tsx carries a
comment citing the source repo and "MIT license," but the MIT license
text itself isn't reproduced anywhere in this repo — a comment saying
"see that repo's LICENSE" doesn't satisfy MIT's own "include a copy of
this permission notice" requirement literally, even though the practical
risk is low (the reference is genuine, specific, and correct). Closed by
§4's new NOTICE file, which reproduces the actual notice text for all
four items in this section in one place.
Vendored from
NightCafeStudio/react-render-if-visible,
commit 6254ffce ("vendor in NightCafeStudio/react-render-if-visible
on 2025-04-06 to apply the fix from .../pull/21"). License correction,
verified not assumed: the vendoring commit's own comment doesn't state
a license, and the audit sub-pass that first flagged this file wrongly
assumed MIT without checking. Verified directly against the upstream
repo's GitHub API license metadata for this doc (2026-07-19): it's
Apache License 2.0, not MIT. This is exactly the "verified, not
assumed" mistake this repo's own conventions exist to catch — recorded
here rather than silently corrected, since the wrong assumption briefly
existed in this pass's own working notes.
Apache-2.0 code is compatible with inclusion in a GPL-3.0 project (a
one-directional compatibility both the FSF and the Apache Software
Foundation recognize for GPLv3 specifically) but has real requirements
beyond a bare source comment: retain the original copyright/attribution
notice, and state significant changes made to the file. Neither is fully
present today — closed by §4's NOTICE file plus this doc's own record
of what changed (the PR #21 fix, per the original vendoring comment).
Vendored from
mattrothenberg/react-overflow-list
"with some minor tweaks to reduce flickering" per its own comment;
earliest commit found in this fork's visible history is ad3ed3d0 (a
rename commit — the actual vendoring predates it). Verified: MIT,
confirmed directly against the upstream repo's GitHub API license
metadata (2026-07-19). License terms aren't reproduced in-repo — same gap
as §1.1, closed the same way.
keyrune.ttf + codepoints.json, vendored from the keyrune npm
package for server-side OCR/phash set-symbol matching
(local_fallback.py), introduced in commit ff7bedd0 ("Add local
OCR/phash printing-ID backfill pilot (Stage 8)"). Already fully
compliant — the only one of the four that is: a comment cites "the
keyrune npm package, SIL OFL 1.1," and a complete LICENSE.md (Keyrune's
own — GPL-3.0 for its code/icons, SIL OFL 1.1 for its fonts, copyright
Andrew Gioia) is checked in alongside the vendored files. Cited in §3 as
the pre-existing positive precedent the absorption protocol formalizes —
this vendoring already did, by instinct, exactly what §3 now requires in
writing.
Not the same thing as frontend/public/keyrune/: the frontend has
its own, separate, gitignored copy of keyrune's font, generated at
npm install time from the real keyrune npm dependency declared in
package.json — ordinary dependency management with its own license
metadata already tracked by npm, not a second vendoring finding. Two
independent uses of the same upstream project, one vendored-in-place
(backend, this section), one dependency-managed (frontend).
Eight short (1–8 line) code idioms, each with an inline StackOverflow
citation, no substantial copied logic: DisableSSR.tsx, api.ts,
processing.ts, Card.tsx, Layout.tsx, jest.setup.ts,
desktop-tool/autofill.py, MPCAutofill/MPCAutofill/settings.py. Listed
for completeness per the audit's own scope, not flagged as action items —
short idiomatic snippets at this size are standard practice and not
meaningfully "external code" in the sense this audit cares about.
image-cdn/worker-configuration.d.ts and
github-release-reverse-proxy/worker-configuration.d.ts carry large
embedded Apache-2.0 headers (Cloudflare/Microsoft copyright) — both
self-declare "Generated by Wrangler by running wrangler types," a
build/type-generation artifact from the Cloudflare Workers toolchain both
projects already depend on, functionally equivalent to a lockfile. No
action needed.
- Every source file repo-wide for attribution keywords (
vendored,adapted from,copied from,taken from,based on,stackoverflow,MIT,Apache,BSD,Copyright (c)) — every hit triaged above; the rest were false positives (identifier names, this repo's ownLICENSE.md,package.jsonlicense fields). - No
THIRD_PARTY,NOTICE(before this change),ATTRIBUTIONS, orvendor-named directory anywhere in the tree. -
frontend/public/fully enumerated: only asset beyond the items above isarrow.svg(an Adobe Illustrator generator string, no copyright/license text, no external attribution — reads as originally authored, not vendored). - The local OCR/phash pilot code (
local_phash.py,local_fallback.py,local_identify_printing_tags.py,models.py) checked specifically for algorithm-attribution or paper/AGPL citations, given it's exactly the kind of code where a copy-pasted implementation would be tempting — none found. Perceptual hashing uses the realImageHash~=4.3.2PyPI dependency (import imagehash, pinned inMPCAutofill/requirements.txt), not a copied algorithm. -
desktop-tool/,schemas/,cloudflare-static-site/,docker/,.github/— same keyword sweep, nothing beyond §1.5's one-liner.
Scope — the actual files, not just the concept, since a policy nobody can point at doesn't function as one:
MPCAutofill/cardpicker/vote_consensus.pyMPCAutofill/cardpicker/printing_consensus.pyMPCAutofill/cardpicker/tag_consensus.pyMPCAutofill/cardpicker/artist_consensus.pyMPCAutofill/cardpicker/local_phash.pyMPCAutofill/cardpicker/local_fallback.py-
federation-hash-tool/hash_my_cards.py(+ its test) -
MPCAutofill/cardpicker/tests/test_federation_hash_tool_parity.py(the parity tether between the previous two) -
decrypt-saved-deck-export/decrypt.mjs(+ its test) — the standalone, zero-import, zero-dependency decrypt tool for a saved-decks export bundle (PR #242); same standalone-trust-anchor risk shape as the federation hash tool above, not itself part of the vote/federation system. Not yet incheck_protected_core_license.py'sPROTECTED_CORE_FILES— that file only exists on PR #242's branch, not yet onmaster; add both paths to the CI script's list in the PR that merges #242 (or immediately after), per this section's own "keep these in sync in the same PR" convention. -
Prospectively: any future verdict schema/signing/export/import/
keygen module (
federation-v1.md/federation/public-export-v1.mddescribe the format; per those docs, "format committed ahead of code" — none of that code exists yet, so there's nothing to list here today beyond the commitment that whatever gets built there joins this list in the same PR).
Explicitly NOT file-level protected here, despite being
conceptually part of the vote/consensus system:
MPCAutofill/cardpicker/models.py. The VoteSource/
AbstractWeightedVote/CanonicalPrintingMetadata/CardPrintingTag
class definitions inside it are real protected-core content, but the
file also holds dozens of unrelated model classes — a file-level import
lint would either miss real violations scoped to just those classes or
false-positive on every unrelated model change in the same file. Per
this repo's own established "narrow v1, no heavyweight AST library"
philosophy (docs_lint.py's own stated limitation), building a real
per-symbol static-analysis check is out of v1 scope. Until/unless that's
worth building, this is a manual-review item: any PR touching those
four classes specifically should get the same license-provenance
scrutiny as a file on the mechanical list, by convention, not by CI gate.
One real correction to the commission's own framing, stated plainly
rather than silently absorbed: the directive says protected-core files
"MUST remain GPL-3-clean." That's accurate for every file in the list
above except federation-hash-tool/hash_my_cards.py and its test —
that tool is deliberately MIT-licensed, a distinct, already-decided
choice (docs/federation/public-export-v1.md §5: "Distinct from the
reference tooling's MIT license... those are separate decisions about
separate artifacts," decided by the owner 2026-07-18), precisely so
third-party consumers can use it without GPL's copyleft attaching —
and, as of PR #242, decrypt-saved-deck-export/decrypt.mjs and its
test as well — that tool is likewise deliberately MIT-licensed, a
distinct, already-decided choice (PR #242, mirroring the federation
hash tool's own precedent, decided by the owner 2026-07-20), precisely
so third-party consumers can use it without GPL's copyleft attaching.
The actual invariant isn't "everything here must be GPL-3" — it's "nothing
here may import from or derive from AGPL-marked code," which would
poison either license (AGPL is incompatible with distributing under
GPL-3.0-only, and definitely incompatible with keeping something
genuinely MIT-permissive). The CI check below enforces the real
invariant, not the narrower one the directive stated.
The CI check — built, not just designed: a new
.github/scripts/check_protected_core_license.py walks each
protected-core file's local (intra-repo) imports and fails if any
imported local module carries an AGPL mention in a # PROVENANCE:
header comment (the format §3's absorption protocol requires of any
future external-code intake) — also fails if a protected-core file
carries that marker on itself directly. Wired into docs-lint.yml as a
new protected-core-license job. Passes today with zero findings,
correctly — nothing in this repo is AGPL-marked; the check's only job is
to trip the day that stops being true. Deliberately does NOT attempt to
scan transitive PyPI/npm dependency license metadata (a much larger,
separate problem — tools like pip-licenses exist for that and aren't
part of this pass); it catches the specific risk the absorption protocol
is actually worried about: someone pasting AGPL-licensed source code
directly into a protected-core file, not a third-party package turning
out to have an unexpected license three dependencies deep.
For the day the "permitted zone" (everything outside protected core) ever needs a capability that only exists as AGPL code elsewhere:
- Never blend into an existing GPL file. A bounded, standalone module only.
- Verbatim AGPL header preserved at the top of the vendored file, unmodified.
-
A
# PROVENANCE:comment, naming the source repo, the exact commit/tag vendored from, and the license — the same shape as §1's own findings already use informally (flags.tsx's "vendored from ... on " comment is the closest existing precedent, now formalized). -
A ledger row — the vendored module's own entry in whichever table
most naturally covers it (a new row in
readiness-audit.md's §1 tables if it's an extractable chunk, or a new entry in this doc's §1 if it's infrastructure-shaped like the four §1 findings). -
A
NOTICEentry — see §4.2. Thekeyrunefont vendoring (§1.4) is the one existing case that already did most of this by instinct (provenance comment + a full LICENSE.md alongside) before this protocol existed in writing; it's the template to match, not a counter-example.
For PROTECTED CORE specifically: the protocol above does not apply —
protected core "accepts patterns, never external code" (the convention
line now in CLAUDE.md). If a needed capability exists only as AGPL code
elsewhere, reimplement from the pattern: describe the behavior in a
doc (not copy the source), implement independently from that
description, record the clean-room decision as a ledger row here. This
is the one asymmetry between protected core and the rest of the repo —
everywhere else, bounded absorption with full attribution is permitted
with owner sign-off; inside protected core, only the pattern may cross,
never the code.
Default posture, repo-wide, stated once rather than re-litigated per
case: patterns (ideas, algorithms-as-described, UI approaches) may be
referenced freely from any public codebase, as they already are
elsewhere in this repo's own docs (e.g. docs/federation/public-export-v1.md
§6b's own careful, non-code use of proxies-at-home's public integration
code as a design reference). Actual code reuse is case-by-case, requires
the absorption protocol above, and requires owner sign-off — never a
unilateral call.
docs/readme-sections.md gained a fourth README-REGION
(license-provenance), assembled into readme.md by the existing
readme emit mode (.github/scripts/publish_readme.py,
docs/proposals/proposal-i-readme-pipeline.md) — no new machinery, the
pipeline this session shipped earlier today already does exactly this
job. Content: "GPL-3.0; complete corresponding source: this repository;
third-party-derived modules listed in NOTICE" per the commission's own
wording, linking to the new NOTICE file (§4.2). Cheap today (the
pipeline already exists); load-bearing the day any absorption actually
happens, since the statement's own truth ("third-party-derived modules
listed in NOTICE") only holds if NOTICE is kept current — which the
absorption protocol's own step 5 (§3) requires as part of intake, not as
an afterthought.
New file at the repo root, NOTICE, consolidating proper attribution for
every §1 finding: lipis/flag-icons (MIT), NightCafeStudio/react-render-if-visible
(Apache-2.0, with the required "changes made" statement), mattrothenberg/react-overflow-list
(MIT), and a pointer to MPCAutofill/cardpicker/local_pilot_data/keyrune/LICENSE.md
for the keyrune vendoring (kept as its own file rather than duplicated,
since it's already a complete, correct, standalone license file). This is
the "one canonical place a reader can check" the README's new
license-provenance line promises, and closes §1.1/§1.2/§1.3's actual
compliance gaps (comment-only attribution → a real, complete notice).
Per the commission's own routing instruction. This cloud session has no
direct channel to the parallel frontend-lane session (confirmed
concretely once already this session: an unrelated branding/mobile-funnel
task arrived misdirected here and had to be declined rather than
silently actioned — see this session's own history). Queued here as the
explicit, addressable deliverable a frontend-lane task description should
reference: add a footer link, likely in frontend/src/features/ui/Footer.tsx,
pointing to the repo's NOTICE file (or the README's new
license-provenance section) — the "one-liner" the commission asked for,
GPL-3.0 attribution/source-availability, visible from every page. Not
actioned by this change; the owner needs to either hand this to that lane
directly or re-route it back to this one.
- §1's two incomplete-attribution findings (RenderIfVisible.tsx,
OverflowList.tsx) are closed by the new
NOTICEfile as of this change — confirm that's sufficient, or whether the individual source files should also get their own comments expanded to quote license text inline (belt-and-suspenders, not required by either license). - §2's
models.pygap (protected-core vote/consensus classes sharing a file with unrelated models, not mechanically lint-covered) — confirm the manual-review-item treatment is acceptable, or whether a per-symbol check is worth building despite the added complexity. - §2's correction to the commission's own "GPL-3-clean" framing (the hash tool is deliberately MIT, not GPL-3) — confirm the restated invariant ("no AGPL-derived code, whatever the file's own permissive- or-copyleft license is") is the intended policy.
- §4.3 — who picks up the site footer link: the frontend lane directly, or does the owner want it re-routed back to this session instead?
- Whether
readiness-audit.md's 41-row actual count (vs. the commission's 27-row estimate) changes anything about how the provenance column gets used going forward, or is just a number worth knowing.
Understanding the system
- Overview
- Documentation-Process
- Theory
- Identification-Pipeline
- Pipeline-Fidelity-Gate
- Federation-v1
- Vote-System
- Readiness-Audit
- License-Provenance
- Upstreaming-Conventions
- Drift-Log
- Upstream-Wiki-Drift
- Printing-Tags
- Catalog-Completion-Plan
- Moderation
- Card-DOM-API
- PDF-Generator
- Print-Export-Page
- Google-Drive-Connect
- Grid-Selector
- Image-CDN
- Local-File-Source
Using it
Operating it
Folded into other pages