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
$ 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.