Repository navigation
release: central fail-closed pre-publish gate (full dependency SBOM, GPL/LGPL/AGPL and UNKNOWN license denial, per-dependency isolated Strix probe) #2342
Description
Central, fail-closed pre-publish gate for PyPI and Rust/crates.io releases, implemented as a reusable workflow in this repository and consumed by release workflows in the sibling repositories. Added to the dot-github lead's goal by the coordinator. No existing issue covers this, so it starts here; related but narrower: #2136 (tagged-commit release-provenance ruleset on Naruon), #2218 (reusable exact-head checkout contract).
Everything in this gate runs in GitHub Actions. There is no LLM key locally, so local Strix execution, key discovery/configuration/copying, and any local LLM fallback are forbidden. Locally we may only author workflow code and non-LLM unit fixtures. Acceptance evidence must be a GitHub Actions run on the exact current head.
1. Full resolved dependency enumeration, SBOM and artifact hashes
- Enumerate every direct and transitive resolved dependency for both ecosystems, from the lockfile and from the actual build environment, and fail when the two disagree.
- Python: the hash-pinned lock plus what is really installed in the build venv.
- Cargo:
Cargo.lockplus the resolved graph of the build, including build-dependencies and the target-specific graph.
- Emit an SBOM and record the sha256 of every produced artifact (wheel, sdist, crate). Reuse the existing exact-artifact path:
exact-artifact-sbom-attestation.ymlalready bindssource_repository,source_sha, artifact filenames and digests, and their SBOM digests.
2. License policy, fail-closed
- Forbidden: GPL and LGPL in every version, both
-onlyand-or-latervariants, and AGPL (treated as GPL-family). Detection must consider all of: the declared SPDX expression; bundledLICENSE/COPYING/NOTICEfiles; files inside the wheel, sdist and crate; and static or dynamic linking targets of any native library shipped or linked. missing,UNKNOWN,custom, and any expression that fails to parse are failures, not warnings.- Dual-licensed dependencies are allowed only when a non-GPL commercially usable option is explicitly selected and the selection rationale is recorded in the artifact provenance.
- A plain string
grepis not an acceptable implementation: the SPDX expression must be parsed, includingAND/OR/WITH, and the archive contents must be inspected.
3. Per-dependency record and isolated Strix probe
- For each resolved dependency record: name, version, source hash, license, and distribution inclusion (does it ship inside our artifact, or is it a build-only or runtime-external dependency).
- Run Strix per dependency against an isolated synthetic fixture, in Actions, using this org's existing secret boundary and approved runners. The simulated surfaces: file parsing, install hooks, archive traversal (path escape), native library loading, credential and network attempts, and known-vulnerability surface.
- Forbidden: attacking real third-party services, and sending participant or company data anywhere. Logs must not contain secrets or sensitive dependency contents.
4. RED and GREEN tests
- RED, each independently: swap one dependency for a GPL/LGPL one; for an unknown-license one; for one with a tampered hash; and for a malicious fixture. Each must fail the gate closed.
- GREEN: a clean MIT/Apache-2.0/BSD fixture passes.
- No
continue-on-error, no allow-failure, no bypass.
Acceptance (all required)
- The reusable workflow exists in
.githubwith its unit fixtures (non-LLM parts testable locally, but the recorded evidence is an Actions run). - A GitHub Actions run on the exact current head shows the RED cases failing and the GREEN case passing.
- End-to-end: fast-mlsirm's release workflow calls this gate as a required check, and a single GPL/LGPL/AGPL or UNKNOWN dependency means the release job never starts. Evidence is the Actions run, not a local reproduction.
- Merging the PR and succeeding at a release are recorded as separate outcomes.
Known sequencing blockers (not part of this gate's design)
opencode-reviewis required in.github, fast-mlsirm and contextual-orchestrator, and no PR can get a verdict until fix(review): point OpenCode at the gateway's /v1 routes and split failure classes #2333 merges.- The Strix evidence-binder defect fails the required
strixcheck in consumer repositories even at zero vulnerabilities; fix is fix(strix): resolve evidence binder from trusted source #2291. pip-auditreports main's inherited anyio CVE; fix is chore(deps): bump anyio from 4.14.0 to 4.14.2 #2278.
Standing scope and the verification checklist for tag/source binding and artifact provenance: docs/triage/release-shepherding-mandate-20260922.md.
Activity
fix(ci): make the release dependency gate executable on a real runner
fix(ci): scan only the fixture, never the trusted binder beside it
feat(ci): decide licences before credentials and compare dependency s…
docs(ci): record the negative-fixture verification plan and its open …
test(ci): pin the empty-enumeration invariant and drop the guard it m…
fix(ci): pin every gate subcommand to the trusted checkout and clarif…
fix(ci): validate lock source directives so capture resolves like ins…
fix(ci): adjudicate every dependency before it is installed
test(ci): cover strict base64 decoding and the non-tick scheduled run
fix(ci): make licence evidence, install binding, and the venv guard real
docs(ci): state the gate toolchain scope limit instead of implying co…
Merge pull request #2347 from ContextualWisdomLab/feat/release-depend…