Guide
CI and verification gates
waxseal is built to run in a pipeline: no network, a documented exit code, and a JSON object when you want one. Verification is the gate.
Add it to a workflow
Install the binary, then verify the archive against its seal with a pinned public key. The command reports and fails the job on its own, so no extra failure step is needed.
name: Verify WACZ seal
on: [push, pull_request]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.x
- name: Install waxseal
run: curl -fsSL https://raw.githubusercontent.com/srivtx/waxseal/main/install.sh | sh
- name: Verify the seal offline against a pinned key
run: waxseal verify capture.wacz -s capture.seal.json --public-key "$WAXSEAL_PUBLIC_KEY"
env:
WAXSEAL_PUBLIC_KEY: ${{ secrets.WAXSEAL_PUBLIC_KEY }}
Add --json to either step to log a machine-readable result, and pass --member-only when the pipeline legitimately re-zips the archive instead of preserving its exact bytes.
The exit code is the gate
verify exits 0 on success and 1 on a failed or mismatched verification, so a shell step that runs the command fails the job whenever the archive does not match the seal. A usage error exits 2 and an I/O failure exits 3. The full scheme is in Usage.
Pin a public key or a root
A seal carries its own public key, so on its own it is only self-consistent: verify prints trusted: no and checks the signature against the embedded key. Pass --public-key <pem|base64> or --root <hex> to pin what you trust; trusted: yes is reported only when the pin actually matches, and a mismatch fails with exit 1. The SHA-256 fingerprint of the SPKI key is always printed so you can pin it out of band.
Root-only pinning attests content, not provenance
Pinning --root proves the archive hashes to that root, but it does not prove who signed it: an attacker can re-sign the same archive with their own key and still satisfy --root. Pin --public-key when you need a provenance verdict.
$ waxseal verify capture.wacz -s capture.seal.json --public-key archive-key.pub.pemOKroot: 7ce7902d6dc6619e28496d7c717bacfbfb36bc7982b6d424d8d1f11c9218fcf7signature: validfingerprint: sha256:8b3e7cbe526fdb46b70f4f3a8b2a3992475febd3f02f94a27a3b9395b2d3825ctrusted: no — self-signed seal; pin it with --public-key or --root
Reproducible seals in CI
Pass --created-at <iso> when sealing and the same archive, key, and timestamp produce a byte-identical seal — including the deterministic Ed25519 signature. A pipeline can rebuild the seal and diff it against the committed one. Without --created-at, createdAt defaults to the current time and each run differs.