ADR-019: Supply-chain hardening for generated repos
Status: Accepted Date: 2026-10-07
Decision
Section titled “Decision”- Actions are pinned by commit SHA (
uses: owner/repo@<40 hex> # vX) in the platform’s own workflows and in every generated repo. A mutable tag such as@v4lets a compromised upstream release run in our CI with our tokens.scripts/pin-actions.pyresolves and rewrites pins;--checkis a CI guard on the platform. Dependabot’sgithub-actionsecosystem (now configured in every generated repo and in the platform) keeps the SHAs current and understands the version comment. - Least-privilege tokens: every workflow declares
permissions: contents: readat top level; only the image jobs addpackages: write.--checkfails on a workflow without it. - Images are scanned and carry an SBOM: after pushing each architecture by digest, Trivy scans it for fixable HIGH/CRITICAL findings. Release builds (
v*.*.*tags) fail on findings; main builds only report them, so a fresh CVE never blocks day-to-day work but never reaches a release unnoticed. A CycloneDX SBOM per architecture is kept as a workflow artifact for 90 days. Tags are applied only in the later manifest job, so a failed scan publishes no usable tag. - Cluster credentials are split:
cluster-uptakesREPO_TOKEN(fine-grained PAT, Contents: read on the GitOps repo) for ArgoCD andPULL_TOKEN(classic PAT, read:packages) for the pull secret. Without them it falls back to your login token and says so.
Not included (deliberately)
Section titled “Not included (deliberately)”- Keyless signing / SLSA attestations (cosign,
actions/attest-build-provenance): attestations need GitHub Enterprise for private repos, and cosign’s public-good Sigstore writes the repository identity to a public transparency log. Revisit when a repo is public or a private Sigstore is available. BuildKit’s own provenance attestation stays at its default.