Skip to content

Licence policy ​

The rules CI enforces, and the reasoning behind them.


1. Allowed without review ​

SPDXNotes
MITRetain copyright and licence text
Apache-2.0Retain licence, NOTICE contents, and state changes if modified
BSD-2-Clause, BSD-3-ClauseRetain copyright, conditions, disclaimer. BSD-3 additionally forbids using contributor names to endorse the product
ISCRetain copyright and permission notice
PostgreSQLRetain copyright and permission notice
Unlicense, 0BSD, CC0-1.0Public-domain-equivalent. See §4 on CC0 and patents
Zlib, BSL-1.0 (Boost)Permissive
Unicode-3.0, Unicode-DFS-2016Unicode data terms; retain the notice
OFL-1.1Unmodified font redistribution only. Retain the copyright and full OFL text; do not sell the font by itself or relicense it
EPL-2.0, EPL-1.0, MPL-2.0, MPL-1.1Unmodified redistribution only. File-level copyleft: the obligation attaches to the licensed files and their modifications, not to a work that links them. Retain the notice and make those files' source available

EDL-1.0 is not listed separately because it is BSD-3-Clause - the same text with the Eclipse Foundation as the named entity. A scanner reports it as unknown, and §2 then treats it as forbidden, which is a parsing gap presenting as a licence decision.

None of these is obligation-free. Every one requires that the copyright and licence text travel with any redistribution. The phrase "no requirements" never appears in this project's documentation, and CI rejects a pull request that introduces it into a licence field.

2. Forbidden in the distributed product ​

SPDX / familyWhy
GPL-2.0, GPL-3.0, LGPL-*, AGPL-*Copyleft. Linking would impose source-disclosure obligations on a proprietary product. LGPL is forbidden too because static linking - which Rust does by default - triggers the same obligations
SSPL-1.0Requires publishing the entire service stack
BUSL-1.1Source-available, not open source; use restrictions
Elastic-2.0Restricts managed-service use
Commons-Clause (any base)Forbids selling
CC-BY-NC-*, any non-commercial termForbids commercial use
NOASSERTION, UNKNOWN, missingUnknown terms are treated as forbidden, not as permissive

A forbidden licence anywhere in the tree fails the build. There is no "temporarily allow" list.

Both halves of the tree are held to the same standard. deny.toml's allow-list governs the Rust crates through cargo deny and the dashboard's npm packages through tools/licence_policy.py, which reads the same file. It did not always: the npm half was gated by a denylist of licence families, so a package under MPL-2.0 or CC-BY-SA-4.0 passed there and failed on the Rust side. A denylist can only refuse what someone thought to write down, and it cannot implement §2's rule that unknown terms are forbidden at all.

tests/licence_gate.sh proves the gates refuse what they claim to, by introducing each violation on purpose.

3. Requires manual review ​

  • Dual or multi-licensed dependencies. Which option is elected must be recorded, not left implicit. See the notify decision in Open-source inventory §4.1.
  • Models, datasets, rule packs and language packs. The code licence of a library says nothing about the licence of a model it downloads. This is not hypothetical: spaCy's en_core_web_lg is MIT while its OntoNotes 5 training data is LDC-licensed under commercial terms.
  • Anything reached at runtime rather than linked - a downloaded rule pack, a language pack, a container base image.
  • Any dependency whose repository has moved between organisations, because the future relicensing authority has changed.

4. Elections we have made ​

The weak-copyleft admissions carry a condition, and it is not decorative.EPL and MPL are admitted for unmodified redistribution only. If we ever patch a file under one of them, the election stops being valid and the obligation changes - modifications to those files must be published. The Modified column in Open-source inventory exists for exactly this, and a change from "no" to "yes" in it is a licence decision, not a housekeeping edit.

Explicitly not admitted, and staying forbidden: CDDL, LGPL, GPL, AGPL. The artefacts carrying them are excluded instead - see SPIKE-003 for what that meant in practice.

OFL-1.1 is admitted for the unmodified IBM Plex Sans files bundled by the dashboard. A modified font requires a new licence review, including the OFL's reserved-name and same-licence conditions. The generated third-party notices record the redistribution obligation.

DependencyOptionsElectedWhy
Most Rust cratesMIT OR Apache-2.0Apache-2.0Express patent grant; one consistent choice across the tree
aho-corasickUnlicense OR MITMITA recognised licence is easier to account for than a public-domain dedication
rustlsApache-2.0 OR ISC OR MITApache-2.0Consistency and the patent grant
blake3CC0-1.0 OR Apache-2.0 OR Apache-2.0-with-LLVM-exceptionApache-2.0CC0 explicitly disclaims any patent licence
notifyCC0-1.0 OR Artistic-2.0Artistic-2.0Same patent reasoning; Artistic-2.0 §1 and §8 are clear on aggregate redistribution

CC0 is listed as allowed in §1 but is never elected where an alternative exists, because it grants no patent rights.

5. What CI does ​

yaml
# .github/workflows/ci.yml → licence job
- cargo deny check licenses      # allow-list from deny.toml; fails on anything else
- cargo deny check bans          # duplicate and banned crates
- cargo deny check advisories    # RUSTSEC vulnerabilities
- cargo audit                    # second opinion on advisories
- syft . -o cyclonedx-json       # SBOM, direct and transitive, with hashes
- license-checker --production   # dashboard dependencies
- tools/check_notices.py         # every distributed dependency has a NOTICE entry

Configuration lives in deny.toml. The allow-list there is the machine-readable form of §1 and is the file to change when adding a licence, so the change is reviewable in a diff.

6. Adding a dependency ​

  1. Read the actual LICENSE and NOTICE in the repository at the tag being adopted. Not a summary site, not the package-manager metadata field - those are frequently wrong, and Hyperscan's NOASSERTION on GitHub versus its plainly BSD-3-Clause LICENSE file is a live example.
  2. Record the exact version or commit.
  3. Enumerate transitive licences.
  4. Assess any bundled model, dataset or rule pack separately.
  5. Check repository activity, latest release, open advisories, and whether the project has changed hands.
  6. Record the integration form - linked, embedded, separate process, separate service - and whether it is redistributed.
  7. Record the exact notice obligation in Third-party notices.
  8. Add a row to Open-source inventory with the decision and the reviewer.

A dependency that cannot complete every step is not adopted. "The repository is public" is not an approval.

7. Release gate ​

A release is blocked if any of the following is true:

  • A forbidden licence appears anywhere in the tree
  • Any dependency has an unknown or ambiguous licence
  • A dual-licensed dependency has no recorded election
  • A model, dataset or rule pack has no separate assessment
  • THIRD_PARTY_NOTICES.md is missing an entry for a distributed dependency
  • The SBOM is older than the lockfile
  • A RUSTSEC advisory of high or critical severity is unresolved and unwaivered

Waivers are recorded in deny.toml with an expiry date and a ticket. A waiver without an expiry is not a waiver.

Statements here describe what is built and tested; planned work is marked as planned.