-
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.
This list is MACHINE-READ, not just prose. The markers below bound the
roster, and .github/scripts/check_protected_core_license.py PARSES this
region at runtime to build its file list — it holds no list of its own.
There is therefore no second copy to drift: adding a bullet here adds a CI
gate, and the CI script cannot silently disagree with this section because
it has nothing to disagree with. Every backtick-quoted path inside the
markers must resolve to a real file (a typo fails the lint), so paths that
were previously written as a prose parenthetical — (+ its test) — are now
spelled out explicitly. Keep prose commentary outside the backticks; only
the backticked spans are read.
MPCAutofill/cardpicker/vote_consensus.pyMPCAutofill/cardpicker/printing_consensus.pyMPCAutofill/cardpicker/tag_consensus.pyMPCAutofill/cardpicker/artist_consensus.py-
MPCAutofill/cardpicker/local_phash.py— still protected; carries one authorised exception, 2026-07-29, logged in §2.1. The exception covers that one change, not the file. -
MPCAutofill/cardpicker/local_fallback.py— still protected; carries one authorised exception, 2026-07-29, logged in §2.1. The exception covers that one change, not the file. -
federation-hash-tool/hash_my_cards.py(+ its test,federation-hash-tool/tests/test_hash_my_cards.py) -
MPCAutofill/cardpicker/tests/test_federation_hash_tool_parity.py(the parity tether between the previous two) -
decrypt-saved-deck-export/decrypt.mjs(+ its test,decrypt-saved-deck-export/tests/decrypt.test.mjs) — 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.
Prospectively (deliberately OUTSIDE the machine-read region — there is
nothing to gate yet, and a marker region containing an unresolvable path
would fail the lint): any future verdict schema/signing/export/import/
keygen module (federation-v1.md/federation/public-export-v1.md
describe 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 the roster above in
the same PR).
Historical note, kept because the gap it describes was real and lasted:
this section used to carry a bullet saying the decrypt-tool paths were
"Not yet in check_protected_core_license.py's PROTECTED_CORE_FILES
— that file only exists on PR #242's branch, not yet on master; 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." PR #242 merged as 5ddf109c; both files landed on master;
the CI list was never updated. Two files this section declares part of
the trust anchor therefore carried NO gate at all from that merge until
2026-07-29. The one-line fix would have been to add them to the script's
list. What actually shipped instead is the derivation above, because "two
hand-maintained lists, kept in sync by a convention written in prose" is
the defect, and adding an entry to the second list would have left the
defect in place for the next entry.
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 reads the roster region
above, then 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, and fails if a path listed above
does not exist. Both languages on the roster are handled: Python files
via ast, resolving dotted imports against MPCAutofill/ and
federation-hash-tool/ as package roots; .mjs files via ES-module
import/export ... from / dynamic import() / require() extraction,
resolving only RELATIVE specifiers (./, ../) — a bare specifier is an
npm package or a node: builtin, out of scope for the same reason the
Python side does not scan PyPI metadata. The comment-marker match accepts
#, // and * comment leaders so a marker in a .mjs file is seen;
before 2026-07-29 the regex required #, which meant a JS file on the
roster could have carried an AGPL marker in a // PROVENANCE: line and
passed. 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.
Protection here means deliberate review, not immutability. A change to a listed file is allowed when the owner rules on it specifically. Every such ruling gets an entry below, so a reviewer who was not present can see what was changed, why, who authorised it, and — the part that matters most — how far the authorisation reaches. An entry that reads as a precedent would be worse than no entry: the whole value of the policy is that the next change has to be asked for again.
The file stays on the list in §2 either way. An exception authorises one change; it does not un-protect a file.
2026-07-29 — MPCAutofill/cardpicker/local_phash.py: declare the two
skip-reason constants at source.
-
What changed.
find_best_matchreturned two skip reasons as bare inline string literals,"no-hashable-candidates"and"no-clear-winner". They are now declared as module-levelPHASH_NO_HASHABLE_CANDIDATES_SKIP_REASONandPHASH_NO_CLEAR_WINNER_SKIP_REASON, exported in__all__, and returned by name. The mirrored copies of both constants inlocal_identify_printing_tags.py(added by PR #567 precisely because this file could not be edited) were deleted; that module now imports the one it uses. Nothing else in the file was touched. -
Why. The
*_SKIP_REASONdeclaration convention and the roster tethercheck_skip_reason_roster_tether()(PR #567,docs/reference/skip-reasons.md) derive the skip-reason roster by scanning for module-levelNAME = "<literal>"declarations. The tether cannot enumerate literals it cannot see. With the values declared only in the consuming module, a NEW literal added insidefind_best_matchwould have reachedCardScanLog.skip_reason— a column with ~2.7M production rows and nochoiceslist or foreign key protecting it — with no lint failure anywhere. PR #567 documented that hole and could not close it, because closing it required editing this file. Two declarations in a protected file is the smaller risk; an undetectable roster gap in the vote system's own scan log is the larger one. -
Who authorised it. The owner, ruling on 2026-07-29 on a request that named this file and this change specifically.
-
Effect: none, and it is proved rather than asserted. This is a naming-only change. The string VALUES are untouched, so a
CardScanLogrow written after it is byte-identical to one written before. Proof, in the PR: (a) the after-source with the two constants inlined back to their literals parses to an AST identical to the before-source; (b) the sequence of stringsfind_best_matchcan return, resolved statically through the module's constant table, is unchanged; (c)tests/test_skip_reason_roster.py, which pins every roster value against a hand-written expected set, needed no edit — the constant NAMES were kept byte-identical too, so nothing about the roster moved except its declaration site. There is no licensing effect of any kind: no import was added to or removed from this file, no external code was introduced, and the file's GPL-3.0 status andPROVENANCE:-header cleanliness are unchanged.check_protected_core_license.pypasses, andlocal_phash.pyremains inPROTECTED_CORE_FILESand in §2's list above. -
What keeps the hole closed. The tether alone cannot: it is blind to exactly the two regressions that would undo this. Two guards in
tests/test_skip_reason_roster.pycover them —test_phash_skip_reasons_are_declared_at_their_origin_and_nowhere_else(fails if any othercardpickermodule re-declares either value, i.e. if the mirror comes back) andtest_find_best_match_returns_no_bare_skip_reason_literal(fails if a skip reason is returned fromfind_best_matchas a bare literal rather than a named module-level constant). Both were mutation-checked against the regression each claims to catch. -
SCOPE OF THIS EXCEPTION — read this before citing it. It permits declaring skip-reason constants in
local_phash.py, and that is its entire reach. It is specifically NOT:- a general licence to edit
local_phash.py; - a licence to edit any other protected-core file, including the four
consensus modules,
local_fallback.py, or the federation hash tool — several of which emit skip-reason-shaped literals of their own (seedocs/reference/skip-reasons.md), and none of which are covered here; - a standing rule that "lint-driven refactors are exempt". The next change of any shape to any file on this list, including the next lint-driven one, needs its own ruling and its own entry below.
- a general licence to edit
2026-07-29 — MPCAutofill/cardpicker/local_fallback.py: declare the
three skip-reason constants at source.
The second entry in this log, and it is the second entry rather than a
continuation of the first: the previous entry's own SCOPE section names
local_fallback.py explicitly as a file it does not cover. This change
was asked for and ruled on separately.
-
What changed.
run_fallback_for_cardsetFallbackOutcome.skip_reasonfrom three bare inline string literals,"no-evidence","eliminated"and"ambiguous". They are now declared as module-levelLOCAL_FALLBACK_NO_EVIDENCE_SKIP_REASON,LOCAL_FALLBACK_ELIMINATED_SKIP_REASONandLOCAL_FALLBACK_AMBIGUOUS_SKIP_REASON, exported in__all__, and passed by name. Two docstrings and one field comment were extended to say so. Nothing else in the file was touched, and no mirror was deleted because none existed — unlike thelocal_phashcase, these values were never re-declared in a consuming module, because this engine's one non-test caller never reads them (see "Effect" below). TheFALLBACK_*_SKIP_REASONfamily inlocal_calculate_verdicts.pyis not a mirror of these: it belongs to the separatestage-d-fallback-v1calculator, has its own rows, and deliberately renames this engine'sno-evidencetono-sub-check-evidence. It was checked and left alone; collapsing the two families would erase a real distinction. TheLOCAL_FALLBACK_prefix exists to keep them apart, and matches this module's ownFALLBACK_ANONYMOUS_ID = "local-fallback-v1". -
Completeness — verified, not taken on trust. The request named three
literals. The file was re-scanned with an AST pass for every
skip_reason=keyword argument, every.skip_reasonattribute assignment, and every lowercase/hyphenated string constant it contains. Three is the complete set. The other lowercase literals the scan surfaced (black,white,silver,borderless,modern,old,trimmed,bleed,appropriate-bleed) are classifier outputs and tag names on paths that never touchskip_reason. -
Why. Identical to the previous entry's reasoning, and the reasoning is
the point rather than the precedent: the
*_SKIP_REASONdeclaration convention and the roster tethercheck_skip_reason_roster_tether()(PR #567,docs/reference/skip-reasons.md) derive the roster by scanning for module-levelNAME = "<literal>"declarations. The tether cannot enumerate literals it cannot see. A fourth reason added insiderun_fallback_for_cardwould have joined three invisible siblings, andCardScanLog.skip_reason— ~2.7M production rows, nochoiceslist, no foreign key — is what it would eventually reach. -
The defect was LATENT, not live, and that is an argument for closing it
rather than against. Nothing persists this outcome today: the module's
own printing-vote/scan-log write branch was retired by PR #560 on
2026-07-29, and its one non-test caller,
local_residual_classify.recover_frame_mismatch_printing_via_fallback_refetch, readsoutcome.printing_pkand discardsskip_reasonentirely. So no row reaches the column through this path right now. The invisibility, however, is a property of the literals and not of the caller: it becomes a live hole the instant anything persists the outcome, and nothing would fail at that moment to mark it. Closing it while it is cheap, and while the change is provably inert, is the smaller intervention in a protected file — not the larger one. - Who authorised it. The owner, ruling on 2026-07-29 on a request that named this file, this function and these literals specifically, and that set the same condition as the first ruling: that it hold up to audit.
-
Effect: none, and it is proved rather than asserted. This is a
naming-only change. The string VALUES are untouched, so a
CardScanLogrow written after it is byte-identical to one written before. Proof, in the PR: (a) the after-source, with the three constants inlined back to their literals and their declarations and__all__entries removed, parses to an AST identical to the before-source once docstrings are normalised — docstrings are the only other difference, and they are not executable; (b) the sequence of stringsrun_fallback_for_cardcan put onskip_reason, resolved statically through the module's constant table, is['no-evidence', 'eliminated', 'ambiguous']before and after; (c)tests/test_local_fallback.pyasserts two of the three (eliminated,no-evidence) againstrun_fallback_for_card's live output as raw string literals, and was deliberately not edited — it is an independent, behavioural pin that does not read the new constants at all and would fail if a value moved. (ambiguoushas no such behavioural test; it is pinned statically instead, byEXPECTED_SKIP_REASONSand by the origin guard intests/test_skip_reason_roster.py. Stated rather than glossed: the behavioural coverage is 2/3, and adding a third case is a test-coverage question outside this exception's scope, not a gap in the proof — (a) and (b) already cover all three at the source level.) There is no licensing effect of any kind: no import was added to or removed from this file, no external code was introduced, and the file's GPL-3.0 status andPROVENANCE:-header cleanliness are unchanged.check_protected_core_license.pypasses, andlocal_fallback.pyremains inPROTECTED_CORE_FILESand in §2's list above. -
What keeps the hole closed. The tether alone cannot; it is blind to
both ways this can be undone. Two guards in
MPCAutofill/cardpicker/tests/test_skip_reason_roster.pycover them —test_local_fallback_skip_reasons_are_not_re_mirrored_elsewhere(fails if any othercardpickermodule declares one of these three values under a constant name not already pinned for it, and fails outright on anyLOCAL_FALLBACK_-prefixed declaration outside this file) andtest_run_fallback_for_card_sets_no_bare_skip_reason_literal(fails ifskip_reasonis set from a bare literal rather than a named module-level constant). A third,test_local_fallback_skip_reasons_are_declared_at_their_origin, pins the three name/value pairs to this file. The mirror guard is deliberately narrower than thelocal_phashone:no-evidence,eliminatedandambiguousare shared vocabulary that several calculators legitimately declare under their own prefixes, so a flat "declared nowhere else" ban would forbid the roster's own design. All three were mutation-checked against the regression each claims to catch. -
SCOPE OF THIS EXCEPTION — read this before citing it. It permits
declaring skip-reason constants in
local_fallback.py, and that is its entire reach. It is specifically NOT:- a general licence to edit
local_fallback.py— every other function in it (the border/artist/symbol sub-checks, the threecast_*_votehelpers,classify_bleed_edge,normalize_crop_box) is untouched and stays untouchable without a fresh ruling; - a licence to edit any other protected-core file, including
local_phash.py(whose own exception is likewise spent), the four consensus modules, the federation hash tool, or the saved-deck decrypt tool; - a precedent that the pattern is now pre-authorised. Two rulings on two files with the same defect do not make a third automatic. The next change of any shape to any file on this list needs its own ruling and its own entry in this log — including the next skip-reason one.
- a general licence to edit
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