diff --git a/docs/architecture/decisions/0052-reviewed-license-supplements.md b/docs/architecture/decisions/0052-reviewed-license-supplements.md new file mode 100644 index 0000000..d4a7514 --- /dev/null +++ b/docs/architecture/decisions/0052-reviewed-license-supplements.md @@ -0,0 +1,218 @@ +# 0052: Reviewed license supplements cover redistributed dependencies whose packages omit required material + +- Status: Proposed +- Date: 2026-10-07 +- Extends: [0049](0049-module-package-v1.md), in one respect only. ADR 0049 left exactly how licence + and notice material is collected to the packager's implementation. That implementation, and the + module development guide, then took material only from a redistributed package's own files, or + from a predefined standard licence text that needs no project-specific lines. This ADR adds one + further source: a reviewed supplement. Everything else in ADR 0049 is unchanged, as is + `packageFormat`. +- Related: [ADR 0048](0048-generic-image-and-installed-module-storage.md), + [ADR 0051](0051-module-package-license-material.md) + +## Context + +ADR 0049 requires every Module Package v1 to carry `THIRD_PARTY_NOTICES`: the licence and notice +material that redistributing its third-party code requires. It also states that no package is a +distributable release until licence and notice collection is proven. The canonical packager collects +material from two places: + +- the licence, copying, copyright, and notice files a redistributed package ships at its root; +- the standard text of the package's declared licence, but only when that text is complete without + project-specific lines (Apache-2.0 today). + +A package that has neither stops packaging. That is fail-closed by design: an MIT or BSD package +without its file is refused, because its copyright line exists only in that file. + +The first native-target module package needs a dependency that this rule cannot handle. +`@img/sharp-libvips-linux-x64@1.3.3` is the prebuilt libvips that `sharp` loads on Linux x64 with +glibc. It declares `LGPL-3.0-or-later`. The package itself, like its latest release 1.3.4, contains +only these files: +- `README.md` +- `versions.json` +- `lib/index.js` +- one glib header +- one shared library + +That shared library includes about 29 libraries. Its README names each one and the licence it is +used under, mostly with a link: +- LGPL components, such as libvips, glib, and pango; +- cairo, under MPL-2.0; +- many BSD-, MIT-, zlib-, IJG-, and FreeType-licensed libraries. + +The package ships no licence text and no copyright notice for any of them. No standard text can stand +in for that material: it includes per-project copyright notices and several different licences. + +Options that were ruled out before this decision: +- **Downloading material while packaging.** Packaging must stay offline and deterministic (ADR 0049, + ADR 0051). +- **Inventing material.** A packager that guesses notices produces artifacts that look compliant and + may not be. + +Ekklesia needs a way to carry material that a dependency's own package omits. It has to be reviewed +by people, tied to exactly the bytes it was reviewed for, and fail closed whenever that tie breaks. + +Some of these licences may also impose obligations beyond carrying text: the LGPL and the MPL can +require recipients to be able to obtain corresponding source. Whether and how such an obligation is +met for a particular redistributed binary is a legal and compliance determination. This decision +does not make that determination. + +## Decision + +### Package-provided material stays the preferred source + +The licence, copying, copyright, and notice material that a redistributed package ships remains the +primary source, collected exactly as it is today. Nothing in this ADR removes, replaces, or rewrites +package-provided material. A supplement only adds to it. + +### A reviewed supplement fills what a package omits + +When a redistributed dependency omits material that redistribution requires, the canonical Ekklesia +packager may use a **license supplement**: a checked-in, reviewed record of that material for one +exact dependency. + +- **Where supplements live.** In the Ekklesia repository, as part of the canonical packager's own + versioned inputs. A supplement enters only through Ekklesia's normal reviewed change process, and + the change that adds it is its review. A given packager version therefore always carries the same + supplements. +- **What a supplement may contain:** + - licence texts; + - copyright and attribution notices; + - provenance: where each piece of material was obtained, and which upstream component versions it + covers; + - corresponding-source information, such as where upstream source for the exact build is + published; + - other material that accompanies the dependency's redistribution. +- **Generic by construction.** Supplements are data. The mechanism contains no package-specific code + and treats every supplement identically, whether it is for libvips or for any other dependency. + +### A supplement matches one exact package, or it fails closed + +A supplement names exactly one redistributed package: + +- its package name; +- its exact version; +- an integrity value for the package's contents. The implementation defines this value as a digest + that the packager computes from the package files it reads and redistributes. The algorithm is + documented and does not depend on any package manager. + +The packager uses a supplement only when all three match the package it is about to redistribute. + +- **A mismatch on any of the three fails packaging.** This covers, for example, a supplement whose + name and version match but whose integrity differs. It never falls back to a nearby version, and + it never silently skips the supplement. +- **Every match is used.** A supplement that matches is always merged into the notices, including + when the package also ships some material of its own. +- **Gaps still fail.** If a dependency lacks required material and no exact supplement matches, the + packager stops, exactly as it does today. + +### Supplements are immutable build inputs + +- **Immutable.** A supplement is never edited in place to cover a different build. A changed + package, a new version, or different contents need a new supplement, reviewed again. +- **No network.** Packaging reads supplements from the packager's own inputs and never downloads + anything. Assembling a supplement's content is a separate, offline-reviewed curation step done + when the supplement is authored, never during packaging. + +### Merging is deterministic and labelled + +The notice generator merges package-provided material and supplement material deterministically. The +same packager version and the same inputs still produce a byte-identical `THIRD_PARTY_NOTICES` +(ADR 0049). + +- **Order.** Within a dependency's entry, package-provided material comes first, then supplement + material. +- **Labelling.** Supplement material is marked as supplied by Ekklesia's reviewed supplement, never + presented as if it came from the package. +- **No other change.** Dependencies are still sorted, line endings normalized, and each dependency + keeps its own entry, exactly as before. + +### A supplement never changes a dependency's declared licence + +`THIRD_PARTY_NOTICES` keeps reporting the licence the dependency itself declares. + +- **No override.** A supplement can add material about the components a dependency contains, but it + cannot replace, override, or rewrite the dependency's declared licence. +- **Consistency check.** A supplement records the declared licence it was reviewed against. If that + disagrees with the package's actual declaration, packaging fails. + +### Legal and compliance determinations are not made here + +A supplement can record corresponding-source information, but this ADR does not decide what +satisfies any licence's source obligation, and neither does the mechanism: +- the mechanism never asserts that a written offer, a source URL, a mirror, or any other arrangement + satisfies a licence; +- carrying a supplement shows that the reviewed material is present in the package. It does not + certify that the package is compliant; +- for every redistributed binary under the LGPL, the MPL, or any other licence with source or + similar obligations, the determination of whether and how those obligations are met is deferred. + It must be made, and verified, separately. + +ADR 0049's release gate still applies. A package that redistributes such a binary does not become a +distributable release just because its supplement was merged. It becomes one only once that +binary's compliance determination has been made and verified. + +### Scope + +- **Third-party code only.** Supplements apply only to redistributed third-party dependencies, + whether bundled or copied into the package. They never apply to the module's own licence or + `LICENSE` (ADR 0051), or to incorporated Ekklesia packages. +- **No package format change.** `packageFormat` stays **1**. A supplement changes only the content of + `THIRD_PARTY_NOTICES`, which is already a listed, digested payload file. No metadata field, archive + rule, or verifier contract changes. + +### The motivating case + +`@img/sharp-libvips-linux-x64@1.3.3` is the first dependency expected to need a supplement. This ADR +does not curate it. Its supplement will be assembled, reviewed, and merged separately, together with +the native-target packaging work that redistributes it. The source-obligation determination for its +LGPL and MPL components remains open, as above. + +## Consequences + +- A dependency whose package omits required material can be redistributed after review, offline and + deterministically, instead of making native packaging impossible. +- Each supplement is tied to exact package bytes, so a changed or unexpected dependency fails + packaging rather than inheriting material reviewed for something else. +- Ekklesia takes on reviewing and maintaining supplements. Every version bump of a supplemented + dependency needs a new reviewed supplement before packaging works again. +- `THIRD_PARTY_NOTICES` can now contain material that did not come from the dependency's package. It + is always labelled. +- Carrying material and meeting obligations stay separate. Source-availability questions remain open + until they are determined per binary. + +## Alternatives + +- **Download licence material while packaging.** Rejected: packaging must stay offline, + deterministic, and independent of a mutable remote source (ADR 0049, ADR 0051). +- **Extend the standard-text list.** Rejected: standard texts only work when the licence needs no + project-specific line. Bundled native libraries need per-project copyright notices, and several + different licences. +- **Match supplements by name and version alone.** Rejected: identical versions can differ in content + across registries or rebuilds, and the material was reviewed for specific bytes. +- **Fall back to the nearest supplemented version.** Rejected: material reviewed for one build says + nothing reliable about another. +- **Let a supplement restate a dependency's licence.** Rejected: the declaration belongs to the + dependency's publisher. A supplement that could override it could misrepresent what is being + redistributed. +- **Per-package special cases in the packager** (for example, code that knows about libvips). + Rejected: every supplemented dependency would need new code, and review would be split between + code and data. +- **Treat a recorded source URL or written offer as satisfying copyleft obligations.** Rejected for + this ADR: that is a legal determination that has to be verified per binary, not assumed by a build + mechanism. +- **Supplements provided by module authors.** Not adopted now: the canonical packager uses only + supplements reviewed into Ekklesia. Whether module repositories may contribute their own reviewed + supplements is deferred. + +## Deferred + +- Implementing the mechanism in the canonical packager: the supplement format and storage location, + the integrity algorithm, the matching, the merge, and the tests. +- Curating and reviewing the supplement for `@img/sharp-libvips-linux-x64@1.3.3`. +- The legal and compliance determination of source obligations for each redistributed binary, and + how a determination is recorded. +- Whether the packager should refuse, or flag, packages whose supplements note an open determination. +- Supplements provided by module repositories. +- Recording which supplements were used in `ekklesia.package.json`, should that ever be needed. diff --git a/docs/architecture/decisions/README.md b/docs/architecture/decisions/README.md index ca22414..9c3dcad 100644 --- a/docs/architecture/decisions/README.md +++ b/docs/architecture/decisions/README.md @@ -60,3 +60,4 @@ ADRs capture durable choices that affect more than one package or phase. - [0049: A module release is one immutable, self-contained package: Ekklesia Module Package v1](0049-module-package-v1.md) — Accepted - [0050: Module Database ABI v1: modules and Core exchange SQL, never ORM objects](0050-module-database-abi-v1.md) — Accepted - [0051: Module packages declare their own license and carry its text](0051-module-package-license-material.md) — Accepted +- [0052: Reviewed license supplements cover redistributed dependencies whose packages omit required material](0052-reviewed-license-supplements.md) — Proposed