Skip to content

Strategy: GPL/free-software compatibility (§11.8 + §11.9 Public Combination Exception) and universal per-file license markers #10

Description

@zackees

Note

AI-generated strategy synthesis — not legal advice. Produced 2026-08-25 by a multi-agent review (2× Opus analysis: GPL-compat legal architecture, per-file zoning; 2× Sonnet: FOSS-exception precedent research, FastLED header audit; plus peer-session primary-source verification of FSF/Debian/Oracle/MySQL texts and ecosystem licenses). Input to the attorney review tracked in #8. Builds on the FRL 1.0-rc1 text merged in #9.

Strategy: GPL & free-software compatibility for the FastLED Reciprocal License, plus universal per-file license markers

Part 0 — The question asked: does FastLED have per-file license markers today?

No. Audit of FastLED/FastLED (2,869 files under src/; 2,334 h/hpp/cpp):

  • Only 121 files (~5%) carry any copyright/license text; only 7 files (0.3%) carry SPDX tags — all third-party (kissfft BSD-3-Clause, pl_mpeg MIT). ~95% of files have no marker at all, so absence of a notice cannot distinguish "FastLED MIT" from "unknown/vendored."
  • The third-party boundary is leaky: vendored code lives outside src/third_party/ (Bill Greiman's SdFat and PJRC audio under src/platforms/arm/teensy/), and 9 of 11 src/third_party/ components lack a per-component LICENSE file.
  • Real divergences exist: src/fl/font/ttf_covenant5x5.* is CC BY 4.0; src/third_party/libhelix_mp3 is RealNetworks RPSL/RCSL (non-free); cq_kernel mixes Apache-2.0 + BSD-3-Clause under one Apache-only LICENSE; console fonts (via WLED) and simplex noise carry no stated license.
  • No REUSE/dep5/SPDX manifest, no CI license-header check.

Steward decision (2026-08-25): all of FastLED will get per-file license markers. Refinement per the audit: universal coverage means every file is classified — in-file SPDX stamps on FastLED-owned code; preserved upstream notices plus manifest (REUSE.toml/SBOM) coverage for vendored and generated files, which must never be stamped over.

Part 1 — The compatibility problem, precisely

FRL 1.0-rc1 is GPL-incompatible by design: Exhibit B closes the MPL Secondary-License path because one GPL file used to let a proprietary vendor shed §11.3 (GPLv2's source duty runs to recipients/requesters, not the public). The goal: admit genuinely public free-software projects without reopening that bypass.

Four verified constraints shape the solution:

  1. GPLv3 §7 ¶4 sentence 3 kills any conversion design ("...provided that the further restriction does not survive such relicensing or conveying"): any text that permits conveying FastLED under GPL, however conditioned, hands recipients the right to shed §11.3. Only a non-converting additional permission survives (GPLv3 §5(c) + §7 ¶1 expressly accommodate it).
  2. FSF's MPL 2.0 doctrine (verified verbatim): a compatibility condition may bind only the party that first creates and distributes the Larger Work — anything binding downstream recipients is a strippable "further restriction."
  3. Debian doctrine (verified): recipient-scoped source duties = DFSG-free (AGPL ftpmaster ruling 2008); world-scoped publication = non-free (dissident/desert-island tests; RPL named as failing, debian-legal 2025-04-13). FRL itself will be non-free; the exception is still cleanly representable ("with X exception" naming is reserved for permission-granting exceptions — which this is).
  4. No precedent exists for an exception that fuses a FOSS-eligibility test with a public-availability trigger (MySQL/Oracle exceptions require only source-with-medium or interface-sharing; verified against primary texts). FastLED would be drafting new ground — narrowly.

Ecosystem reality check (verified): WLED is EUPL-1.2+ (relicensed Oct 2024) and no longer uses upstream FastLED at all — it vendors a ~32KB MIT fork of 3.6.0 color math (fastled_slim) and drives LEDs via NeoPixelBus. That use case is already fully covered by §11.4 (MIT-era releases stay MIT) and needs no exception. xLights is GPL-3.0 (treat as -only). The real targets are xLights-class GPLv3 projects, Debian packaging, and future adopters — and the eligible-license test must be broader than GPL/LGPL/AGPL or EUPL projects stay excluded.

Part 2 — Recommended architecture (composition)

Rejected first: dual licensing FRL|GPL (a global self-service bypass — GPLv3 §6(b)'s offer runs only to possessors of the object code, strictly weaker than §11.3, handed to the exact adversary); selective Exhibit B removal + preservation covenant (incoherent per-licensee, covenant-not-condition, barred by GPLv2 §6, pre-empted by §7 ¶4 s.3); a permissive API zone as the primary mechanism (FastLED's API is its implementation — 91 templated addLeds overloads, 769-header include closure of FastLED.h, 401 code-emitting headers, all 57 clockless drivers inside the closure; an honestly-drawn permissive zone gives away the drivers and creates a §11.3 escape hatch).

Adopt instead, as License text (new sections, so every DCO'd contribution carries them — a steward-published side document would be void as to non-steward contributors):

§11.8 — Compiled and Expanded Forms (ship regardless of GPL strategy)

Fixes the §1.10(b)/§11.2 over-reach that currently makes every user's preprocessed TU, -save-temps artifact, or amalgamated build "Modified FastLED" (FastLED's own unity-build model — 29 aggregator .cpp files pulling 741 .cpp.hpp fragments — is textual amalgamation). Mechanics: define Target Work (executable, or machine-generated source from compilation/preprocessing/amalgamation/codegen) and Eligible Input (Covered Software whose source, as used, is Publicly Available). Permission to distribute Target Works whose Covered inputs are all Eligible — §11.3 does not apply to the Target Work, §1.10(b) does not apply to it, and non-Covered material never becomes Covered. Excludes files a person hand-maintains as the preferred modification form. Unmodified upstream trivially qualifies (it's public), so ordinary proprietary users are safe; a vendor with secret modifications fails the Eligible-Input test — nothing is conceded. Companion edit: narrow §11.2's last sentence to files "You create or maintain."

§11.9 — Public Combination Exception (the GPL/FOSS door)

A non-converting additional permission. FastLED files never leave FRL; Exhibit B stays; §3.3 stays closed. Granted: permission to combine Covered Software into an Eligible Combined Work and distribute it, with §11.3 disapplied and no Triggering Transfer arising. Conditions — on the first distributor of that combination only (constraint 2):

  • (i) the Combined Work as a whole is under a single Eligible License — categorical test on the Oracle UFE model: OSI-approved and/or FSF-categorized-free, determined at first distribution, one-way ratchet (later delisting never divests). This covers EUPL-1.2, MPL-2.0, EPL-2.0, Apache-2.0, CDDL, OSL without list curation. Publish an illustrative (non-operative) list.
  • (ii) the Complete Corresponding Source of the entire Combined Work (GPLv3 §1 definition, so a free project's existing compliance artifact is the artifact) is Publicly Available at no charge on or before first distribution, for the §11.3(d) duration.
  • Standing compliance mirror of §11.3(b): always-public development repo = compliant with nothing further — the entire on-ramp for xLights-class projects, at zero cost to them.
  • No condition on recipients (unqualified — this is what keeps it GPL-survivable). A party creating a new combination becomes the first distributor of that combination.
  • Anti-severance (authorized by GPLv3 §7 ¶2's self-removing-permission parenthetical): if the condition is removed/held-unenforceable as to a person, that person has no exception — never exception-without-condition.
  • Termination on breach with §5.1 reinstatement; recipient survival mirroring §5.3. (Deliberate departure from Oracle's no-termination design, because unlike Oracle's, this exception has a condition to enforce.)
  • Exhibit C notice = convention, not condition (a flow-down obligation on recipients would violate constraint 2).

Why the bypass stays closed: the publication limb is measured on the combined work. The one-GPL-file vendor passes the license limb and fails publication — the only compliant path is publishing the product's source, which is over-compliance with §11.3, not evasion. And nothing converts, so there is no hop-2 leak.

§11.3(g) bilateral grants — the backstop

Already in the license. Mandatory path for EUPL adopters: EUPL Art. 5 requires derivatives under EUPL or its Compatible-Licences list (FRL won't be on it) and EUPL has no §7-style additional-terms mechanism, so EUPL projects can't self-serve. Keep a public register of grants (counterparty, scope, date) so practice is legible.

Project-side reciprocity (required for GPL projects)

GPLv2 §2(b)/GPLv3 §5(c) require the whole work under GPL; FRL files inside carry non-§7(a)–(f) terms. Classpath/GCC-RLE worked because FSF owned the GPL side; FastLED is the non-GPL component going up. So the GPL project must add its own additional permission back. Publish copy-paste GPLv3 §7 snippet and GPLv2 linking-exception snippet + an eligible-combination FAQ. Pre-negotiate with named projects before announcing. Do not market this as "FastLED is now GPL-compatible" — it makes FastLED usable by GPL projects, not forkable into them.

Part 3 — Universal per-file markers: zone plan

Zones classify; they do not scope the exception (§11.8/§11.9 are global license text — no zone-drift risk on the legal effect). Zone table (first-match precedence):

Zone Marker Contents
vendored-generated never stamped; manifest-covered **/node_modules/** (gitignored but the tool deliberately ignores .gitignore — a dev machine with npm install run would get stamped), src/platforms/wasm/compiler/vendor/** (371 tracked three.js files, MIT), dist/min/map
third-party upstream ids preserved; per-component LICENSE + manifest entry required src/third_party/** plus vendored code found outside it (SdFat, PJRC audio)
legacy-mit MIT wholly third-party-derived files (animartrix*)
examples-permissive MIT-0 (or CC0 — decide) examples/** — an FRL-stamped example makes every copied sketch a Modification
frl LicenseRef-FastLED-Reciprocal-1.0-rc1 everything else FastLED-owned (core, platforms, tooling)

Attribution is an orthogonal overlay: files with surviving MIT-era third-party authorship get the additive MIT-legacy fragment on top of their zone stamp (MIT's notice-preservation condition is what the relicensing authority rests on).

Tooling fixes before any mass stamping (all verified against current license_headers.py):

  1. Glob semantics: _is_excluded uses fnmatch where * crosses / — replace with gitignore-semantics matching.
  2. Add the vendored-generated exclusions to the policy itself (the tool correctly ignores .gitignore, so the policy must carry them) + regression test.
  3. Schema: header-policy.schema.json pattern ^LicenseRef-[A-Za-z0-9.-]+$ forbids compound ... WITH AdditionRef-... expressions — relax if compound ids are ever used (note: AdditionRef- is SPDX 3.0+ only; SPDX 2.x scanners will choke — prefer plain zone ids and put exception info in the license text/SBOM).
  4. RC gate: "-rc" in policy.license_id is a substring test a compound id could defeat — parse the base identifier.
  5. Schema v2: [[zones]] (ordered, precedence, per-zone id/template/old_ids, stamp=false zones replacing exclusions) + [[attributions]] overlay + new blocking states ZONE_UNASSIGNED / ZONE_MISMATCH (drift detector) + map subcommand emitting REUSE.toml + release SBOM (reuse lint as independent cross-check).
  6. Include-graph pass (cheap, ~2s): detects third-party files inside the public include closure — live case: src/third_party/ezws2812/ezWS2812.h is reachable from FastLED.h (MIT, benign today; the check must exist so an RPSL/GPL header can never silently poison user binaries).

Migration order: (0) tooling fixes; (1) ownership audit (git blame → mit-legacy overlay list); (2) third-party manifest — and a decision on libhelix_mp3 (RPSL/RCSL, non-free: externalize, replace — minimp3 is CC0 — or accept no-Debian) and cq_kernel's mixed LICENSE; (3) draft §11.8/§11.9 → LEGAL-REVIEW.md section (rc-gated); (4) zone assignment + human review; (5) stamp zone-by-zone, one PR each; (6) generate REUSE.toml/LICENSES//SBOM; (7) CI gate + CODEOWNERS on policy/LICENSE*/NOTICE-*; (8) release artifacts ship LICENSE + exceptions + MIT-legacy + SBOM.

Part 4 — Risks (top 5)

  1. One-sided exception insufficiency — without the project-side snippet, a GPL project's own license still can't absorb FRL terms; EUPL has no self-service path at all (bilateral grants only). Mitigate by shipping snippets + FAQ + pre-negotiation.
  2. Anti-severance is untested — no court has construed §7 ¶4 removal against a non-Program component; failure mode is litigation, not silent loss. Rests on the Jacobsen condition framing + §412 registration already flagged for counsel.
  3. Debian: FRL stays non-free (world-scoped publication fails dissident/desert-island); dependents land in contrib. FRL is more defensible than RPL (no internal-use trigger, no price cap, no notification duty, no network trigger) — argue those distinctions affirmatively. libhelix_mp3/cq_kernel must be resolved before any Debian story is credible.
  4. Contributor authority — the exception must be in the License text and the DCO/CLA must cover it before stamping; it is one-way in practice.
  5. Overclaiming — "GPL-compatible" messaging would create wrong reliance; the accurate claim is "usable in public free-software projects."

Immediate next actions

  1. Attorney review adds §11.8/§11.9 + Eligible License/Combined Work/CCS definitions to the FRL rc (tracked with META: AI first-pass legal review of FastLED Reciprocal License 1.0 RC — triage, findings & prior-art survey #8's checklist).
  2. Land tooling fixes 1–4 in FastLED/license (small PR, no legal review needed).
  3. Start the FastLED ownership audit + third-party manifest (prereq for the universal-marker decision regardless of the GPL strategy).
  4. Decide libhelix_mp3 and the examples-zone license (MIT-0 vs CC0).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions