0030. REUSE compliance and third-party notices
Context
ADR-0018 decided the licenses (Apache-2.0 for code, CC-BY-4.0 for documentation), the copyright line, the headers and the absence of a project NOTICE file. It left the mechanics open: how a CI check proves that every file is covered, how files without comments and third-party content are licensed, and how the notices that the dependencies require reach the people who receive the binaries.
The facts that make the mechanics necessary:
- The binaries link 117 Go modules (Apache-2.0, BSD, MIT, ISC, Zlib and one MPL-2.0 module of which only BSD-3-Clause packages are linked). Twelve of them ship NOTICE files that Apache-2.0 section 4(d) requires to be reproduced. MIT, BSD, ISC and Zlib require their license texts in binary distributions. The Vite build removes the license comments of the web UI packages that are embedded into
myriarchd, and four of them publish no license file. - The repository holds content that is not original: OpenTelemetry release fixtures, Sigstore test data, component lists derived from OpenTelemetry, and community documents adapted from the CNCF project template and the CNCF Code of Conduct.
- Many files cannot carry a comment (JSON, images, lock files), and generated files would lose a hand-written header.
- The server image of the development variant contained OpenTelemetry release fixtures that production deployments do not need.
Decision
REUSE 3.3 is the compliance format, and
reuse lintis the check. The gatelicensesofmake check-localruns the header check,ci/reuse-lint.shand the notices drift check.reuseis pinned (5.1.1, the last release for Python 3.9) and installed from hash-locked requirements. Only the licenses Apache-2.0 and CC-BY-4.0 are used, and their texts are inLICENSES/; the repositoryLICENSEis the unchanged Apache License 2.0 text.Source files carry the header of ADR-0018 in their comment syntax, as two lines followed by one empty line:
Copyright The Myriarch Authors SPDX-License-Identifier: Apache-2.0scripts/license-headers.pychecks and inserts the header and knows where it goes (after a shebang, a Dockerfile parser directive or a leading doctype, before//go:buildlines and package comments). Helm templates use a template comment, which keeps the rendered output identical. Generated files get the header from their generator (pnpm gen:api).REUSE.tomlcovers every file that has no header: YAML, JSON, data, images and Markdown. Every Markdown file (documentation, decision records, root documents, READMEs) and the brand artwork are CC-BY-4.0, except the files of item 4 and the GitOps template (gitops-template/), which is Apache-2.0 so that the template that users copy carries a single license. Third-party content has its own annotation with the original license and holder, and a comment names the upstream source (URL, tag or commit). Annotations useprecedence = "override"; a new data or third-party file needs an entry in the same pull request.Adapted community documents keep the license of their upstream.
GOVERNANCE.mdandCONTRIBUTOR_LADDER.mdcome from the CNCF project template (Apache-2.0) and stay Apache-2.0; both state that they were adapted.CODE_OF_CONDUCT.mdcomes from texts under CC-BY-4.0 and stays CC-BY-4.0.THIRD_PARTY_NOTICESis generated, not written.scripts/gen-third-party-notices.shcombinesgo-licensesreports for all four binaries and the three target operating systems (and thedevpgbuild, marked as development only), the Vite license report of the bundled web UI packages, a shared override list (ci/license-overrides.txt) for modules whose license the tool cannot classify, and a small file of verified texts for components without a license file (scripts/notices/third-party-texts.json). It reproduces every distinct license text verbatim and prints identical texts once (section “License texts”, each under a deterministic ID such as[T1](numbered by first use), referenced by every component that ships it; texts that differ in any byte stay separate), keeps every NOTICE file verbatim with its component, fails when the file grows over 1,000,000 bytes (the limit of the publication gate), records the origin of the embedded Mozilla root bundle and of the time zone data, and notes the run-time download of PostgreSQL in development mode. The output is deterministic, and the drift check fails when it differs from the committed file.The notices travel with the software and are public.
LICENSEandTHIRD_PARTY_NOTICESare in every release archive and every container image built by the project, andmyriarchdserves them at/licenseswithout authentication. They are static information about the build, contain no user data and are served astext/plainwith a restrictive Content-Security-Policy. Settings > System links them.Release fixtures only in the development image variant.
scripts/build-image-crane.shbuilds the variantsdev(default;devpgand/opt/myriarch/release-fixtures) andrelease(nodevpg, no fixtures). The production image does not carry test data from third parties.Still no project NOTICE file, as decided in ADR-0018.
THIRD_PARTY_NOTICESis a notice about third-party software, not a NOTICE file in the sense of Apache-2.0 section 4(d) for the project itself.
Consequences
Positive
- A machine-checkable statement of the license of every file, with attribution for third-party content, that a foundation review or a downstream packager can verify with a standard tool.
- Distributions of the binaries meet the notice obligations of their dependencies without manual work, and the drift check keeps the file current when dependencies change.
- White-label builds can replace the header text and the notices generator input without changing the mechanism.
- Production images are free of third-party test data.
Negative
- Every new file needs a header or a
REUSE.tomlentry, and a dependency change needsmake notices. reuse5.1.1 builds from source on most platforms and needs Python 3.9 or newer; the pin has to move when Python 3.9 support is dropped.- A public
/licensesroute is a small addition to the unauthenticated surface (covered by the route enumeration test and the security model). - The npm license texts for packages without a license file are stored in the repository and must be refreshed with the package version.
Alternatives considered
addlicense -checkonly: covers source headers, but not files without comments, third-party attribution or license texts, and does not check the license of data files.- A project NOTICE file: rejected in ADR-0018, because it creates obligations for every downstream redistributor.
- Writing
THIRD_PARTY_NOTICESby hand: not reproducible and out of date after the next dependency change. go-licenses save: refuses modules it cannot classify and copies whole source trees of MPL modules;go-licenses reportwith the shared override list gives full control over the output.- Serving the notices only from the documentation site: a binary that is moved to an air-gapped host would not carry them.
- Per-file headers for JSON and YAML fixtures: changes upstream bytes (checksums and signatures of fixtures) and is not possible in JSON.