Skip to content

build: ship licence texts and third-party notices with releases and the image - #165

Merged
jacderida merged 3 commits into
masterfrom
build/third-party-notices
Oct 7, 2026
Merged

jacderida merged 3 commits into
masterfrom
build/third-party-notices

Conversation

@grumbach

@grumbach grumbach commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

What this changes

Indelible's release binaries and Docker image ship no licence material today. .dockerignore drops LICENSE*, so the image does not even carry Indelible's own licence. Nothing reproduces the licence and notice files that the bundled third-party code requires. MIT, BSD, ISC and Apache-2.0 all require those notices when the code is redistributed as a binary.

The binary also statically links 22 go-ethereum library packages, which are licensed under the GNU LGPL v3 or later. Shipping them requires a prominent notice, the LGPL and GPL texts, and a pointer to the corresponding source.

After this PR every release and every image ships THIRD-PARTY-NOTICES.txt next to LICENSE-MIT and LICENSE-APACHE:

  • Release assets: the three files are uploaded alongside the binaries and included in SHA256SUMS.
  • Docker image: the three files are installed under /usr/share/doc/indelible/, which is where Debian keeps licence files.

How the notices are built

  • scripts/notices (Go, standard library only) lists the modules linked into ./cmd/indelible for each release target, using go list -deps with CGO_ENABLED=0 exactly as the release build does. It writes each module's licence and notice files into the output, including NOTICE files (go-oidc, grpc, yaml.v2), licences kept in subdirectories (go-ethereum's metrics/LICENSE) and modernc's LICENSE-3RD-PARTY.md. It also adds:

    • the Go standard library licence;
    • the Swagger UI notices;
    • the web UI notices;
    • a section on the antd release bundled alongside (recording its exact tag), and on the Debian base image.
  • go-ethereum section: when go-ethereum is linked, the file opens with a section that:

    • names it and its exact version;
    • gives the source location for that version (the Go module proxy zip and the upstream tag);
    • gives the commit this Indelible build came from;
    • lists the steps to rebuild that commit against a modified go-ethereum (web build, go mod edit -replace, CGO_ENABLED=0 go build).

    The LGPL v3 and GPL v3 texts come from go-ethereum's own COPYING.LESSER and COPYING.

  • Failure checks: the tool fails if a linked module ships no licence file, or if any module other than go-ethereum carries GNU GPL-family text. A dependency bump therefore cannot silently leave the notices incomplete.

    • The one listed exception is antd-go. It is published from a subdirectory of ant-sdk, so its module zip carries no licence file; ant-sdk itself is MIT/Apache.
  • Web UI: a small Vite plugin (web/vite.config.ts) records which npm packages the production build actually bundles. web/scripts/third-party-notices.mjs then reproduces their licence files.

    • It also covers the build tools whose output is in the bundle: Tailwind CSS and its PrimeUI preset, and the Vite and Vue plugin helpers.
    • That is 21 packages today. The script fails if one of them has no licence file.
  • third_party/swagger-ui/NOTICES.txt covers the Swagger UI 4.11.0 bundle that github.com/swaggo/files embeds. That module carries only its own MIT licence. This file supplies the Apache-2.0 licence and SmartBear NOTICE of Swagger UI, plus the licences of the 76 npm packages bundled into it.

    • The package list was taken from the bundles' source maps, and the licence files from the published npm packages.
    • Two of those packages publish no licence file, so their licence is taken from the upstream repository.
    • The file needs refreshing when swaggo/files is upgraded.
  • CI: both generators run on every code change, the Go one in the lint job and the web one in the frontend job.

  • README: the licence section now links the real licence files instead of a missing LICENSE.

  • Makefile: make notices generates the file locally.

Verification

Everything below ran locally with Go 1.25.13 and Node 22.

  • Build, lint and tests:
    • go vet ./... is clean.
    • golangci-lint v1.64.8 on ./scripts/... is clean.
    • CGO_ENABLED=0 go build ./cmd/indelible succeeds.
    • npm run build (including vue-tsc) succeeds, and npm run test:unit passes 45 of 45.
    • tsc --noEmit -p tsconfig.node.json passes for the new Vite plugin, which vue-tsc does not type-check.
  • Notices for all four release targets:
    • The run produces 69 modules: 62 linked on every target, the rest platform-specific (for example go-winio and go-ole on Windows only).
    • The output contains the go-ethereum section with COPYING, COPYING.LESSER and metrics/LICENSE.
    • It also contains the grpc NOTICE.txt, the go-oidc and yaml.v2 NOTICEs, the Go LICENSE and PATENTS, the Swagger UI section and the 21 web packages.
  • Docker image target: -targets linux/amd64 lists 64 modules.
  • CI steps: both CI commands pass.
  • Workflow files: both edited workflow files parse as YAML.
  • Docker build: not run locally, because Docker is not available on this machine. The Dockerfile steps were exercised outside Docker with the same commands and paths. The PR's own CI run builds the image, and its Docker build and smoke test pass.

Known limits and out of scope

  • Bare release binaries: they remain bare downloads, and the notices are sibling assets of the same release. Packaging each binary in an archive with its notices would tie the two together on every copy, but it would rename every release asset that installers and docs download today. That is worth doing as its own change.
  • Removing go-ethereum: three files use it, all for wallet and payment code. Whether to remove it is a separate product decision. This PR only ships what its licence asks for while it is linked.
  • antd's own licence notices: they belong in the ant-sdk release. The notices here describe antd as a separate program and record which antd release is bundled.

Closes V2-1395

…he image

Release binaries and the Docker image carried no licence material at all:
.dockerignore excluded LICENSE* and nothing reproduced the notices that the
linked Go modules, the embedded Swagger UI and the bundled web packages
require (MIT, BSD, ISC and Apache-2.0 all ask for this in binary
redistribution). The binary also statically links go-ethereum library code
under the GNU LGPL v3, which has to be identified, with the licence texts and
a pointer to its source.

scripts/notices (standard library only) lists the modules linked into
./cmd/indelible for each release target with `go list -deps` and CGO
disabled, as the release build does, and writes THIRD-PARTY-NOTICES.txt
with every module's licence and notice files (including NOTICE files and
licences kept in subdirectories), the Go standard library licence, the
Swagger UI notices from third_party/swagger-ui and the web UI notices. When
go-ethereum is linked it adds a section naming it, its version, where its
exact source is available, and how to rebuild this Indelible commit against
a modified copy. It records the commit built and the antd release bundled
alongside. It fails when a linked module ships no licence file (antd-go,
published from a subdirectory of the MIT/Apache ant-sdk repository, is the
one listed exception) or when any module other than go-ethereum carries GNU
GPL-family text.

A small Vite plugin records which npm packages the production build actually
bundles, and web/scripts/third-party-notices.mjs reproduces their licence
files plus those of the build tools whose output is in the bundle, failing
when one is missing. CI runs both generators on every code change.

The release workflow uploads THIRD-PARTY-NOTICES.txt, LICENSE-MIT and
LICENSE-APACHE as release assets. The Docker image installs the same three
files under /usr/share/doc/indelible/. The README licence section now points
at the real licence files instead of a missing LICENSE, and `make notices`
generates the file locally.
@jacderida

Copy link
Copy Markdown
Member

Reviewed as part of the V2-1385 sweep (V2-1395). Of all eleven PRs in this sweep, this is the one doing real licence-compliance reasoning rather than paperwork, and writing a purpose-built Go tool instead of reusing the Python generator was the right call for a Go project.

The go-ethereum handling is genuinely well done: a dedicated LGPL section, the LGPL-3.0 and GPL-3.0 texts reproduced in full, a source URL pinned to the exact module version, and step-by-step go mod edit -replace relink instructions — which is what LGPL §4 actually wants from a static link, and the part most projects get wrong. Failing CI when GPL-family text appears in any module other than go-ethereum is a good standing guard. The .dockerignore fix (it was excluding LICENSE*, so the image shipped without even Indelible's own licence) is a nice catch.

Requesting one change: the notices don't travel with the thing they cover.

THIRD-PARTY-NOTICES.txt, LICENSE-MIT and LICENSE-APACHE are uploaded as the indelible-third-party-notices artifact, so after merge-multiple: true they land as separate release assets sitting alongside the binaries. Anyone who downloads just indelible-linux-amd64 — which is the normal way to install this — gets the binary and no notice of any kind. That is precisely the failure mode the parent issue exists to fix, and it's the one channel in this whole sweep where it survives.

Compare the sibling PRs: ant-node and ant-client both put the licence files and notices inside each archive, and both added a line to the release body pointing at them. The release body here is unchanged.

What I'd like, either of:

  1. ship each binary as an archive containing the binary plus LICENSE-MIT, LICENSE-APACHE, THIRD-PARTY-NOTICES.txt — matching ant-node and ant-client, and the most defensible option; or
  2. if you want to keep publishing bare binaries, at minimum add a line to the release body naming the notice assets and stating they apply to every binary in the release, so someone downloading one can find them.

The Docker image is already correct — /usr/share/doc/indelible/ is exactly right — so this is only about the binary downloads.

Happy to approve once either is in.

…ices

The licence files and third-party notices were published as separate
release assets beside bare binaries, so anyone who downloaded a single
binary, the usual way to install, received no notice at all.

The release job now packs each indelible binary into
indelible-<os>-<arch>.tar.gz (indelible-windows-amd64.zip on Windows)
together with LICENSE-MIT, LICENSE-APACHE and THIRD-PARTY-NOTICES.txt,
and publishes those archives in place of the bare binaries. The binary
inside is named indelible (indelible.exe) and is set to mode 0755 in the
tarballs, since workflow artifacts drop file modes. The job fails if any
of the three files is missing. One notices file still covers all four
targets, so it is generated once and copied into every archive.

The bundled antd-* binaries stay separate assets, republished unchanged
from the ant-sdk release named in the release body, which now also says
what each archive contains.

The release asset names change accordingly. Nothing in the WithAutonomi
organisation downloads the old names, and the version check reads only
the release tag and URL. The download walkthrough in FEATURES.md now
fetches the archive from the GitHub release instead of a
releases.autonomi.com host that does not resolve, and the README says
the notices ship inside every release binary archive.
Publishing only archives renamed every indelible release asset, which
would break any download URL or script that fetches the bare binaries.
Every asset name a release has today now stays published with the same
content: the bare indelible-<os>-<arch> binaries, the bundled antd-*
binaries and SHA256SUMS, so releases/download/<tag>/<name> and
releases/latest/download/<name> keep working.

The archives are published alongside them: indelible-<os>-<arch>.tar.gz
(indelible-windows-amd64.zip on Windows) holds a copy of the binary with
LICENSE-MIT, LICENSE-APACHE and THIRD-PARTY-NOTICES.txt. The three files
also stay loose release assets, so someone who downloads a bare binary
finds them in the same release, and SHA256SUMS covers every asset. The
release body now says what the archives contain, that the loose files
apply to the bare binaries, and that the antd-* binaries are the named
ant-sdk release redistributed unchanged.

The FEATURES.md walkthrough goes back to the bare binary, now at its
GitHub release URL, which resolves today. The README describes what the
release workflow publishes.

@dirvine dirvine left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review — archive and download-compatibility request addressed

Reviewed 03caeb075f82a89bb251ae0d420b97121b058a21.

The revised release workflow adds per-platform archives containing the binary, LICENSE-MIT, LICENSE-APACHE and THIRD-PARTY-NOTICES.txt, while preserving the existing bare asset names. The release body also identifies which notices apply. This satisfies both alternatives in the earlier packaging comment.

I executed the actual archive step using explicit synthetic binary fixtures plus the real notice/licence files: all three Unix archives and the Windows ZIP had the expected contents; Unix binary mode was 0755; legacy bare fixtures remained. This verifies packaging logic, not a new production release build. The specialist reviewer also exercised the Go/web notices generators; applicable CI, including Docker build/smoke, is green.

Recommendation: no introduced blocker identified for the requested revision. Keep inherited distribution debt separate: copying the antd binary from its source image does not copy its notice directory; the added cross-reference is not the full daemon notices bundle. That needs its own checked distribution path before declaring the complete product's licence work finished.

The go-ethereum texts/source links/relink instructions are useful engineering evidence, not a blanket legal opinion that all LGPL obligations are satisfied. Advisory review only; no approval or merge performed.

Panel result: the repository specialist, independent GLM-5.2 reviewer, and both adversarial reviewers agree there is no introduced blocker in this revision. Coordinator verification supports that engineering recommendation, with the limitations above.

@dirvine dirvine left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up engineering review

Exact head: 03caeb075f82a89bb251ae0d420b97121b058a21.

No introduced blocker found. Head is identical to the previous six-seat review; this revalidation reuses that packaging evidence rather than claiming repeated builds. Current applicable CI checks pass, including Docker build and smoke test.

Archives include licence texts and notices; existing bare download names/URLs remain unchanged. Bundled antd notice distribution remains pre-existing follow-up work. Notice files and LGPL relink instructions are engineering evidence, not a legal compliance certification. Completed follow-up panel supports the prior recommendation.

Advisory COMMENT review only; no formal approval, merge, release dispatch or legal certification. Browser SDK PR #3 excluded as requested.

@dirvine dirvine left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formal review — APPROVE

Reviewed exact head 03caeb075f82a89bb251ae0d420b97121b058a21.

The previous distribution request is satisfied: each new platform archive includes its binary, both licence texts and third-party notices; the release body also identifies the notices applicable to the retained bare binaries. The completed six-seat panel, including independent GLM-5.2 review, found no actionable blocker after coordinator verification.

Fresh verification: frontend build and web notices generation passed. The Go notices generator passed for all four default release targets under official Go 1.25.13, including LGPL/GPL texts, the nested metrics licence and exact source SHA. Homebrew Go lacked its standard-library LICENSE file; that local toolchain packaging failure did not recur with official Go. The actual archive step passed with explicitly synthetic binary/notice fixtures for three Unix archives and Windows ZIP; Unix executable mode is 0755. Those fixtures test packaging, not production binaries. Exact-head hosted Docker build/smoke CI passes; Docker was not rebuilt locally.

Inherited antd notice-directory distribution remains separate follow-up work. The source links and relink instructions are engineering evidence, not a legal compliance certification. No merge or release performed.

@jacderida
jacderida merged commit 40f002f into master Oct 7, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants