What this repository is: the pinned-CI home for FlareClaw's canonicalization conformance. The canonical development home of the verifier is GitLab: flareclaw-verifier — files here are the same
conformance/drop, published on GitHub so the frozen vectors re-verify undergiskard09/action-ref-conformance@v1on every commit. Context: x402-foundation/x402#3000.
The exact canonicalization FlareClaw uses to digest attestation evidence, plus adapters so anyone can check it against two independent test suites. No trust required at any step: run it yourself.
Why this is public: badge evidence in
FCAttestationBadges
is referenced as x402ev/1; digest=sha256:<hex>; ref=<uri> — a SHA-256 over
the canonical form of an evidence artifact. If this function is wrong, those
digests are wrong. So it ships where it can be checked.
npm i -D tsx # only dependency; everything else is stdlib
npx tsx run-jcs.mts # RFC 8785 official vectors -> expect 6/6
python3 run-conformance.py # action-ref-v1-jcs-sha256 -> expect 8/8run-jcs.mts — RFC 8785 (JCS). Vectors are the reference set from the
RFC author's own repository (cyberphone/json-canonicalization): arrays,
french, structures, unicode, values, weird. Byte-for-byte comparison. This
is the one that matters for our badges — the digest is only meaningful if
the serialization is canonical by someone else's definition, not ours.
run-conformance.py — action-ref-v1-jcs-sha256. Frozen vectors from
giskard09/action-ref-conformance.
Four positives must reproduce the canonical digest byte-identically; four
negatives must either be rejected or diverge from the forgeable
claimed_action_ref. In this repository the same vectors also run under
the pinned Action itself (giskard09/action-ref-conformance@v1,
verify-impl + verify-vendored) on every commit — see
.github/workflows/conformance.yml and
the Actions tab. That green run is the conformance claim; this local
runner is the same check without the Actions runtime.
action-ref-cli.ts reads one preimage JSON object on stdin and writes the
hex SHA-256 of its canonical form to stdout — it fails closed on a
timestamp that is not RFC3339 UTC with millisecond precision, rather than
coercing a drifted form into a match.
read evidenceRef on-chain -> parse x402ev/1 -> fetch ref -> sha256(bytes) == digest
The artifact is served content-addressed (the path is the digest), and the server re-hashes before responding — so it cannot serve bytes that don't match their own name.