feat(ci): migrate signed-deploy gate to siax-templates G17 reference (ADR-W16-003)
masterplan-lock / check (push) Successful in 3s
Security Scan (SIAX Cloud) / security (push) Successful in 16s
CI (SIAX Cloud) / integration (push) Successful in 28s
CI (SIAX Cloud) / quality (push) Successful in 35s
masterplan-lock / check (pull_request) Successful in 5s
CI (SIAX Cloud) / security (pull_request) Successful in 13s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 14s
CI (SIAX Cloud) / integration (pull_request) Successful in 28s
CI (SIAX Cloud) / security (push) Successful in 1m24s
CI (SIAX Cloud) / quality (pull_request) Successful in 1m9s
masterplan-lock / check (push) Successful in 3s
Security Scan (SIAX Cloud) / security (push) Successful in 16s
CI (SIAX Cloud) / integration (push) Successful in 28s
CI (SIAX Cloud) / quality (push) Successful in 35s
masterplan-lock / check (pull_request) Successful in 5s
CI (SIAX Cloud) / security (pull_request) Successful in 13s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 14s
CI (SIAX Cloud) / integration (pull_request) Successful in 28s
CI (SIAX Cloud) / security (push) Successful in 1m24s
CI (SIAX Cloud) / quality (pull_request) Successful in 1m9s
0pt's own "P007 pattern" release chain (added 2026-09-14) genuinely failed the ADR-W16-003 promotion bar an audit (2026-09-15) checked it against: syft/cosign installed via curl + a freshly-refetched checksums file (not a pinned, out-of-band-verified digest), no vulnerability scan of the built digest at all, cosign signed only the bare digest (no in-toto/SLSA statement, no source-SHA/build-identity/environment/SBOM-hash binding, no scoped key identity), and evidence committed straight back into this same mutable repo (siax/production-evidence/*.json, siax/source-bundles/*.json -- nine such commits already existed in this repo's history, deleted in this change). Delegates every bar item (1-7: pinned-tool install, SBOM, blocking vuln scan, in-toto attestation, scoped-key signing, pubkey verification, AUD0/ST0RE evidence storage) to sax3l/siax-templates' real, reviewed G17 reference implementation (PR #51, merged, pinned at 384e35060b91ea78ec045e14af114abf5d5eb23b), checked out at CI runtime via the SIAX_CI_TOKEN org secret this repo already had wired for a different cross-repo write -- picked over a vendored copy (the mechanism st0re/cl0ud/ api0 used) because 0pt has no prior vendoring convention anywhere in this repo. Matches aud0/h0st's own migrations for the same reason. See .siax/hooks/README.md for the full composition-mechanism rationale. .siax/hooks/G17.sh is the adapter: owns only 0pt-specific values (image repo, key identity, and a license-allowlist policy measured against 0pt's own real SBOM -- 280 components, one genuine new finding this pass caught that the old gate never checked at all: gcompat's NCSA license, triaged and allowed as the real OS-substrate license it is). cd.yml's own real signed-artifact wait/verify gate (predates this migration, genuinely 0pt-specific -- polls the registry for release.yml's artifact, verifies before triggering Coolify) is KEPT, updated from `cosign verify` (bare digest) to `cosign verify-attestation --type ...` to match the new attestation format `cosign attest` produces. A fresh cosign keypair was generated for this migration -- the previously committed cosign.pub had no corresponding private-key secret ever provisioned on this repo (the old release.yml's own comment confirms: "NOT YET SET on sax3l/0pt as of this writing"), so there was no real existing key material to carry forward. G20 (live-digest-equality) deliberately NOT wired in this pass: 0pt has no Coolify application provisioned and no /version endpoint for it to poll against -- see .siax/hooks/README.md "G20 -- deliberately not wired yet" for what would need to exist first. Verified for real during this migration (see PR description for the full evidence): a real image built from this repo's own Dockerfile, pushed to a local registry, SBOM'd (syft), scanned (trivy, 0 CRITICAL/HIGH findings), DSSE-attested (cosign attest) and verified (cosign verify-attestation) against the new cosign.pub, submitted to a mock AUD0 server enforcing the real eventInputSchema contract, plus three real tamper-rejection negative controls (wrong key, wrong predicate type, never-attested digest) against this exact artifact, plus the reference implementation's own 29/29-assertion selftest (including a real live check against production api.aud0.siax.io). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+36
-19
@@ -27,13 +27,31 @@ jobs:
|
||||
steps:
|
||||
# -----------------------------------------------------------------
|
||||
# SIGNED-ARTIFACT GATE (added 2026-09-14, same pattern as
|
||||
# sax3l/cl0ud + sax3l/st0re's fix/wire-signed-digest-to-deploy): once
|
||||
# the guard step below stops failing (i.e. once a real Coolify app
|
||||
# exists for 0pt and COOLIFY_APP_ID is filled in), this job will
|
||||
# REFUSE to call Coolify at all unless a cosign-verified image exists
|
||||
# in the registry for the EXACT commit being deployed.
|
||||
# `.gitea/workflows/release.yml` (added in this same change) is the
|
||||
# piece that builds, SBOMs, signs, and pushes that image.
|
||||
# sax3l/cl0ud + sax3l/st0re's fix/wire-signed-digest-to-deploy; this
|
||||
# job's own wait-for-signed-artifact polling logic below predates and
|
||||
# is independent of the 2026-09-15 G17 migration, and is KEPT as-is
|
||||
# here -- it is a real, working, 0pt-specific mechanism, not part of
|
||||
# what that migration delegates to siax-templates): once the guard
|
||||
# step below stops failing (i.e. once a real Coolify app exists for
|
||||
# 0pt and COOLIFY_APP_ID is filled in), this job will REFUSE to call
|
||||
# Coolify at all unless a verified attestation exists in the registry
|
||||
# for the EXACT commit being deployed. `.gitea/workflows/release.yml`
|
||||
# is the piece that builds, SBOMs, scans, attests, and pushes that
|
||||
# image (rewritten 2026-09-15 to delegate to sax3l/siax-templates'
|
||||
# G17 reference hook -- see `.siax/hooks/README.md`).
|
||||
#
|
||||
# VERIFY STEP CHANGED 2026-09-15 (part of the G17 migration): the old
|
||||
# release.yml called `cosign sign` on the bare digest, so this job's
|
||||
# gate used `cosign verify`. The new release.yml calls `cosign attest`
|
||||
# instead -- a full DSSE-signed in-toto Statement binding digest +
|
||||
# source SHA + build identity + environment + SBOM hash (ADR-W16-003
|
||||
# bar items 4/5), not just a bare-digest signature. `cosign verify`
|
||||
# against a `cosign attest`-only artifact fails with "no matching
|
||||
# signatures" (attestations and signatures are stored/verified
|
||||
# separately in cosign's model) -- so this step now calls
|
||||
# `cosign verify-attestation --type <predicate-type>` instead, the
|
||||
# same command `.siax/hooks/G17.sh` itself already runs and requires
|
||||
# to PASS before it will submit evidence to AUD0.
|
||||
#
|
||||
# HONEST LIMITATION (identical to cl0ud/st0re/h0st's writeup):
|
||||
# `siax.config.json`'s `deploy.target: "coolify"` and this file's own
|
||||
@@ -102,6 +120,7 @@ jobs:
|
||||
env:
|
||||
IMAGE_REF: ${{ steps.sha.outputs.image_ref }}
|
||||
SHORT: ${{ steps.sha.outputs.short }}
|
||||
PREDICATE_TYPE: https://siax.io/attestations/g17-release-evidence/v1
|
||||
run: |
|
||||
set -euo pipefail
|
||||
test -f cosign.pub || { echo "::error::cosign.pub not found at repo root — cannot verify, refusing to deploy"; exit 1; }
|
||||
@@ -114,13 +133,11 @@ jobs:
|
||||
# hanging forever.
|
||||
#
|
||||
# The loop retries TWO distinct not-ready states (measured live on
|
||||
# run 2265dbb 2026-09-15: deploy pulled the image at 02:36:45 and
|
||||
# failed verify at 02:37:03 with "no signatures found" while the
|
||||
# release run attached the signature at 02:37:11 — an 8-second race
|
||||
# that the pull-only retry missed):
|
||||
# 1. tag not pushed yet (release still building)
|
||||
# 2. tag pushed but signature not attached yet (release between
|
||||
# push and cosign sign)
|
||||
# run 2265dbb 2026-09-15, under the OLD bare-signature gate — the
|
||||
# same race applies to attestation-attach timing today): tag not
|
||||
# pushed yet (release still building) vs. tag pushed but the
|
||||
# attestation not attached yet (release between push and
|
||||
# `cosign attest`).
|
||||
attempt=0
|
||||
max_attempts=40
|
||||
digest=""
|
||||
@@ -147,16 +164,16 @@ jobs:
|
||||
digest="${repo_digest##*@}"
|
||||
echo "$digest" | grep -Eq '^sha256:[0-9a-f]{64}$' || { echo "::error::unexpected digest shape: $digest"; exit 1; }
|
||||
|
||||
echo "verifying cosign signature on ${IMAGE_REPO}@${digest} ..."
|
||||
if cosign verify --key cosign.pub "${IMAGE_REPO}@${digest}" >/tmp/verify.log 2>&1; then
|
||||
echo "verifying cosign attestation on ${IMAGE_REPO}@${digest} ..."
|
||||
if cosign verify-attestation --key cosign.pub --type "$PREDICATE_TYPE" "${IMAGE_REPO}@${digest}" >/tmp/verify.log 2>&1; then
|
||||
break
|
||||
fi
|
||||
if grep -q "no signatures found" /tmp/verify.log; then
|
||||
echo "image present but signature not attached yet (attempt $attempt/$max_attempts) — waiting for release.yml's cosign sign..."
|
||||
if grep -qE "no matching (attestations|signatures) found" /tmp/verify.log; then
|
||||
echo "image present but attestation not attached yet (attempt $attempt/$max_attempts) — waiting for release.yml's cosign attest..."
|
||||
sleep 15
|
||||
continue
|
||||
fi
|
||||
echo "::error::cosign verify FAILED for ${IMAGE_REPO}@${digest} (not a not-ready state — refusing to deploy)"
|
||||
echo "::error::cosign verify-attestation FAILED for ${IMAGE_REPO}@${digest} (not a not-ready state — refusing to deploy)"
|
||||
cat /tmp/verify.log
|
||||
exit 1
|
||||
done
|
||||
|
||||
+99
-230
@@ -1,75 +1,100 @@
|
||||
name: Release chain (P007 pattern)
|
||||
name: Release chain (G17, ADR-W16-003)
|
||||
|
||||
# ADDED 2026-09-14: 0pt had NO SBOM/sign/digest chain at all before this file
|
||||
# (re-confirmed live: no cosign/syft/sbom hit anywhere under .gitea/workflows/,
|
||||
# only doc mentions in CHANGELOG.md/docs/architecture/ARCHITECTURE.md). This
|
||||
# is the proven sax3l/cl0ud + sax3l/st0re pattern (originally inlined
|
||||
# 2026-09-10 from sax3l/siax-standard's release-chain.yml, then hardened
|
||||
# 2026-09-14), authored directly for 0pt because cross-repo `uses:` clones
|
||||
# anonymously on this Gitea instance and fails with "repository not found"
|
||||
# against private repos (the same documented trap that forced cl0ud/st0re to
|
||||
# inline rather than call out to a shared workflow).
|
||||
# Builds + pushes the 0pt image, then hands off to the shared
|
||||
# sax3l/siax-templates G17 reference hook for every ADR-W16-003 bar item
|
||||
# 1-7 (pinned-tool install, SBOM, blocking vuln scan, in-toto attestation,
|
||||
# scoped-key signing, pubkey verification, AUD0/ST0RE evidence storage).
|
||||
#
|
||||
# Cosign keypair is 0pt-specific (generated offline 2026-09-14, never
|
||||
# transmitted anywhere); cosign.pub in the repo root is the corresponding
|
||||
# public key. Neither this Dockerfile nor h0st's declares
|
||||
# `ARG GIT_SHA`/`ARG BUILD_TIME`, so this file does not pass them as
|
||||
# --build-arg (would just produce a harmless-but-noisy "not consumed"
|
||||
# warning) -- GIT_SHA/DIGEST still go into the evidence JSON below either way.
|
||||
# REPLACES this repo's own ad hoc "P007 pattern" release chain (added
|
||||
# 2026-09-14). An audit (2026-09-15) found that chain failed most of the
|
||||
# real promotion bar it claimed to meet: syft/cosign installed via a `curl`
|
||||
# + freshly-refetched checksums file (not a pinned, out-of-band-verified
|
||||
# digest -- see siax-templates' `lib/pinned-tools.sh` header for exactly
|
||||
# why that is not a verified digest), NO vulnerability scan of the built
|
||||
# digest at all, `cosign sign` on the bare digest only (no in-toto/SLSA
|
||||
# statement, no source-SHA/build-identity/environment/SBOM-hash bound
|
||||
# together, no scoped key identity), and evidence committed straight back
|
||||
# into this same mutable repo (`siax/production-evidence/*.json`,
|
||||
# `siax/source-bundles/*.json` -- nine such commits already existed in this
|
||||
# repo's history before this change; deleted in this same PR, superseded by
|
||||
# the real AUD0 write below). This file keeps ONLY what is genuinely
|
||||
# 0pt-specific (image name, tag scheme, registry push, Dockerfile) and
|
||||
# delegates everything else to `.siax/hooks/G17.sh` -> the shared reference
|
||||
# implementation. See `.siax/hooks/README.md` for the pin status and
|
||||
# required secrets (none of which were provisioned for the old gate either
|
||||
# -- see that file's own note).
|
||||
#
|
||||
# STATUS NOTE (see .gitea/workflows/cd.yml's own header): 0pt has NO Coolify
|
||||
# Application provisioned yet -- cd.yml's guard step already fails closed on
|
||||
# the placeholder COOLIFY_APP_ID for that reason, independent of this file.
|
||||
# This release chain is deliberately built ahead of that: once the app
|
||||
# exists and cd.yml's placeholder is replaced with a real UUID, the signed-
|
||||
# artifact gate added to cd.yml in this same change is already wired and
|
||||
# ready, instead of being a second follow-up piece of work.
|
||||
#
|
||||
# Krävda repo-secrets (NOT YET SET on sax3l/0pt as of this writing -- this
|
||||
# file will fail closed on its first run until Simon sets them, same
|
||||
# prerequisite cl0ud/st0re needed before their release.yml went green
|
||||
# 2026-09-10): REGISTRY_USER/REGISTRY_TOKEN (git.cloud.siax.io push),
|
||||
# COSIGN_PRIVATE_KEY/COSIGN_PASSWORD (the private half of this repo's
|
||||
# cosign.pub), SIAX_CI_TOKEN (scoped write:repository token for the
|
||||
# evidence-commit push -- the runner's ephemeral actions token gets a
|
||||
# pre-receive 500, GetUserByID(uid=-2), same fleet-wide gotcha as cl0ud/st0re).
|
||||
# Verification: cosign verify --key cosign.pub git.cloud.siax.io/sax3l/0pt@<digest>
|
||||
# DELIBERATELY ONE JOB. Gitea 1.26 on this fleet resolves org-level
|
||||
# secrets (SIAX_CI_TOKEN below is org-level) only for the FIRST job of a
|
||||
# workflow file -- learned the hard way on sax3l/h0st's and sax3l/aud0's
|
||||
# own G17 migrations. 0pt does not wire a G20 post-deploy step in this
|
||||
# pass at all (see `.siax/hooks/README.md` "G20 -- deliberately not wired
|
||||
# yet": no Coolify application provisioned for 0pt, no `/version`
|
||||
# endpoint), so the single-job constraint that forces G20 into its own
|
||||
# workflow file elsewhere does not yet bite here -- documented anyway so a
|
||||
# future PR adding G20 does not repeat the mistake.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
IMAGE_REPO: git.cloud.siax.io/sax3l/0pt
|
||||
DOCKERFILE: Dockerfile
|
||||
SIAX_TEMPLATES_REPO: sax3l/siax-templates
|
||||
# PIN STATUS 2026-09-15: sax3l/siax-templates PR #51
|
||||
# (feat/g17-signed-deploy-gate-adr-w16-003) MERGED to main, plus three
|
||||
# real follow-up fixes on top -- #56/#57 (SPDX compound-license-
|
||||
# expression evaluation, exercised live by this repo's own
|
||||
# G17_LICENSE_ALLOW policy in .siax/hooks/G17.sh) and #59 (G20 retry
|
||||
# logic -- not used by 0pt yet, but the pin picks up main's current tip
|
||||
# rather than an older commit, matching what a fresh migration reviews).
|
||||
SIAX_TEMPLATES_REF: main
|
||||
SIAX_TEMPLATES_PINNED_SHA: 384e35060b91ea78ec045e14af114abf5d5eb23b
|
||||
SIAX_TEMPLATES_DIR: /tmp/siax-templates-g17-ref
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Build, push, SBOM, sign, record evidence
|
||||
name: Build, push, G17 (SBOM/scan/attest/verify/evidence)
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
env:
|
||||
IMAGE_REPO: git.cloud.siax.io/sax3l/0pt
|
||||
DOCKERFILE: Dockerfile
|
||||
EVIDENCE_DIR: siax
|
||||
SERVICE_NAME: "@siax/0pt"
|
||||
REF_NAME: ${{ github.ref_name }}
|
||||
RUN_ID: ${{ github.run_id }}
|
||||
RUN_ATTEMPT: ${{ github.run_attempt }}
|
||||
steps:
|
||||
- uses: https://git.siax.io/actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4, mirrored + SHA-pinned (SUP-06, same pin n0d/cl0ud/st0re already use)
|
||||
- uses: https://git.siax.io/actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4, mirrored + SHA-pinned (SUP-06, same pin n0d/cl0ud/st0re/h0st already use)
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# --- fetch the shared G17 reference implementation -----------------
|
||||
# Same authenticated-clone-at-runtime mechanism this repo's OLD
|
||||
# release.yml already used SIAX_CI_TOKEN for (the evidence-commit
|
||||
# push this PR deletes) -- see .siax/hooks/G17.sh's header for why
|
||||
# NOT a `uses:` reusable workflow / submodule / vendored copy. Fails
|
||||
# closed if the branch has moved past the exact commit this adapter
|
||||
# was reviewed against.
|
||||
- name: Fetch siax-templates G17 reference (pinned)
|
||||
env:
|
||||
SIAX_CI_TOKEN: ${{ secrets.SIAX_CI_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
rm -rf "$SIAX_TEMPLATES_DIR"
|
||||
git clone --quiet --branch "$SIAX_TEMPLATES_REF" \
|
||||
"https://oauth2:${SIAX_CI_TOKEN}@git.siax.io/${SIAX_TEMPLATES_REPO}.git" "$SIAX_TEMPLATES_DIR"
|
||||
actual_sha="$(git -C "$SIAX_TEMPLATES_DIR" rev-parse HEAD)"
|
||||
if [ "$actual_sha" != "$SIAX_TEMPLATES_PINNED_SHA" ]; then
|
||||
echo "::error::siax-templates $SIAX_TEMPLATES_REF moved (now $actual_sha, pinned $SIAX_TEMPLATES_PINNED_SHA) -- refusing to run an unreviewed version of the gate. Re-review and update SIAX_TEMPLATES_PINNED_SHA deliberately."
|
||||
exit 1
|
||||
fi
|
||||
chmod +x "$SIAX_TEMPLATES_DIR/ci/v2/reference-hooks/"*.sh "$SIAX_TEMPLATES_DIR/ci/v2/reference-hooks/lib/"*.sh
|
||||
echo "siax-templates G17 reference @ $actual_sha (pinned, verified)"
|
||||
|
||||
- name: Resolve SHA + tag (never :latest)
|
||||
id: sha
|
||||
run: |
|
||||
set -euo pipefail
|
||||
full="$(git rev-parse HEAD)"
|
||||
short="$(git rev-parse --short=12 HEAD)"
|
||||
built_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
echo "full=$full" >> "$GITHUB_OUTPUT"
|
||||
echo "short=$short" >> "$GITHUB_OUTPUT"
|
||||
echo "built_at=$built_at" >> "$GITHUB_OUTPUT"
|
||||
echo "image_ref=${IMAGE_REPO}:sha-$short" >> "$GITHUB_OUTPUT"
|
||||
echo "image_tag=sha-$short" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Docker login (git.cloud.siax.io)
|
||||
env:
|
||||
@@ -82,194 +107,38 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
IMAGE_REF: ${{ steps.sha.outputs.image_ref }}
|
||||
IMAGE_TAG: ${{ steps.sha.outputs.image_tag }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
docker build \
|
||||
-f "$DOCKERFILE" \
|
||||
-t "$IMAGE_REF" \
|
||||
.
|
||||
docker build -f "$DOCKERFILE" -t "${IMAGE_REPO}:${IMAGE_TAG}" .
|
||||
|
||||
- name: Push (tag sha-<12>, never :latest)
|
||||
- name: Push (immutable sha-<12> tag, never :latest)
|
||||
env:
|
||||
IMAGE_REF: ${{ steps.sha.outputs.image_ref }}
|
||||
run: docker push "$IMAGE_REF"
|
||||
IMAGE_TAG: ${{ steps.sha.outputs.image_tag }}
|
||||
run: docker push "${IMAGE_REPO}:${IMAGE_TAG}"
|
||||
|
||||
- name: Read back the digest the registry actually stored (never assumed)
|
||||
id: digest
|
||||
# --- G17: everything else, delegated -------------------------------
|
||||
- name: G17 (bar items 1-7, delegated to siax-templates)
|
||||
env:
|
||||
IMAGE_REF: ${{ steps.sha.outputs.image_ref }}
|
||||
ARTIFACT_COMMIT_SHA: ${{ steps.sha.outputs.full }}
|
||||
ARTIFACT_IMAGE_TAG: ${{ steps.sha.outputs.image_tag }}
|
||||
CI_RUN_ID: ${{ github.run_id }}
|
||||
CI_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
G17_COSIGN_KEY: /tmp/0pt-g17-cosign.key
|
||||
G17_COSIGN_KEY_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
|
||||
AUD0_INGEST_TOKEN: ${{ secrets.AUD0_INGEST_TOKEN }}
|
||||
AUD0_TENANT_ID: ${{ secrets.AUD0_TENANT_ID }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# `docker inspect`'s RepoDigests can carry MULTIPLE entries (e.g. one for
|
||||
# whatever this image was originally pulled/built FROM, plus one per registry
|
||||
# it has since been pushed to) — index 0 is not reliably "the one we just
|
||||
# pushed". Filter for the entry whose repo matches IMAGE_REPO instead (same
|
||||
# filter proven live on cl0ud's P007 build-sandbox: a probe push showed
|
||||
# RepoDigests holding both an "alpine@sha256:..." entry AND the
|
||||
# "git.cloud.siax.io/...@sha256:..." entry side by side).
|
||||
repo_digest="$(docker inspect --format='{{json .RepoDigests}}' "$IMAGE_REF" \
|
||||
| node -e "const rd=JSON.parse(require('fs').readFileSync(0,'utf8')); const prefix=process.env.IMAGE_REPO+'@'; const match=rd.find(r=>r.startsWith(prefix)); if(!match){console.error('no RepoDigests entry starting with '+prefix+' among: '+JSON.stringify(rd));process.exit(1);} console.log(match);")"
|
||||
digest="${repo_digest##*@}"
|
||||
echo "$digest" | grep -Eq '^sha256:[0-9a-f]{64}$' || { echo "::error::unexpected digest shape: $digest"; exit 1; }
|
||||
echo "digest=$digest" >> "$GITHUB_OUTPUT"
|
||||
echo "pushed and verified: $IMAGE_REF @ $digest"
|
||||
echo "${{ secrets.COSIGN_PRIVATE_KEY }}" > "$G17_COSIGN_KEY"
|
||||
trap 'rm -f "$G17_COSIGN_KEY"' EXIT
|
||||
bash .siax/hooks/G17.sh
|
||||
|
||||
# KNOWN RISK, NOT YET FIXED (same open issue as cl0ud's/st0re's/h0st's
|
||||
# copy of this file, flagged 2026-09-03/09-14): this fleet's runner
|
||||
# egress is confirmed to reach raw.githubusercontent.com but NOT
|
||||
# github.com/*/releases/download URLs (curl -sfL -> silent failure).
|
||||
# The two `curl -fsSL -O https://github.com/.../releases/download/...`
|
||||
# steps below (syft, cosign) use exactly that broken URL shape, and
|
||||
# neither tool ships a raw.githubusercontent.com-hosted installer that
|
||||
# avoids a github.com/releases fetch for the actual binary. Left as
|
||||
# pinned, checksum-verified curl installs, same as cl0ud/st0re/h0st;
|
||||
# the first real run of this file on 0pt's own runners is the first
|
||||
# live evidence for OR against this risk actually manifesting here
|
||||
# (not simulated in this dry-run pass — see PR description).
|
||||
- name: Install syft v1.51.1 (pinned, checksum-verified — never :latest)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd /tmp
|
||||
curl -fsSL -O https://github.com/anchore/syft/releases/download/v1.51.1/syft_1.51.1_linux_amd64.tar.gz
|
||||
curl -fsSL -O https://github.com/anchore/syft/releases/download/v1.51.1/syft_1.51.1_checksums.txt
|
||||
grep 'syft_1.51.1_linux_amd64.tar.gz' syft_1.51.1_checksums.txt | sha256sum -c -
|
||||
tar -xzf syft_1.51.1_linux_amd64.tar.gz syft
|
||||
install -m 0755 syft /usr/local/bin/syft
|
||||
syft version
|
||||
|
||||
- name: Install cosign v3.1.3 (pinned, checksum-verified — never :latest)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd /tmp
|
||||
curl -fsSL -O https://github.com/sigstore/cosign/releases/download/v3.1.3/cosign-linux-amd64
|
||||
curl -fsSL -O https://github.com/sigstore/cosign/releases/download/v3.1.3/cosign_checksums.txt
|
||||
grep 'cosign-linux-amd64$' cosign_checksums.txt | sha256sum -c -
|
||||
install -m 0755 cosign-linux-amd64 /usr/local/bin/cosign
|
||||
cosign version
|
||||
|
||||
- name: SBOM (syft, spdx-json, against the DIGEST not the tag)
|
||||
env:
|
||||
DIGEST: ${{ steps.digest.outputs.digest }}
|
||||
SHORT: ${{ steps.sha.outputs.short }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p "$EVIDENCE_DIR/_release-artifacts"
|
||||
syft "${IMAGE_REPO}@${DIGEST}" -o "spdx-json=${EVIDENCE_DIR}/_release-artifacts/sbom-${SHORT}.spdx.json"
|
||||
|
||||
- name: Sign (cosign, key-based — see cosign.pub at repo root)
|
||||
env:
|
||||
COSIGN_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}
|
||||
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
|
||||
DIGEST: ${{ steps.digest.outputs.digest }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "$COSIGN_KEY" > /tmp/cosign.key
|
||||
cosign sign --yes --key /tmp/cosign.key "${IMAGE_REPO}@${DIGEST}"
|
||||
rm -f /tmp/cosign.key
|
||||
|
||||
- name: Verify the signature just written (fail closed if it does not verify)
|
||||
env:
|
||||
DIGEST: ${{ steps.digest.outputs.digest }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
test -f cosign.pub || { echo "::error::cosign.pub not found at repo root — commit the PUBLIC key (not a secret) so anyone can verify without CI access"; exit 1; }
|
||||
cosign verify --key cosign.pub "${IMAGE_REPO}@${DIGEST}"
|
||||
|
||||
- name: Write siax.source-bundle + siax.production-evidence records
|
||||
env:
|
||||
SHA_FULL: ${{ steps.sha.outputs.full }}
|
||||
SHA_SHORT: ${{ steps.sha.outputs.short }}
|
||||
DIGEST: ${{ steps.digest.outputs.digest }}
|
||||
IMAGE_REF: ${{ steps.sha.outputs.image_ref }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p "$EVIDENCE_DIR/source-bundles" "$EVIDENCE_DIR/production-evidence"
|
||||
now="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
repo_name="$(basename "$(git rev-parse --show-toplevel)")"
|
||||
|
||||
cat > "$EVIDENCE_DIR/source-bundles/release-${SHA_SHORT}.json" <<JSON
|
||||
{
|
||||
"id": "sb-release-${SHA_SHORT}",
|
||||
"repo": "$repo_name",
|
||||
"commitSha": "$SHA_FULL",
|
||||
"branch": "$REF_NAME",
|
||||
"buildId": "${RUN_ID}-${RUN_ATTEMPT}",
|
||||
"artifactId": "$IMAGE_REF",
|
||||
"producedAt": "$now"
|
||||
}
|
||||
JSON
|
||||
|
||||
cat > "$EVIDENCE_DIR/production-evidence/release-${SHA_SHORT}-artifact.json" <<JSON
|
||||
{
|
||||
"id": "pe-artifact-${SHA_SHORT}",
|
||||
"repo": "$repo_name",
|
||||
"evidenceType": "artifact-digest",
|
||||
"verifiedAt": "$now",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "pushed $IMAGE_REF to $IMAGE_REPO",
|
||||
"tool": "docker",
|
||||
"sourceSha": "$SHA_FULL",
|
||||
"digest": "$DIGEST"
|
||||
}
|
||||
JSON
|
||||
|
||||
cat > "$EVIDENCE_DIR/production-evidence/release-${SHA_SHORT}-sbom.json" <<JSON
|
||||
{
|
||||
"id": "pe-sbom-${SHA_SHORT}",
|
||||
"repo": "$repo_name",
|
||||
"evidenceType": "sbom",
|
||||
"verifiedAt": "$now",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "$EVIDENCE_DIR/_release-artifacts/sbom-${SHA_SHORT}.spdx.json",
|
||||
"tool": "syft",
|
||||
"sbomFormat": "spdx-json",
|
||||
"digest": "$DIGEST"
|
||||
}
|
||||
JSON
|
||||
|
||||
cat > "$EVIDENCE_DIR/production-evidence/release-${SHA_SHORT}-signature.json" <<JSON
|
||||
{
|
||||
"id": "pe-signature-${SHA_SHORT}",
|
||||
"repo": "$repo_name",
|
||||
"evidenceType": "signature",
|
||||
"verifiedAt": "$now",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "cosign verify --key cosign.pub ${IMAGE_REPO}@${DIGEST} (verified in this same run)",
|
||||
"tool": "cosign",
|
||||
"signatureTool": "cosign",
|
||||
"keyless": false,
|
||||
"digest": "$DIGEST"
|
||||
}
|
||||
JSON
|
||||
|
||||
# upload-artifact deliberately OMITTED: act_runner on this fleet has no
|
||||
# GHES-artifact-API, so upload-artifact@v4 always dies even with
|
||||
# continue-on-error: true and can abort the whole job before the
|
||||
# evidence-commit step below runs (proven on cl0ud run 23340, fixed
|
||||
# there 2026-09-14 by deleting the step outright — applied here from
|
||||
# the start instead of repeating the same bug). Evidence lands in the
|
||||
# repo via the commit step below regardless.
|
||||
- name: Commit evidence back to the calling repo
|
||||
if: true
|
||||
env:
|
||||
SHA_SHORT: ${{ steps.sha.outputs.short }}
|
||||
SIAX_CI_TOKEN: ${{ secrets.SIAX_CI_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
git config user.name "siax-ci"
|
||||
git config user.email "ci@siax.io"
|
||||
git add "$EVIDENCE_DIR/source-bundles" "$EVIDENCE_DIR/production-evidence"
|
||||
if git diff --cached --quiet; then
|
||||
echo "no evidence changes to commit"
|
||||
else
|
||||
git commit -m "chore(release-chain): evidence for sha-${SHA_SHORT} [skip ci]"
|
||||
# Runnerns ephemeral actions-token (uid -2) kan inte pusha:
|
||||
# pre-receive GetUserByID(-2) → 500. Autentisera som riktig
|
||||
# Gitea-user via SIAX_CI_TOKEN (samma mönster som cl0ud/st0re/h0st).
|
||||
git config http.https://git.siax.io/.extraheader "AUTHORIZATION: basic $(printf 'x-access-token:%s' "${SIAX_CI_TOKEN}" | base64 -w0)"
|
||||
git push origin "HEAD:${REF_NAME}"
|
||||
fi
|
||||
# NOTE: deliberately NO `actions/upload-artifact@v4` step here.
|
||||
# sax3l/cl0ud's release.yml (run 23340, 2026-09-14) documents that
|
||||
# this Gitea instance's act_runner does not reliably support
|
||||
# upload-artifact@v4 even with continue-on-error: true, and that it
|
||||
# can abort the whole job before later steps run. G17.sh's own AUD0
|
||||
# submission (bar item 7, step above) is already the durable evidence
|
||||
# record; a convenience local copy is not worth re-triggering that
|
||||
# known breakage.
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"schemaVersion": "siax.hook-pin/v1",
|
||||
"repo": "0pt",
|
||||
"hooks": {
|
||||
"G17": {
|
||||
"contract": "ci/v2 G17 (Artifact security) -- ADR-W16-003 promotion bar",
|
||||
"sourcePath": "ci/v2/reference-hooks/{G17.sh,lib/*}",
|
||||
"consumedAs": [".siax/hooks/G17.sh"],
|
||||
"compositionMechanism": "checkout-at-CI-runtime (pinned commit, SIAX_CI_TOKEN), not a vendored copy -- see .siax/hooks/README.md"
|
||||
}
|
||||
},
|
||||
"templateRepo": "sax3l/siax-templates",
|
||||
"templateRef": "384e35060b91ea78ec045e14af114abf5d5eb23b",
|
||||
"templateBranch": "main",
|
||||
"templatePr": "sax3l/siax-templates#51",
|
||||
"prStatus": "MERGED to main, plus follow-up fixes #56/#57/#59 already included at this pin",
|
||||
"pinnedAt": "2026-09-15T17:00:00Z",
|
||||
"reSyncInstructions": "If siax-templates main moves past this commit: review the diff (`git -C <clone> log 384e35060b91ea78ec045e14af114abf5d5eb23b..main -- ci/v2/reference-hooks`), re-run this migration's local verification (real local registry + docker build from this repo's own Dockerfile + G17.sh end-to-end + tamper-rejection checks -- see the PR description for the exact commands used), then bump SIAX_TEMPLATES_PINNED_SHA in .gitea/workflows/release.yml and this file's templateRef together in one reviewed commit.",
|
||||
"notes": "Supersedes 0pt's own ad hoc 'P007 pattern' release.yml (added 2026-09-14, audited 2026-09-15 and found to fail most of ADR-W16-003's bar: syft/cosign installed via unpinned-digest curl+checksums-refetch, no vulnerability scan of the built digest, cosign signed only the bare digest -- not a full in-toto predicate -- evidence committed back into this mutable repo at siax/production-evidence/*.json + siax/source-bundles/*.json instead of AUD0/ST0RE, no live-digest-equality proof). This pin replaces that ad hoc logic with sax3l/siax-templates' real, reviewed reference implementation; 0pt keeps only its own adapter values (image repo, license policy, key identity -- see G17.sh's own header) plus the pre-existing 0pt-specific signed-artifact wait/verify gate in cd.yml (kept, updated to cosign verify-attestation). G20 (live-digest-equality) deliberately NOT wired in this pass -- see .siax/hooks/README.md."
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env bash
|
||||
# 0pt's G17 (Artifact security) hook adapter.
|
||||
#
|
||||
# 0pt's OWN release chain (`.gitea/workflows/release.yml`, added 2026-09-14
|
||||
# as "P007 pattern") had a signing/SBOM chain -- but an audit (2026-09-15)
|
||||
# found it failed most of the real ADR-W16-003 promotion bar it claimed to
|
||||
# meet: syft/cosign installed via a `curl` + freshly-refetched checksums
|
||||
# file (not a pinned digest), NO vulnerability scan of the built digest at
|
||||
# all, `cosign sign` on the bare digest only (not source-SHA/build-identity/
|
||||
# environment/SBOM-hash bound together), no in-toto/SLSA statement, and
|
||||
# evidence committed straight back into this same mutable repo
|
||||
# (`EVIDENCE_DIR="siax"` -> `siax/production-evidence/*.json`,
|
||||
# `siax/source-bundles/*.json`, pushed with a SIAX_CI_TOKEN-authenticated
|
||||
# `git push` on every release -- nine such commits already sit in this
|
||||
# repo's history). This adapter, plus the rewritten `release.yml`, replaces
|
||||
# that chain; the previous `siax/production-evidence/` and
|
||||
# `siax/source-bundles/` trees are deleted in this same change (superseded,
|
||||
# not left dangling -- see the PR description for exactly what a `git log`
|
||||
# on those paths still shows for history).
|
||||
#
|
||||
# This adapter owns ONLY 0pt-specific values -- every ADR-W16-003 bar item
|
||||
# (1-7: pinned-tool install, SBOM, blocking vuln scan, in-toto attestation,
|
||||
# scoped-key signing, pubkey verification, AUD0/ST0RE evidence storage) is
|
||||
# implemented ONCE in sax3l/siax-templates and executed here unmodified, per
|
||||
# that reference file's own header: "This file is starting material a
|
||||
# consumer repo copies to `.siax/hooks/G17.sh` and adapts -- it owns only
|
||||
# the adapter ... `siax-templates` remains the sole owner of the G17
|
||||
# CONTRACT and this reference implementation."
|
||||
#
|
||||
# --- Composition mechanism: checkout-at-CI-runtime, not a vendored copy ---
|
||||
# `.gitea/workflows/release.yml` clones sax3l/siax-templates at a pinned
|
||||
# commit into $SIAX_TEMPLATES_DIR before calling this file, authenticated
|
||||
# with the SIAX_CI_TOKEN org secret 0pt's OWN release.yml already had wired
|
||||
# for a DIFFERENT cross-repo write (the evidence-commit push this same
|
||||
# change deletes) -- so the token and the auth idiom
|
||||
# (`https://oauth2:${SIAX_CI_TOKEN}@git.siax.io/...`) are not new to this
|
||||
# repo, only their use for a `git clone` of a sibling repo is. Picked over
|
||||
# vendoring (the mechanism sax3l/st0re, sax3l/cl0ud and sax3l/api0's own
|
||||
# G17 migrations used) because 0pt has ZERO prior vendored-copy convention
|
||||
# anywhere in this repo (`grep -rl vendor .gitea/workflows/ .siax/` finds
|
||||
# nothing, confirmed before writing this file) -- introducing one now, for
|
||||
# this alone, would be a bigger repo-shape change than reusing the
|
||||
# SIAX_CI_TOKEN pattern 0pt already has proof it can authenticate with.
|
||||
# Matches sax3l/aud0 and sax3l/h0st's own G17 migrations, which
|
||||
# independently made the same choice for the same reason. See
|
||||
# `ci/shim/ci.yml` in siax-templates for why NOT a native
|
||||
# `uses: sax3l/siax-templates/...@ref` reusable workflow (Gitea Actions
|
||||
# clones a called repo ANONYMOUSLY, so this 404s on every private sax3l
|
||||
# repo).
|
||||
#
|
||||
# GOTCHA LEARNED FROM sax3l/h0st's OWN MIGRATION (its
|
||||
# `cl0ud-real-policy.yml` header, and independently from sax3l/aud0's):
|
||||
# Gitea 1.26 on this fleet resolves ORG-level secrets (SIAX_CI_TOKEN is
|
||||
# org-level) only for the FIRST job of a multi-job workflow file. That is
|
||||
# exactly why `release.yml` (this file's caller) is a single-job workflow.
|
||||
# 0pt does not wire a G20 (live-digest-equality) post-deploy step in this
|
||||
# pass -- see `.siax/hooks/README.md` "G20 -- deliberately not wired yet"
|
||||
# for why (no Coolify application provisioned for 0pt at all, and no
|
||||
# `/version` endpoint for a live check to poll -- both genuine
|
||||
# infrastructure gaps, not something this CI adapter can close).
|
||||
#
|
||||
# PIN STATUS (2026-09-15): sax3l/siax-templates PR #51
|
||||
# (`feat/g17-signed-deploy-gate-adr-w16-003`) is MERGED to main, plus three
|
||||
# real follow-up fixes already on top of that merge as of this pin --
|
||||
# bf0c157/#56 "evaluate compound SPDX license expressions per SPDX
|
||||
# semantics", 794546f/#57 "skip bare SPDX operator tokens emitted as their
|
||||
# own license entry" (both exercised live below via G17_LICENSE_ALLOW
|
||||
# against 0pt's real SBOM), and e1230a1/#59 "retry on observed-but-
|
||||
# different sha" (a G20 fix; 0pt does not use G20 yet, but the pin still
|
||||
# picks up main's current tip rather than an older commit, matching what a
|
||||
# fresh migration reviews). Pinned at
|
||||
# 384e35060b91ea78ec045e14af114abf5d5eb23b -- the exact ref lives in
|
||||
# `.gitea/workflows/release.yml` (SIAX_TEMPLATES_REF=main +
|
||||
# SIAX_TEMPLATES_PINNED_SHA, which refuses to run if main has moved past
|
||||
# the pin).
|
||||
set -euo pipefail
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
|
||||
: "${SIAX_TEMPLATES_DIR:?set by the calling workflow step to the path siax-templates was checked out to}"
|
||||
REFERENCE_G17="$SIAX_TEMPLATES_DIR/ci/v2/reference-hooks/G17.sh"
|
||||
[ -x "$REFERENCE_G17" ] || {
|
||||
echo "0pt G17 adapter: FAIL: $REFERENCE_G17 not found/executable -- was the siax-templates checkout step run first, and did chmod +x survive the clone?" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# --- 0pt-specific adapter values --------------------------------------------
|
||||
export ARTIFACT_IMAGE_REPO="${ARTIFACT_IMAGE_REPO:-git.cloud.siax.io/sax3l/0pt}"
|
||||
export ARTIFACT_COMMIT_SHA="${ARTIFACT_COMMIT_SHA:?set by release.yml to the full 40-hex commit SHA this image was built from}"
|
||||
export ARTIFACT_IMAGE_TAG="${ARTIFACT_IMAGE_TAG:?set by release.yml, e.g. sha-<12-hex> -- never :latest}"
|
||||
export G17_ENVIRONMENT="production"
|
||||
export G17_KEY_IDENTITY="siax-svc-g17/0pt/production"
|
||||
|
||||
# The reference script's own default for G17_COSIGN_PUBKEY assumes it was
|
||||
# COPIED to .siax/hooks/G17.sh inside the consumer repo (relative path
|
||||
# lands at the consumer's own root). This adapter instead runs the
|
||||
# reference script from a SEPARATE checkout ($SIAX_TEMPLATES_DIR) -- that
|
||||
# default would resolve inside siax-templates' own checkout, not 0pt's --
|
||||
# so it must be pointed explicitly at 0pt's own committed key.
|
||||
export G17_COSIGN_PUBKEY="$REPO_ROOT/cosign.pub"
|
||||
|
||||
# G17_COSIGN_KEY / G17_COSIGN_KEY_PASSWORD / AUD0_INGEST_TOKEN /
|
||||
# AUD0_TENANT_ID are Infisical-injected repo secrets -- release.yml exports
|
||||
# them from `secrets.*` before calling this file. This adapter deliberately
|
||||
# never reads, echoes or forwards a raw secret value itself; it only relies
|
||||
# on them already being present in the environment the reference script
|
||||
# inherits.
|
||||
|
||||
# License policy -- measured 2026-09-15 against 0pt's OWN real signed
|
||||
# artifact SBOM (280 components; real local-registry verification run
|
||||
# performed during this migration, not copied from another repo's policy):
|
||||
# * G17_LICENSE_ALLOW_UNKNOWN=1 -- 177/280 components declare no license
|
||||
# field at all in their packed metadata (transitive npm packages --
|
||||
# next/react/sharp's own dependency tree -- there is no fix for
|
||||
# third-party metadata from this repo). Same opt-in st0re/aud0/h0st
|
||||
# already record; visible in the attestation evidence, not silent.
|
||||
# * G17_LICENSE_ALLOW below is the exact, minimal set of SPDX ids AND
|
||||
# compound-expression branches 0pt's real SBOM needs once unknowns are
|
||||
# allowed -- every id was individually present in the real scan
|
||||
# output (`python3 -c "..." verify-work/e2e-out/sbom.cdx.json` run
|
||||
# during this migration), not a broad copy of a sibling repo's list.
|
||||
# GPL-2.0-only/GPL-2.0-or-later/GPL-3.0-or-later/LGPL-2.1-or-later/
|
||||
# LGPL-3.0-or-later/Zlib/OpenSSL-Exception/NCSA cover alpine's own base
|
||||
# packages this image's `RUN apk add --no-cache libc6-compat wget` (+
|
||||
# the deps/sharp/build stages' own libc6-compat installs) pull in --
|
||||
# the OS substrate node:22-alpine ships, not a dependency 0pt chose.
|
||||
# NCSA specifically is gcompat's real declared license (a first real
|
||||
# finding this migration's initial run caught and triaged: the OLD ad
|
||||
# hoc gate never scanned licenses at all, so this had never been
|
||||
# checked before). MIT/BSD-2-Clause/BSD-3-Clause/ISC/0BSD/Apache-2.0/
|
||||
# CC0-1.0/BlueOak-1.0.0/MPL-2.0 cover the Next.js/React/sharp npm
|
||||
# dependency tree's own real declared licenses, including the compound
|
||||
# "MPL-2.0 AND MIT" and "GPL-2.0-or-later AND LGPL-2.1-or-later"
|
||||
# expressions actually present in the SBOM (evaluated per real SPDX
|
||||
# AND/OR semantics -- the two 2026-09-15 siax-templates fixes #56/#57
|
||||
# this pin includes).
|
||||
export G17_LICENSE_ALLOW_UNKNOWN="1"
|
||||
export G17_LICENSE_ALLOW="${G17_LICENSE_ALLOW:-BlueOak-1.0.0,GPL-2.0-only,GPL-2.0-or-later,GPL-3.0-or-later,LGPL-2.1-or-later,LGPL-3.0-or-later,Zlib,OpenSSL-Exception,NCSA,MIT,BSD-2-Clause,BSD-3-Clause,ISC,0BSD,Apache-2.0,CC0-1.0,MPL-2.0}"
|
||||
|
||||
echo "0pt G17 adapter: delegating to $REFERENCE_G17 for artifact $ARTIFACT_IMAGE_REPO:$ARTIFACT_IMAGE_TAG"
|
||||
exec bash "$REFERENCE_G17"
|
||||
@@ -0,0 +1,104 @@
|
||||
# `.siax/hooks/` -- 0pt's G17 (signed-deploy gate) adapter
|
||||
|
||||
## What this is
|
||||
|
||||
`G17.sh` in this directory is a thin **adapter**: it sets 0pt-specific
|
||||
values (image repo, environment, key identity, license policy) and then
|
||||
`exec`s the real, reviewed reference implementation checked out at CI
|
||||
runtime from `sax3l/siax-templates` (`ci/v2/reference-hooks/G17.sh`). This
|
||||
repo does not own, fork, or duplicate any of the ADR-W16-003 bar-item logic
|
||||
itself -- see `G17.sh`'s own header for the full rationale and the audit
|
||||
that motivated replacing 0pt's prior ad hoc gate.
|
||||
|
||||
## Composition mechanism: pinned-commit checkout at CI runtime
|
||||
|
||||
`.gitea/workflows/release.yml` clones `sax3l/siax-templates` at a pinned
|
||||
commit into a scratch directory before invoking `.siax/hooks/G17.sh`,
|
||||
authenticated with the `SIAX_CI_TOKEN` org secret. This was chosen over a
|
||||
vendored copy under `.siax/hooks/vendor/` (the mechanism `st0re`, `cl0ud`
|
||||
and `api0` used for their own G17 migrations) because 0pt has **no existing
|
||||
vendored-copy convention anywhere in this repo** -- confirmed by searching
|
||||
`.gitea/workflows/` and `.siax/` for any prior "vendor" pattern before
|
||||
choosing -- while it **does** already reference `SIAX_CI_TOKEN` with the
|
||||
exact same `git.siax.io` authenticated-clone idiom this change reuses (the
|
||||
now-deleted evidence-commit-push step in the old `release.yml` used the
|
||||
identical `x-access-token`/`oauth2` bearer pattern for a different
|
||||
cross-repo write). Reusing a pattern this repo already has proof it can
|
||||
authenticate with is a smaller, lower-risk change than introducing a new
|
||||
vendoring convention for this alone. `sax3l/aud0` and `sax3l/h0st`'s own
|
||||
G17 migrations independently reached the same conclusion for the same
|
||||
reason.
|
||||
|
||||
## Why not a `uses:` reusable workflow
|
||||
|
||||
Gitea Actions on this fleet resolves a called repository **anonymously**
|
||||
regardless of the caller's own auth, so `uses: sax3l/siax-templates/...@ref`
|
||||
404s against any private `sax3l` repo. See `ci/shim/ci.yml` in
|
||||
`siax-templates` for the fuller writeup. Checkout-at-runtime with an
|
||||
authenticated clone is the only mechanism that works against a private
|
||||
template repo on this Gitea instance.
|
||||
|
||||
## Pin status
|
||||
|
||||
Pinned to `sax3l/siax-templates` main at
|
||||
`384e35060b91ea78ec045e14af114abf5d5eb23b` (2026-09-15) -- PR #51
|
||||
(`feat/g17-signed-deploy-gate-adr-w16-003`) merged, plus follow-up fixes
|
||||
#56/#57 (SPDX compound-license-expression evaluation, exercised live by
|
||||
this adapter's own `G17_LICENSE_ALLOW` policy) and #59 (G20 retry logic;
|
||||
not used by 0pt yet, see below). `.gitea/workflows/release.yml`'s own
|
||||
`SIAX_TEMPLATES_PINNED_SHA` step refuses to run if `siax-templates` main
|
||||
has moved past this exact commit -- bumping the pin is a reviewed,
|
||||
source-controlled diff to that one line, never a silent re-resolution.
|
||||
|
||||
## G20 (live-digest-equality) -- deliberately not wired yet
|
||||
|
||||
The reference implementation's bar item 8 proxy (`G20`, "does the running
|
||||
service's own `/version` endpoint report the sha that was actually signed")
|
||||
needs two things 0pt does not have today, confirmed live before writing
|
||||
this file:
|
||||
|
||||
1. **A provisioned Coolify application.** `.gitea/workflows/cd.yml`'s own
|
||||
guard step already fails closed on a literal `COOLIFY_APP_ID` placeholder
|
||||
-- 0pt has never been deployed to the fleet.
|
||||
2. **A `/version` (or equivalent) endpoint.** `app/api/` has `health/` and
|
||||
`ready/` routes but no route reporting a build SHA, and the Dockerfile
|
||||
declares no `ARG GIT_SHA`/`ARG BUILD_TIME` to bake one in.
|
||||
|
||||
Wiring G20 against nothing live would be decorative, not a real check --
|
||||
the exact anti-pattern this whole migration replaces. Once both exist
|
||||
(Simon provisions the Coolify app; a follow-up adds a `/api/version` route
|
||||
and the Dockerfile `ARG`s, the same small change `h0st`'s own migration
|
||||
made), copy `G20.sh` + its own single-job `.gitea/workflows/
|
||||
g20-live-verify.yml` from `h0st` or `aud0`'s repo as the starting point --
|
||||
**as its own workflow file**, not a second job appended to `cd.yml`: Gitea
|
||||
1.26 on this fleet resolves org-level secrets (`SIAX_CI_TOKEN`,
|
||||
`AUD0_INGEST_TOKEN`) only for the **first** job of a multi-job workflow
|
||||
file (learned the hard way on `h0st`'s and `aud0`'s own migrations).
|
||||
|
||||
## Required secrets (not yet set on `sax3l/0pt` as of this migration)
|
||||
|
||||
Same prerequisite every prior migration needed before its `release.yml`
|
||||
went green:
|
||||
|
||||
- `REGISTRY_USER` / `REGISTRY_TOKEN` -- `git.cloud.siax.io` push (already
|
||||
required by the OLD release.yml too; unchanged).
|
||||
- `COSIGN_PRIVATE_KEY` / `COSIGN_PASSWORD` -- the private half of this
|
||||
repo's `cosign.pub`. **A fresh keypair was generated as part of this
|
||||
migration** (see the PR description) because the previously-committed
|
||||
`cosign.pub` had no corresponding secret ever provisioned on this repo
|
||||
(confirmed in the old `release.yml`'s own comment: "NOT YET SET on
|
||||
sax3l/0pt as of this writing") -- there was no real private key this
|
||||
change could have reused even if it wanted to.
|
||||
- `AUD0_INGEST_TOKEN` / `AUD0_TENANT_ID` -- new requirement vs. the old
|
||||
gate (which never wrote to AUD0 at all). Needs a `siax-svc-g17`
|
||||
workload-identity client provisioned in Zitadel, same open item every
|
||||
prior migration recorded (see `G17-ADR-W16-003.md` "What this pass could
|
||||
not test against production, and why" in `siax-templates`).
|
||||
- `SIAX_CI_TOKEN` -- already exists on this repo (used previously for the
|
||||
now-deleted evidence-commit push); reused here for the `siax-templates`
|
||||
checkout.
|
||||
|
||||
Until these are set, `release.yml` fails closed on its first real run --
|
||||
same honest behaviour as the gate it replaces, and the same prerequisite
|
||||
`cl0ud`/`st0re`/`aud0`/`api0`/`h0st` each had before their own `release.yml`
|
||||
went green.
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3EIrsPWBhSnH6HL7yD9US1RtXDg4
|
||||
kHaLp8mDefBhepQRFsFPedyWwNaaqEwA3Pe1G2qBdm/FgAMAFkYjZyvgCg==
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEjHBlAcoKLipNvBHujrscg7E06j6I
|
||||
QU9pPVy+rDGUoIp+kTRlrgK4ObU37HZCaBQ8B6tf2Fqee0orLVo6SFJzdQ==
|
||||
-----END PUBLIC KEY-----
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-artifact-0b53c4bfd5c6",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "artifact-digest",
|
||||
"verifiedAt": "2026-09-15T13:12:49Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "pushed git.cloud.siax.io/sax3l/0pt:sha-0b53c4bfd5c6 to git.cloud.siax.io/sax3l/0pt",
|
||||
"tool": "docker",
|
||||
"sourceSha": "0b53c4bfd5c6bd9a368930a5433cb3dd3f51c724",
|
||||
"digest": "sha256:f2f086b52e12a24c79ca1c80d588aeace6312f072185f845d59f4b53bcf5e6ae"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-sbom-0b53c4bfd5c6",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "sbom",
|
||||
"verifiedAt": "2026-09-15T13:12:49Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "siax/_release-artifacts/sbom-0b53c4bfd5c6.spdx.json",
|
||||
"tool": "syft",
|
||||
"sbomFormat": "spdx-json",
|
||||
"digest": "sha256:f2f086b52e12a24c79ca1c80d588aeace6312f072185f845d59f4b53bcf5e6ae"
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"id": "pe-signature-0b53c4bfd5c6",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "signature",
|
||||
"verifiedAt": "2026-09-15T13:12:49Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "cosign verify --key cosign.pub git.cloud.siax.io/sax3l/0pt@sha256:f2f086b52e12a24c79ca1c80d588aeace6312f072185f845d59f4b53bcf5e6ae (verified in this same run)",
|
||||
"tool": "cosign",
|
||||
"signatureTool": "cosign",
|
||||
"keyless": false,
|
||||
"digest": "sha256:f2f086b52e12a24c79ca1c80d588aeace6312f072185f845d59f4b53bcf5e6ae"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-artifact-2265dbb9a7cf",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "artifact-digest",
|
||||
"verifiedAt": "2026-09-15T02:37:09Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "pushed git.cloud.siax.io/sax3l/0pt:sha-2265dbb9a7cf to git.cloud.siax.io/sax3l/0pt",
|
||||
"tool": "docker",
|
||||
"sourceSha": "2265dbb9a7cfb97fecd7b15a0e18ce84bc937558",
|
||||
"digest": "sha256:372ac1a9b8ebfbfa54960e3447c667cc6606a13c7406db7806a05c0df63e7d13"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-sbom-2265dbb9a7cf",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "sbom",
|
||||
"verifiedAt": "2026-09-15T02:37:09Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "siax/_release-artifacts/sbom-2265dbb9a7cf.spdx.json",
|
||||
"tool": "syft",
|
||||
"sbomFormat": "spdx-json",
|
||||
"digest": "sha256:372ac1a9b8ebfbfa54960e3447c667cc6606a13c7406db7806a05c0df63e7d13"
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"id": "pe-signature-2265dbb9a7cf",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "signature",
|
||||
"verifiedAt": "2026-09-15T02:37:09Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "cosign verify --key cosign.pub git.cloud.siax.io/sax3l/0pt@sha256:372ac1a9b8ebfbfa54960e3447c667cc6606a13c7406db7806a05c0df63e7d13 (verified in this same run)",
|
||||
"tool": "cosign",
|
||||
"signatureTool": "cosign",
|
||||
"keyless": false,
|
||||
"digest": "sha256:372ac1a9b8ebfbfa54960e3447c667cc6606a13c7406db7806a05c0df63e7d13"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-artifact-570352eb80d2",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "artifact-digest",
|
||||
"verifiedAt": "2026-09-15T03:17:55Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "pushed git.cloud.siax.io/sax3l/0pt:sha-570352eb80d2 to git.cloud.siax.io/sax3l/0pt",
|
||||
"tool": "docker",
|
||||
"sourceSha": "570352eb80d2809508506409b5e988673bc85a60",
|
||||
"digest": "sha256:4c0f3ab6fd581bdaec7843cc6670c20b653cd6c931c614b07a24b22def481ce0"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-sbom-570352eb80d2",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "sbom",
|
||||
"verifiedAt": "2026-09-15T03:17:55Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "siax/_release-artifacts/sbom-570352eb80d2.spdx.json",
|
||||
"tool": "syft",
|
||||
"sbomFormat": "spdx-json",
|
||||
"digest": "sha256:4c0f3ab6fd581bdaec7843cc6670c20b653cd6c931c614b07a24b22def481ce0"
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"id": "pe-signature-570352eb80d2",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "signature",
|
||||
"verifiedAt": "2026-09-15T03:17:55Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "cosign verify --key cosign.pub git.cloud.siax.io/sax3l/0pt@sha256:4c0f3ab6fd581bdaec7843cc6670c20b653cd6c931c614b07a24b22def481ce0 (verified in this same run)",
|
||||
"tool": "cosign",
|
||||
"signatureTool": "cosign",
|
||||
"keyless": false,
|
||||
"digest": "sha256:4c0f3ab6fd581bdaec7843cc6670c20b653cd6c931c614b07a24b22def481ce0"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-artifact-6a125e10ccc3",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "artifact-digest",
|
||||
"verifiedAt": "2026-09-15T12:39:15Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "pushed git.cloud.siax.io/sax3l/0pt:sha-6a125e10ccc3 to git.cloud.siax.io/sax3l/0pt",
|
||||
"tool": "docker",
|
||||
"sourceSha": "6a125e10ccc3bc9d9d6610154f40469a169d4cf3",
|
||||
"digest": "sha256:a6f3ed9cf32fc94f292c564bf115aa70241a440245d68271ac018ec9378323ff"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-sbom-6a125e10ccc3",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "sbom",
|
||||
"verifiedAt": "2026-09-15T12:39:15Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "siax/_release-artifacts/sbom-6a125e10ccc3.spdx.json",
|
||||
"tool": "syft",
|
||||
"sbomFormat": "spdx-json",
|
||||
"digest": "sha256:a6f3ed9cf32fc94f292c564bf115aa70241a440245d68271ac018ec9378323ff"
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"id": "pe-signature-6a125e10ccc3",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "signature",
|
||||
"verifiedAt": "2026-09-15T12:39:15Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "cosign verify --key cosign.pub git.cloud.siax.io/sax3l/0pt@sha256:a6f3ed9cf32fc94f292c564bf115aa70241a440245d68271ac018ec9378323ff (verified in this same run)",
|
||||
"tool": "cosign",
|
||||
"signatureTool": "cosign",
|
||||
"keyless": false,
|
||||
"digest": "sha256:a6f3ed9cf32fc94f292c564bf115aa70241a440245d68271ac018ec9378323ff"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-artifact-7f3df904b741",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "artifact-digest",
|
||||
"verifiedAt": "2026-09-15T12:51:12Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "pushed git.cloud.siax.io/sax3l/0pt:sha-7f3df904b741 to git.cloud.siax.io/sax3l/0pt",
|
||||
"tool": "docker",
|
||||
"sourceSha": "7f3df904b741cc6e842320e3be7d05d8223c6fee",
|
||||
"digest": "sha256:993f12c0eb0d0ccde968865eca6d87654dee4bb08e80cc0f169a60e44209f536"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-sbom-7f3df904b741",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "sbom",
|
||||
"verifiedAt": "2026-09-15T12:51:12Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "siax/_release-artifacts/sbom-7f3df904b741.spdx.json",
|
||||
"tool": "syft",
|
||||
"sbomFormat": "spdx-json",
|
||||
"digest": "sha256:993f12c0eb0d0ccde968865eca6d87654dee4bb08e80cc0f169a60e44209f536"
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"id": "pe-signature-7f3df904b741",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "signature",
|
||||
"verifiedAt": "2026-09-15T12:51:12Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "cosign verify --key cosign.pub git.cloud.siax.io/sax3l/0pt@sha256:993f12c0eb0d0ccde968865eca6d87654dee4bb08e80cc0f169a60e44209f536 (verified in this same run)",
|
||||
"tool": "cosign",
|
||||
"signatureTool": "cosign",
|
||||
"keyless": false,
|
||||
"digest": "sha256:993f12c0eb0d0ccde968865eca6d87654dee4bb08e80cc0f169a60e44209f536"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-artifact-8be11b6485d3",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "artifact-digest",
|
||||
"verifiedAt": "2026-09-15T03:45:04Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "pushed git.cloud.siax.io/sax3l/0pt:sha-8be11b6485d3 to git.cloud.siax.io/sax3l/0pt",
|
||||
"tool": "docker",
|
||||
"sourceSha": "8be11b6485d3a3f88960af68e71d45d35735d1a8",
|
||||
"digest": "sha256:5b890676933a8dd19c96d0ba3f00d19d1051b75fd6259ed1d5414782532eb822"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-sbom-8be11b6485d3",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "sbom",
|
||||
"verifiedAt": "2026-09-15T03:45:04Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "siax/_release-artifacts/sbom-8be11b6485d3.spdx.json",
|
||||
"tool": "syft",
|
||||
"sbomFormat": "spdx-json",
|
||||
"digest": "sha256:5b890676933a8dd19c96d0ba3f00d19d1051b75fd6259ed1d5414782532eb822"
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"id": "pe-signature-8be11b6485d3",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "signature",
|
||||
"verifiedAt": "2026-09-15T03:45:04Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "cosign verify --key cosign.pub git.cloud.siax.io/sax3l/0pt@sha256:5b890676933a8dd19c96d0ba3f00d19d1051b75fd6259ed1d5414782532eb822 (verified in this same run)",
|
||||
"tool": "cosign",
|
||||
"signatureTool": "cosign",
|
||||
"keyless": false,
|
||||
"digest": "sha256:5b890676933a8dd19c96d0ba3f00d19d1051b75fd6259ed1d5414782532eb822"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-artifact-90ca9d6ec08b",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "artifact-digest",
|
||||
"verifiedAt": "2026-09-15T02:56:55Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "pushed git.cloud.siax.io/sax3l/0pt:sha-90ca9d6ec08b to git.cloud.siax.io/sax3l/0pt",
|
||||
"tool": "docker",
|
||||
"sourceSha": "90ca9d6ec08baf7aa372c5198083fac64278d3e0",
|
||||
"digest": "sha256:7ba57ea461bd0253c92428f36f6bec9602c5e9c3f2e537a834a9a5a5cf09ae71"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-sbom-90ca9d6ec08b",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "sbom",
|
||||
"verifiedAt": "2026-09-15T02:56:55Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "siax/_release-artifacts/sbom-90ca9d6ec08b.spdx.json",
|
||||
"tool": "syft",
|
||||
"sbomFormat": "spdx-json",
|
||||
"digest": "sha256:7ba57ea461bd0253c92428f36f6bec9602c5e9c3f2e537a834a9a5a5cf09ae71"
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"id": "pe-signature-90ca9d6ec08b",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "signature",
|
||||
"verifiedAt": "2026-09-15T02:56:55Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "cosign verify --key cosign.pub git.cloud.siax.io/sax3l/0pt@sha256:7ba57ea461bd0253c92428f36f6bec9602c5e9c3f2e537a834a9a5a5cf09ae71 (verified in this same run)",
|
||||
"tool": "cosign",
|
||||
"signatureTool": "cosign",
|
||||
"keyless": false,
|
||||
"digest": "sha256:7ba57ea461bd0253c92428f36f6bec9602c5e9c3f2e537a834a9a5a5cf09ae71"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-artifact-946baef8434d",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "artifact-digest",
|
||||
"verifiedAt": "2026-09-15T13:26:03Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "pushed git.cloud.siax.io/sax3l/0pt:sha-946baef8434d to git.cloud.siax.io/sax3l/0pt",
|
||||
"tool": "docker",
|
||||
"sourceSha": "946baef8434d860bf98b31aa4bc3042601436bb8",
|
||||
"digest": "sha256:1903f36bf4f6ea007849f8848a4b5ed1d1efe66026fc1f8ccb93461b814da9d1"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-sbom-946baef8434d",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "sbom",
|
||||
"verifiedAt": "2026-09-15T13:26:03Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "siax/_release-artifacts/sbom-946baef8434d.spdx.json",
|
||||
"tool": "syft",
|
||||
"sbomFormat": "spdx-json",
|
||||
"digest": "sha256:1903f36bf4f6ea007849f8848a4b5ed1d1efe66026fc1f8ccb93461b814da9d1"
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"id": "pe-signature-946baef8434d",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "signature",
|
||||
"verifiedAt": "2026-09-15T13:26:03Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "cosign verify --key cosign.pub git.cloud.siax.io/sax3l/0pt@sha256:1903f36bf4f6ea007849f8848a4b5ed1d1efe66026fc1f8ccb93461b814da9d1 (verified in this same run)",
|
||||
"tool": "cosign",
|
||||
"signatureTool": "cosign",
|
||||
"keyless": false,
|
||||
"digest": "sha256:1903f36bf4f6ea007849f8848a4b5ed1d1efe66026fc1f8ccb93461b814da9d1"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-artifact-a285c2f45f78",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "artifact-digest",
|
||||
"verifiedAt": "2026-09-15T03:22:20Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "pushed git.cloud.siax.io/sax3l/0pt:sha-a285c2f45f78 to git.cloud.siax.io/sax3l/0pt",
|
||||
"tool": "docker",
|
||||
"sourceSha": "a285c2f45f78af1291890176f97da643c28842c4",
|
||||
"digest": "sha256:27b02219edbff19a57c88e6617a42363dbf7bdfd39002278f537b5cc571db49b"
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"id": "pe-sbom-a285c2f45f78",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "sbom",
|
||||
"verifiedAt": "2026-09-15T03:22:20Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "siax/_release-artifacts/sbom-a285c2f45f78.spdx.json",
|
||||
"tool": "syft",
|
||||
"sbomFormat": "spdx-json",
|
||||
"digest": "sha256:27b02219edbff19a57c88e6617a42363dbf7bdfd39002278f537b5cc571db49b"
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"id": "pe-signature-a285c2f45f78",
|
||||
"repo": "0pt",
|
||||
"evidenceType": "signature",
|
||||
"verifiedAt": "2026-09-15T03:22:20Z",
|
||||
"verifiedBy": "gitea-ci",
|
||||
"result": "pass",
|
||||
"proofRef": "cosign verify --key cosign.pub git.cloud.siax.io/sax3l/0pt@sha256:27b02219edbff19a57c88e6617a42363dbf7bdfd39002278f537b5cc571db49b (verified in this same run)",
|
||||
"tool": "cosign",
|
||||
"signatureTool": "cosign",
|
||||
"keyless": false,
|
||||
"digest": "sha256:27b02219edbff19a57c88e6617a42363dbf7bdfd39002278f537b5cc571db49b"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"id": "sb-release-0b53c4bfd5c6",
|
||||
"repo": "0pt",
|
||||
"commitSha": "0b53c4bfd5c6bd9a368930a5433cb3dd3f51c724",
|
||||
"branch": "main",
|
||||
"buildId": "28418-1",
|
||||
"artifactId": "git.cloud.siax.io/sax3l/0pt:sha-0b53c4bfd5c6",
|
||||
"producedAt": "2026-09-15T13:12:49Z"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"id": "sb-release-2265dbb9a7cf",
|
||||
"repo": "0pt",
|
||||
"commitSha": "2265dbb9a7cfb97fecd7b15a0e18ce84bc937558",
|
||||
"branch": "main",
|
||||
"buildId": "26937-1",
|
||||
"artifactId": "git.cloud.siax.io/sax3l/0pt:sha-2265dbb9a7cf",
|
||||
"producedAt": "2026-09-15T02:37:09Z"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"id": "sb-release-570352eb80d2",
|
||||
"repo": "0pt",
|
||||
"commitSha": "570352eb80d2809508506409b5e988673bc85a60",
|
||||
"branch": "main",
|
||||
"buildId": "27177-1",
|
||||
"artifactId": "git.cloud.siax.io/sax3l/0pt:sha-570352eb80d2",
|
||||
"producedAt": "2026-09-15T03:17:55Z"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"id": "sb-release-6a125e10ccc3",
|
||||
"repo": "0pt",
|
||||
"commitSha": "6a125e10ccc3bc9d9d6610154f40469a169d4cf3",
|
||||
"branch": "main",
|
||||
"buildId": "28224-1",
|
||||
"artifactId": "git.cloud.siax.io/sax3l/0pt:sha-6a125e10ccc3",
|
||||
"producedAt": "2026-09-15T12:39:15Z"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"id": "sb-release-7f3df904b741",
|
||||
"repo": "0pt",
|
||||
"commitSha": "7f3df904b741cc6e842320e3be7d05d8223c6fee",
|
||||
"branch": "main",
|
||||
"buildId": "28293-1",
|
||||
"artifactId": "git.cloud.siax.io/sax3l/0pt:sha-7f3df904b741",
|
||||
"producedAt": "2026-09-15T12:51:12Z"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"id": "sb-release-8be11b6485d3",
|
||||
"repo": "0pt",
|
||||
"commitSha": "8be11b6485d3a3f88960af68e71d45d35735d1a8",
|
||||
"branch": "main",
|
||||
"buildId": "27317-1",
|
||||
"artifactId": "git.cloud.siax.io/sax3l/0pt:sha-8be11b6485d3",
|
||||
"producedAt": "2026-09-15T03:45:04Z"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"id": "sb-release-90ca9d6ec08b",
|
||||
"repo": "0pt",
|
||||
"commitSha": "90ca9d6ec08baf7aa372c5198083fac64278d3e0",
|
||||
"branch": "main",
|
||||
"buildId": "26992-1",
|
||||
"artifactId": "git.cloud.siax.io/sax3l/0pt:sha-90ca9d6ec08b",
|
||||
"producedAt": "2026-09-15T02:56:55Z"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"id": "sb-release-946baef8434d",
|
||||
"repo": "0pt",
|
||||
"commitSha": "946baef8434d860bf98b31aa4bc3042601436bb8",
|
||||
"branch": "main",
|
||||
"buildId": "28442-1",
|
||||
"artifactId": "git.cloud.siax.io/sax3l/0pt:sha-946baef8434d",
|
||||
"producedAt": "2026-09-15T13:26:03Z"
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"id": "sb-release-a285c2f45f78",
|
||||
"repo": "0pt",
|
||||
"commitSha": "a285c2f45f78af1291890176f97da643c28842c4",
|
||||
"branch": "main",
|
||||
"buildId": "27202-1",
|
||||
"artifactId": "git.cloud.siax.io/sax3l/0pt:sha-a285c2f45f78",
|
||||
"producedAt": "2026-09-15T03:22:20Z"
|
||||
}
|
||||
Reference in New Issue
Block a user