Verify SpendEnvelopes in your CI.
Drop a six-line job into any GitHub Action workflow. The build fails if an envelope is malformed, expired, replay-marked, or its signatures don't match. Use it as a pre-deploy gate, a PR check on envelope fixtures, or as an agent-flow regression guard.
.github/workflows/pqsafe.ymlname: PQSafe SpendEnvelope verify on: [push, pull_request] jobs: verify: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: PQSafe/verify-envelope-action@v1 with: envelope-glob: 'fixtures/**/*.envelope.json' issuer: 'did:web:pqsafe.xyz:issuer:v1' fail-on-tampered: true
That's the whole installation. Push, watch CI go green, fail it deliberately by editing a fixture to confirm.
What it checks
- โSignature validity. Re-verifies the ECDSA P-256 + ML-DSA-65 dual signature over the canonical mandate. Either fails → build fails.
- โCanonical bytes match. Recomputes the RFC 8785 JCS encoding and confirms the fingerprint is what's signed.
- โIssuer fingerprint. Confirms the envelope claims the issuer DID/keypair you expect. Catches forged envelopes from rogue issuers.
- โExpiration window. If the envelope has a
expires_atfield, fails the build if it's in the past. - โNonce uniqueness (opt-in). Cross-checks nonces against the canonical revoke/replay endpoint at
api.pqsafe.xyz/v1/revoke/{nonce}. - โOptional policy assertions. Pass
expected-amount,expected-currency, orexpected-recipientinputs to enforce additional invariants in CI.
Inputs
| Input | Required | Description |
|---|---|---|
| envelope-glob | yes | Glob pattern matching envelope JSON files |
| issuer | no | Expected issuer DID or pubkey fingerprint |
| fail-on-tampered | no | Default true. Fail build if any envelope is invalid. |
| expected-amount | no | Assert mandate.amount equals this value |
| expected-currency | no | Assert mandate.currency equals this value |
| expected-recipient | no | Assert mandate.recipient equals this DID |
| replay-check | no | Default false. Hit canonical replay endpoint. |
| verifier-api-url | no | Override for self-hosted verifier API |
Outputs
| Output | Type | Description |
|---|---|---|
| verified-count | number | Number of envelopes that verified successfully |
| failed-count | number | Number of envelopes that failed verification |
| report-json | string | Path to per-envelope detail report |
Use cases
Verify the production envelope fixtures haven't drifted from the signed issuer keys before merging to main.
Catch the case where someone updates an agent test fixture without re-signing it — the action fails the PR.
If your team accepts payment mandates from a vendor's agent, run this action on every PR that updates the integration fixtures.
Run against the official AP2-PQ test vector set in CI as a continuous claim that your implementation matches the canonical envelope shape.
Failure-mode example
Suppose someone edits amount on a signed fixture from 50.00 to 5000.00. The action output:
โ fixtures/payment-001.envelope.json ECDSA signature invalid for this envelope ML-DSA-65 signature invalid for this envelope # JCS canonical bytes changed โ fingerprint changed โ both sigs reject Error: 1 envelope(s) failed verification. Failing build.
Re-signing requires the issuer's private key. There is no way to flip a field and keep the original signature.
Install with one click into any repo.
Apache-2.0. Pin @v1 for stable, @main for latest.