ADR-0705: Release engineering and supply chain¶
How Kollect builds, signs, and ships releases: multi-arch images, cosign signing, SBOM + provenance, vulnerability gating, OCI chart publishing, and git-cliff versioning.
Theme: 07 · Project & meta · Status: Current
Context¶
As OSS infrastructure that runs with broad cluster read access, Kollect's supply-chain trust is a
product feature: adopters need to verify what they run. The release pipeline (.github/workflows/release.yaml,
hack/release-assets.sh) implements this, but the decisions weren't recorded. docs/RELEASE.md is the
operator how-to; this ADR is the rationale.
Decision¶
Trigger and versioning¶
- Releases fire on
vX.Y.Ztags (semver, validated in-workflow);workflow_dispatchcan rebuild a tag's assets for testing. - Conventional Commits + gitmoji drive versioning and changelog via git-cliff (
hack/release/cliff.toml); release notes are generated, not hand-written (perAGENTS.md).
Image build¶
- Multi-arch
linux/amd64,linux/arm64via buildx; pushed to GHCR: - Operator:
ghcr.io/<owner>/kollect - Pipeline CLI:
ghcr.io/<owner>/kollect-pipeline - Non-root runtime for the operator (Debian slim with the Git/OpenSSH tools required by the Git backend).
Supply-chain attestations (binding)¶
- SBOM — buildx
sbom: trueplus an SPDX-JSON SBOM (anchore/sbom-action) published as a release asset (dist/sbom.spdx.json). - Provenance — buildx
provenance: mode=max(SLSA-style). - Signing — cosign keyless (Sigstore OIDC,
id-token: write) signs images and Helm chart OCI artifacts by digest; GitHub Release assets are signed withcosign sign-blob(.sigstore.jsonbundles for OpenSSF Scorecard). - Attestations —
actions/attestpublishes SLSA provenance and SPDX SBOM attestations to GHCR and the repository attestations API; release-level provenance is exported asrelease-provenance.intoto.jsonl. - Vulnerability gate — Trivy scans the operator and pipeline release images and fails the release on fixable
CRITICAL/HIGH(ignore-unfixed: true).
Action hardening¶
- All GitHub Actions are pinned by commit SHA; workflow permissions are least-privilege
(
contents: readdefault, elevated per-job only where needed) (ADR-0104).
Release artifacts¶
Each GitHub Release publishes: install-crds.yaml and install.yaml (kubectl install paths —
ADR-0704), the Helm chart .tgz also pushed as OCI to GHCR,
sbom.spdx.json, sbom-pipeline.spdx.json, checksums.txt, per-asset
*.sigstore.json bundles, and release-provenance.intoto.jsonl.
Consequences¶
- Adopters can
cosign verifyby digest and inspect the SBOM before deploying — trust is verifiable. - A new fixable CRITICAL/HIGH CVE blocks the release until the base/deps are bumped (intentional friction).
- SHA-pinned actions mean Renovate and maintainer review keep the pipeline current; stale pins are a known cost.
- Tag-driven releases keep
mainalways-releasable (ADR-0201).
OpenSSF Scorecard follow-ups¶
The project publishes an OpenSSF Scorecard badge
(see README.md). A scheduled workflow (.github/workflows/scorecard.yaml) runs on every main push and
weekly; SARIF results are uploaded to GitHub Code Scanning.
Solo-maintainer policy (2026-07-17): raise OpenSSF Branch-Protection / SAST without a second human reviewer.
- Ruleset
protect-main: require PR, 0 approving reviews while solo-maintained (2026-07-30 operator decision — no second GitHub identity / paid seat for fake review), required status checks (preflight,test,kind-smoke,Analyze (Go)), up-to-date before merge, rebase-only merge methods. Admin remains a bypass actor withbypass_mode: pull_requestonly. Force-push and direct push tomainstay blocked. Scorecard Branch-Protection / Code-Review scores stay low until a real second maintainer joins — accepted residual risk; Environmentrelease+ tag ruleset still gate publication. - CodeQL has no
paths-ignoreso Scorecard SAST sees analysis on every recent commit (target 10). - Code-Review (approved changesets from a second person) and 2-reviewer / CODEOWNERS-required gates remain deferred until a second maintainer joins.
| Check | Score (snapshot) | Status | Rationale |
|---|---|---|---|
| Dangerous-Workflow | 10 | Done | No pull_request_target; workflow inputs passed via env vars; actions SHA-pinned |
| Token-Permissions | 0 high | Partial | Default contents: read; release + changelog-sync still need contents: write |
| Pinned-Dependencies | 10 | Done | Actions pinned to commit SHA; runtime base image by digest; Helm SHA256-verified; pip hash-locked |
| SAST | 9→10 | Done | CodeQL on every push/PR to main (no paths-ignore) + golangci-lint / govulncheck |
| Vulnerabilities | 0 | Open | Re-score after docs dep bumps (click/pillow); OSV may still flag x/crypto/openpgp |
| Security-Policy | 10 | Done | SECURITY.md |
| Dependency-Update-Tool | 10 | Done | Renovate |
| Binary-Artifacts | 10 | Done | No committed binaries |
| License | 10 | Done | MIT |
| Code-Review | 0 high | Deferred | Solo maintainer; non-author APPROVE deliberately not required (2026-07-30) |
| Branch-Protection | 3→6–8 | Done | PR + required checks; 0 review count while solo; Admin PR-only bypass remains |
| Maintained | 0 high | Deferred | Repo < 90 days; improves with continued activity |
| Fuzzing | 10 | Done | Native Go fuzz in CI; OSS-Fuzz deferred |
| CII-Best-Practices | 0 low | Open | Passing badge exists but Best Practices project URL still points at old konih/kollect |
| Contributors | 0 low | N/A | Solo OSS; diversity metric not applicable |
CodeQL (SAST): GitHub CodeQL for Go runs on every push/PR to main (including docs-only), weekly
on Mondays, and uploads results to GitHub Code Scanning (.github/workflows/codeql.yaml). Complements
golangci-lint security linters and govulncheck — not a replacement.
Native Go fuzz: CI job fuzz runs go test -fuzz=FuzzContentHash -fuzztime=30s on
internal/aggregate (export coalesce checksum path). Full OSS-Fuzz integration remains deferred.
Decided follow-ups (2026-06-05, planned v0.4 band)¶
- DONE: Publish signed provenance + SBOM attestations (
actions/attest→ GHCR + attestations API) and release-asset signatures (cosign sign-blob+release-provenance.intoto.jsonl). - DONE: OpenSSF Scorecard workflow + badge (
.github/workflows/scorecard.yaml). - DONE: Sign the Helm chart (
cosign signthe OCI chart artifact) — see release workflow. - TODO: Add
slsa-verifiercheck in release CI for provenance verification.