ADR-016 — License the project under MPL-2.0, without Exhibit B

  • Status: Accepted

  • Date: 2026-09-06

  • Closes: PRD 19 [OPEN-11] (License choice), open since PRD v1

  • Deciders: stakeholder

  • Evidence: Autodesk App Store Publisher Agreement, retrieved 2026-09-06, sections 4.3, 7(e), 14.3, 20.11, 20.12, 20.18, 20.19; a license audit of every dependency, hand-written component and asset in the repository

Context

The repository is going public. [OPEN-11] framed the choice narrowly — as a constraint imposed by FreeCAD’s LGPL on a future shared core (G6) — but two other constraints turned out to matter more, and one widely believed constraint turned out not to exist.

What the audit found: nothing blocks any license

  • Zero runtime dependencies, enforced by tools/check_no_third_party.py and by the CI package job importing the bundle under python -S (ADR-013). There is no third-party code in the shipped artifact to be compatible with.

  • Dev-only dependencies are permissive or MPL-2.0 (pytest, ruff, mypy, sphinx, furo, myst-parser: MIT; numpy, pypdf, babel: BSD; coverage, requests: Apache-2.0; hypothesis, pathspec: MPL-2.0). None is distributed and none is linked.

  • Every hand-written component is original. The PDF writer implements ISO 32000-1, a spec Adobe publishes with a royalty-free grant for conforming implementations, and embeds no font — base-14 Helvetica is referenced by name only. The icons are generated by tools/make_icon.py. No Autodesk stubs are committed and no third-party fixture data exists: PRD 11 records measurements of a model, not the model.

  • One provenance risk existed and was removed. core/linalg.py cited Numerical Recipes, whose code is not redistributable under any license. The routine is an independent 3x3 implementation — no b/z correction vectors, no tresh schedule, a Frobenius-scaled convergence test, the three index pairs enumerated rather than looped — so the exposure was the citation’s wording, not the code. Golub & Van Loan is now the primary reference and the independence is stated in the docstring.

Constraint 1 — the Autodesk App Store, measured rather than assumed

The belief that copyleft bars an app from the Autodesk App Store is wrong as stated, and the way it is wrong changes the decision.

Clause

What it actually says

7(e)

warrants no Open Source Software is included “in a manner that could cause any Autodesk Assets to be subject to any Open Source License”, then adds: “In the event that Your App includes Open Source Software, You will comply with all licensing terms for such Open Source Software.”

20.18

“Open Source License” = any Copyleft License plus any OSI- or FSF-approved license

20.12

“Copyleft License” names GPL, LGPL, Artistic, the Mozilla Public License, NPL, SCSL, SISL, CPL, SSPL

20.5

“Autodesk Assets” = the Marketplace, Autodesk Confidential Information, Trademark Materials, Autodesk websites, and other Autodesk products or services

4.3

the publisher may furnish a Custom End User Agreement; six minimum terms are mandated

20.11

commission is currently 0.0 %; paid distribution is supported

Three consequences follow. Open source is permitted — 7(e) forbids infecting Autodesk’s assets, not shipping OSS, and the next sentence says so. No license escapes the clause by category, because 20.18 sweeps in MIT and BSD as well; picking a permissive license to “be safe” is a misreading. And MPL is named as a Copyleft License in 20.12 exactly as GPL is, so MPL is not chosen here to dodge that clause — the advice that MPL clears app stores comes from Apple’s terms and does not transfer.

What does differ between GPL and MPL under this agreement is 4.3. Of the six mandatory Custom EULA terms, five (relationship acknowledgement, warranty disclaimer, liability for claims, third-party beneficiary, publisher contact) sit inside what GPLv3 §7(a)–(f) already permits a licensor to add. The 18+ representation does not, and GPLv3 §10 forbids imposing further restrictions. MPL has no equivalent of §10 and explicitly contemplates distributing the Executable Form under terms of the distributor’s choice (§3.2), so the same EULA raises no question at all.

Constraint 2 — the proprietary host

core/ never imports adsk (ADR-002), but adapter/ and ui/ must, and the add-in runs inside Fusion’s process. Under the GPL this invites the long-running argument about whether a plugin sharing an address space with a proprietary program forms a single combined work. Nobody distributes that combination — the user assembles it, and the GPL does not reach private use — but a redistributor would have to make the argument, and an App Store reviewer reading 7(e) would have to be persuaded by it. Answering that argument needs a GPLv3 §7 additional permission for the Fusion API.

Under MPL the question does not arise: §3.3 permits the Covered Software to be part of a Larger Work under other terms, so no exception has to be drafted, granted or defended.

Constraint 3 — the one [OPEN-11] actually named

FreeCAD is LGPL-2.0-or-later. MPL-2.0 §1.12 defines GPL, LGPL and AGPL as Secondary Licenses, and §3.3 lets a recipient distribute Covered Software under one of them — unless the file carries the Exhibit B notice. Omitting Exhibit B therefore satisfies [OPEN-11]’s requirement directly.

Decision

The project is licensed under the Mozilla Public License 2.0. Exhibit B (“Incompatible With Secondary Licenses”) is not applied to any file, now or later.

  1. LICENSE holds the canonical MPL-2.0 text, unmodified.

  2. Every file of the shipped tree — src/**/*.py and MightyMiter.py — carries the Exhibit A notice plus a copyright line. These are the files whose covered status has legal consequence, because MPL copyleft is per-file.

  3. tests/, tools/, docs/ and prd/ are covered by the repository-level LICENSE under MPL’s own Exhibit A allowance for a notice “in a location … where a recipient would be likely to look”. They are not distributed (PRD 14.2) and headering ~70 further files would add noise without changing anything.

  4. The CI package job copies LICENSE into the bundle and asserts it is non-empty. MPL §3.1 requires the license to travel with the Source Code Form; the job’s comment had claimed this copy since the job was written, and it was not happening.

Consequences

  • Modifications to these files stay open. Anyone distributing a changed core/unroll/cylinder.py must make that file’s source available under the MPL. The geometry — the part that is hard and the part that must be checkable — cannot be taken closed.

  • The larger work may be proprietary. Someone can wrap this core in closed code and ship it, republishing only their changes to MPL-covered files. This is a real concession relative to the GPL and it was made deliberately, in exchange for removing two arguments (the App Store’s 4.3, the combined-work question) rather than managing them.

  • App Store distribution stays open, including paid. Charging a fee was never the obstacle; the GPL permits selling copies too. 7(e) still has to be answered honestly if Autodesk asks — the answer is that the MPL covers only the files in this repository and cannot reach Fusion — but that answer is now underwritten by §3.3 rather than by argument.

  • A future FreeCAD addon may absorb core/ into GPL/LGPL code via §3.3. Adding Exhibit B to any file at any point would silently revoke this, which is why it is prohibited here rather than merely omitted.

  • Contributions need no CLA. MPL §5.1’s patent-defense termination and the per-file scope make inbound=outbound sufficient. This is the concrete cost avoided by not choosing the GPL dual-licensing route below.

  • Every new file under src/ starts with the Exhibit A header, no file anywhere carries Exhibit B, and the bundle contains LICENSE. All three are asserted in tests/unit/test_license_notices.py, because a constraint that only lives in prose is not enforced — the lesson of ADR-015, and the cp line above is the proof.

Alternatives rejected

  • GPLv3 with a §7 additional permission for the Fusion API. The strongest copyleft, and it does work: the exception answers the combined-work argument in writing. Rejected on 4.3 — the mandatory 18+ representation is outside the §7(a)–(f) list that GPLv3 §10 otherwise forbids adding — and on the reviewer risk that 7(e) presents to a license naming itself in 20.12 while also being the one the clause’s drafters plainly had in mind.

  • GPLv3 plus dual licensing under the sole copyright. Also works: a sole copyright holder is not bound by their own license and may ship the identical code to the App Store under Autodesk’s Standard EULA. Rejected because it only keeps working while the copyright stays consolidated, which means a CLA on every outside contribution. For a tool whose value depends on fabricators and other CAD developers contributing corrections, that friction costs more than the copyleft strength it buys.

  • LGPLv3. Worse than both: named in 20.12 anyway, inherits GPLv3 §10, and its relink requirement is meaningless for a plain Python source tree that ships as source.

  • MIT or Apache-2.0. Would end every question above, and gives up the one guarantee worth keeping — that a corrected unroller stays public. 20.18 makes them “Open Source Licenses” under the Publisher Agreement regardless, so they do not even simplify 7(e).

  • MPL-2.0 with Exhibit B. Rejected explicitly: it would close the FreeCAD path that [OPEN-11] was raised to protect, in exchange for nothing this project wants.