From 7eedbba418f19efbca5de7c6e23207271aba4348 Mon Sep 17 00:00:00 2001 From: kanywst Date: Thu, 7 May 2026 23:27:44 +0900 Subject: [PATCH 1/3] docs: fix README badges to point at 0-draft/zopa The CI and OpenSSF Scorecard badges were still pointing at github.com/kanywst/zopa, left over from before the repo was moved to the 0-draft org. The badges resolved to 404 and stayed gray on the rendered README. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a75ec99..2ffc150 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ Tiny, zero-allocation authorization engine for proxy-wasm and the edge. ~50 KB. No GC. No deps. [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE) -[![CI](https://github.com/kanywst/zopa/actions/workflows/ci.yml/badge.svg)](https://github.com/kanywst/zopa/actions/workflows/ci.yml) -[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/kanywst/zopa/badge)](https://securityscorecards.dev/viewer/?uri=github.com/kanywst/zopa) +[![CI](https://github.com/0-draft/zopa/actions/workflows/ci.yml/badge.svg)](https://github.com/0-draft/zopa/actions/workflows/ci.yml) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/0-draft/zopa/badge)](https://securityscorecards.dev/viewer/?uri=github.com/0-draft/zopa) [![Zig](https://img.shields.io/badge/zig-0.16.0-orange.svg)](https://ziglang.org) zopa runs as a `wasm32-freestanding` module. Hosts hand it a request From 61f3c6f7759460148e98b1e058ccaa80325f95ee Mon Sep 17 00:00:00 2001 From: kanywst Date: Thu, 7 May 2026 23:27:44 +0900 Subject: [PATCH 2/3] ci(release): add tag-triggered SLSA L3 + cosign release workflow Pushing a v* tag now produces a signed, attested wasm release: - build: zig build --release=small produces zopa-.wasm. We compute its SHA-256, write a checksum file, and emit the base64-encoded subject for the SLSA generator. - provenance: slsa-github-generator/generator_generic_slsa3 v2.1.0 attests the build in an isolated reusable workflow and uploads the .intoto.jsonl bundle to the release. - sign: sigstore cosign sign-blob runs keylessly via OIDC, emitting a single .sigstore.json bundle (cosign v4 default). - release: softprops/action-gh-release attaches the .wasm, .sha256, and .sigstore.json to the release with auto-generated notes from the merged PRs since the previous tag. All actions are sha-pinned except the SLSA reusable workflow, which must be tag-pinned per upstream's binary-fetch convention. No long- lived secrets are required; all credentials are minted via OIDC per run. CHANGELOG records the new pipeline under Unreleased. --- .github/workflows/release.yml | 129 ++++++++++++++++++++++++++++++++++ CHANGELOG.md | 6 ++ 2 files changed, 135 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..a9f7cb4 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,129 @@ +# release flow: +# 1. tag v* on main triggers this workflow +# 2. build job produces zopa.wasm (--release=small) + sha256 and exposes +# base64 subjects for the slsa-github-generator +# 3. provenance job generates SLSA v1.0 attestation via the reusable workflow +# (runs in an isolated builder, uploads the intoto.jsonl to the release) +# 4. sign job runs cosign sign-blob keylessly and attaches the sigstore bundle +# 5. release job attaches the wasm + sha256 to the GitHub Release +# +# secrets used: none. credentials are minted via OIDC per run. + +name: release + +on: + push: + tags: ["v*"] + workflow_dispatch: + +permissions: {} + +jobs: + build: + name: build wasm + checksum + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + outputs: + wasm-name: ${{ steps.pack.outputs.wasm-name }} + wasm-sha256: ${{ steps.pack.outputs.wasm-sha256 }} + subjects-base64: ${{ steps.pack.outputs.subjects-base64 }} + steps: + - name: harden runner + uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2 + with: + egress-policy: audit + + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1 + with: + version: 0.16.0 + + - name: build (release-small) + run: zig build --release=small + + - name: pack + id: pack + run: | + set -euo pipefail + src="zig-out/bin/zopa.wasm" + name="zopa-${GITHUB_REF_NAME}.wasm" + cp "$src" "$name" + sha=$(shasum -a 256 "$name" | awk '{print $1}') + printf '%s %s\n' "$sha" "$name" > "$name.sha256" + subjects=$(printf '%s %s\n' "$sha" "$name" | base64 -w0) + echo "wasm-name=$name" >>"$GITHUB_OUTPUT" + echo "wasm-sha256=$sha" >>"$GITHUB_OUTPUT" + echo "subjects-base64=$subjects" >>"$GITHUB_OUTPUT" + ls -l "$name" "$name.sha256" + wc -c "$name" + + - name: upload wasm + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: wasm + path: | + ${{ steps.pack.outputs.wasm-name }} + ${{ steps.pack.outputs.wasm-name }}.sha256 + if-no-files-found: error + retention-days: 7 + + provenance: + name: slsa v1.0 provenance + needs: [build] + permissions: + actions: read + contents: write + id-token: write + # exception: slsa-github-generator reusable workflows MUST be referenced by tag, + # not sha. internally this ref is parsed as `refs/tags/vX.Y.Z` to fetch the + # pre-built builder binary from the matching release. sha pinning makes the + # binary download fail with "Invalid ref ... Expected ref of the form + # refs/tags/vX.Y.Z". see https://github.com/slsa-framework/slsa-github-generator + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 + with: + base64-subjects: ${{ needs.build.outputs.subjects-base64 }} + provenance-name: ${{ needs.build.outputs.wasm-name }}.intoto.jsonl + upload-assets: true + + sign: + name: cosign sign-blob (keyless) + needs: [build, provenance] + runs-on: ubuntu-latest + permissions: + contents: write + id-token: write + steps: + - name: harden runner + uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2 + with: + egress-policy: audit + + - uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 + + - name: download wasm + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + name: wasm + + - name: sign + # cosign v4 emits a single sigstore bundle (.sigstore.json) by default; + # --output-signature / --output-certificate are deprecated and ignored. + run: | + cosign sign-blob --yes \ + --bundle "${{ needs.build.outputs.wasm-name }}.sigstore.json" \ + "${{ needs.build.outputs.wasm-name }}" + + - name: attach to release + uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3 + with: + files: | + ${{ needs.build.outputs.wasm-name }} + ${{ needs.build.outputs.wasm-name }}.sha256 + ${{ needs.build.outputs.wasm-name }}.sigstore.json + fail_on_unmatched_files: true + generate_release_notes: true diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d0abc2..8b4f777 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,3 +27,9 @@ once the first stable tag ships. proxy-wasm host buffer ownership conventions. - Integration tests in Node, wasmtime, and a real Envoy (`zig build test`, `test-wasmtime`, `test-envoy`). +- Release pipeline: `v*` tag pushes trigger `.github/workflows/release.yml`, + which builds `zopa-.wasm` (`--release=small`), generates a + SHA-256 checksum, attests SLSA v1.0 build provenance via + `slsa-github-generator`, signs the wasm with cosign keyless, and + attaches all four artifacts (`.wasm`, `.sha256`, `.intoto.jsonl`, + `.sigstore.json`) to the GitHub Release with auto-generated notes. From f78b161893d25e3c704f9fa52fecba126962d41d Mon Sep 17 00:00:00 2001 From: kanywst Date: Thu, 7 May 2026 23:30:33 +0900 Subject: [PATCH 3/3] docs(changelog): rephrase release pipeline entry, add Fixed section Address gemini-code-assist review: the Added entry was implementation- detail-heavy ('triggers .github/workflows/release.yml ... slsa-github- generator ... cosign keyless ...') rather than describing a user-facing outcome. Rewrite as 'automated releases on v* tags with SLSA v1.0 provenance and cosign signatures' plus the artifact list. Also add a Fixed section recording the README badge URL repair, which the previous CHANGELOG didn't capture even though the same PR ships the fix. Keep a Changelog calls for distinct Added / Fixed buckets. See https://github.com/0-draft/zopa/pull/3#discussion_r... --- CHANGELOG.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b4f777..7521fd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,9 +27,11 @@ once the first stable tag ships. proxy-wasm host buffer ownership conventions. - Integration tests in Node, wasmtime, and a real Envoy (`zig build test`, `test-wasmtime`, `test-envoy`). -- Release pipeline: `v*` tag pushes trigger `.github/workflows/release.yml`, - which builds `zopa-.wasm` (`--release=small`), generates a - SHA-256 checksum, attests SLSA v1.0 build provenance via - `slsa-github-generator`, signs the wasm with cosign keyless, and - attaches all four artifacts (`.wasm`, `.sha256`, `.intoto.jsonl`, - `.sigstore.json`) to the GitHub Release with auto-generated notes. +- Automated releases on `v*` tags with SLSA v1.0 build provenance and + cosign keyless signatures. Each release attaches `zopa-.wasm`, + `.sha256`, `.intoto.jsonl`, and `.sigstore.json`. + +### Fixed + +- README badges (CI, OpenSSF Scorecard) now resolve. They were left + pointing at `kanywst/zopa` after the repo moved to `0-draft/zopa`.