Notarizing documentation

Release builds

Developer preview. Not yet production ready. This page is rendered from docs/release.md of the Notarizing repository at revision d23579e737f9d1e16e07b3c6b21a51282d64027e. It describes the behavior of that revision.

Contents

This page tells you how to build the release artifacts of notarizing, how to check that the build is reproducible, and how to verify the files that you receive. The rules are in openspec/changes/reimplement-notarizing/n0-decisions.md section 50.

The tooling publishes nothing. It creates no tag, no GitHub release and no upload, and it signs nothing. Publishing is a manual step of the repository owner.

Requirements

  • Go 1.27.0. The build uses GOTOOLCHAIN=local.
  • Node and npm (build time only). The binary does not need Node at run time.
  • Network access to the npm registry. The build installs the browser dependencies from web/package-lock.json into a new, empty npm cache.
  • Access to the private ka2a module (GOPRIVATE='github.com/k-a2a/*'), or a module cache that already has it. See the Build section of the README.
  • A work tree that is exactly HEAD: no changed, staged or untracked file (git status lists nothing; ignored files such as dist/ and web/node_modules are allowed). The artifacts name the commit of HEAD, and the Go and browser builds would also compile an untracked file.

Check for known vulnerabilities

Run this step on the commit that you release, before make release-artifacts. The release build does not run it, because its result depends on the date of the vulnerability databases and the release build depends only on the commit (n0-decisions.md section 59).

go install golang.org/x/vuln/cmd/govulncheck@v1.8.0
make vulncheck

make vulncheck runs govulncheck ./... and npm audit --omit=dev in web/ (the browser packages that ship in the binary). It fails when either reports a vulnerability. It needs network access to vuln.go.dev and the npm registry. Where only the Go module proxy is reachable, build an offline database from the pinned golang.org/x/vulndb module first:

scripts/vulndb.sh /tmp/vulndb
make vulncheck VULNDB=/tmp/vulndb

Keep the output with the qualification reports, for example in reports/qualification/<date>/vulncheck/vulncheck.txt, with the commit and the database version (/tmp/vulndb/VERSION). Also record a positive control: a scan of a small module that calls golang.org/x/text/language.Parse at v0.3.5 must report GO-2021-0113. A recorded scan is valid only for the commit, go.sum and web/package-lock.json that it names.

Build the release artifacts

make release-artifacts VERSION=v1.2.3

The version must have the form vMAJOR.MINOR.PATCH, with an optional pre-release suffix such as v1.2.3-rc.1. The command writes dist/v1.2.3/:

FileContent
notarizing_<version>_<os>_<arch>One binary for each row of the supported platform table.
<binary>.spdx.jsonThe SPDX 2.3 SBOM of that binary: the Go standard library, each linked Go module and each npm package whose code is in the embedded browser assets.
LICENSEThe license of notarizing.
NOTICEThe notice of notarizing. Apache-2.0 section 4(d) requires it in a redistribution.
THIRD_PARTY_NOTICES.mdThe license and notice texts of the Go modules and npm packages that ship.
release-evidence.mdThe commit, the toolchain, the browser assets, the digest of each file, the platform table, the acceptance-ledger counts, what ran, what did not run and the open evidence.
SHA256SUMSThe SHA-256 of every other file.

The command also runs npm ci and the production build in web/. It replaces web/node_modules and the built assets in internal/web/dist.

The build environment is fixed. The tool removes the CGO_ENABLED, GOFLAGS, GOOS, GOARCH, GOEXPERIMENT, GOWORK, GOAMD64 and GOARM64 values of your shell, and the NODE_ENV, NODE_OPTIONS and npm_config_* values. npm does not read your user or global .npmrc (only the project file web/.npmrc). It then sets its own values. It refuses a binary with other recorded build settings, a binary that does not embed the built index.html, and a linked module or shipped npm package that THIRD_PARTY_NOTICES.md does not list with the same version.

For a development cross-build, use a pre-release version, for example make release-artifacts VERSION=v0.0.0-dev.1. There is no other cross-build target.

Check that the build is reproducible

make release-check VERSION=v1.2.3

The check extracts two git archive copies of HEAD into two new directories. Each copy builds the release directory with an empty Go build cache, an empty npm cache and a new node_modules. The check fails when one file of the two release directories, or one file of the two built asset trees, differs. The Go module cache is shared; go.sum verifies it.

To keep the checksums, the SBOMs and the evidence summary of the run, set RELEASE_CHECK_OUT:

make release-check VERSION=v1.2.3 RELEASE_CHECK_OUT=reports/qualification/$(date -u +%F)/release-check

Verify the files that you receive

  1. Put the files and SHA256SUMS in one directory.

  2. Check the digests:

    sha256sum --check --ignore-missing SHA256SUMS

    On macOS, use shasum -a 256 --check SHA256SUMS. Each line must end with OK.

  3. Compare the digest of SHA256SUMS with the value that the owner publishes through a second channel. The tooling does not sign the files, so the checksum file alone does not prove the origin.

  4. Check the version and the commit of the binary:

    ./notarizing_v1.2.3_linux_amd64 --version

    The first line is notarizing v1.2.3. The second line is commit <commit>. The commit must be the commit in release-evidence.md. --output json version also gives the platform.

  5. To rebuild the files yourself, check out that commit and run make release-check with the same version. Your digests can differ when your Go, Node or npm version differs from the versions in release-evidence.md.

Read the SBOM

Each <binary>.spdx.json is an SPDX 2.3 JSON document. It describes one binary:

  • The binary package has the SHA-256 of the binary. Its comment names the commit and the digest of the embedded asset tree.
  • The go-stdlib package is the Go runtime and standard library.
  • Each Go module has its version, its go.sum hash and a pkg:golang package URL. The tool compares this list with the modules that the binary records.
  • Each npm package has its version, the SHA-512 of its integrity hash in web/package-lock.json and a pkg:npm package URL.
  • The declared license comes from THIRD_PARTY_NOTICES.md. The concluded license is NOASSERTION: the tool names the license texts in the files, which is not a legal review.

The document has no time other than the commit time. Two builds of one commit give the same bytes.

To list the components with jq:

jq -r '.packages[] | [.name, .versionInfo, .licenseDeclared] | @tsv' notarizing_v1.2.3_linux_amd64.spdx.json

What the evidence summary does not claim

A platform with "Cross-build only" in the platform table has no test evidence. Its binary is built, not qualified. The release build does not run the Go, browser or integration tests, govulncheck or npm audit. Run them separately (see the README and Check for known vulnerabilities). The section "Open evidence" of release-evidence.md lists every acceptance-ledger row that is not automated.

All Notarizing documents