~/arcana/governance/envelopes.md
09
SIGNED ENVELOPES — 7-LAYER VERIFICATION
Ed25519 signatures over canonical serialization
Policies, capabilities, and node identities travel as Ed25519-signed envelopes with domain-separated signatures over deterministic canonical serialization. An envelope descends through seven stages — every one must pass:
Any stage fails → rejected. There is no partial trust and no skip path.
1[ PARSE ]strict decode
2[ SCHEMA ]shape & types
3[ SIGNATURE ]Ed25519 verify
4[ TRUST ]issuer anchored?
5[ AUDIENCE ]meant for us?
6[ FRESHNESS ]not expired/stale
7[ REVOCATION ]not withdrawn
# 09 · Signed Envelopes — 7-Layer Verification > Ed25519 signatures over canonical serialization. ## Overview Anything that must be trusted across processes, machines, or time — policies, capability grants, node identities, delegations — travels as a **signed envelope**: an Ed25519 domain-separated signature over deterministic canonical serialization of the payload. Canonical serialization matters because signatures are computed over bytes. If two implementations can serialize the same logical object differently, signatures break or, worse, two different objects collide. Arcana's canonical form is stricter than RFC 8785/JCS: no floats, strict UTC RFC 3339 millisecond timestamps, unpadded base64url. ## The seven verification stages An envelope is trusted only after all seven pass, in order: | # | Stage | Question answered | Example failure | |---|---|---|---| | 1 | PARSE | Is this decodable at all? | Truncated bytes | | 2 | SCHEMA | Right shape and types? | Missing audience field | | 3 | SIGNATURE | Does Ed25519 verify over the canonical bytes? | Tampered payload | | 4 | TRUST | Is the issuer anchored in our trust store? | Self-signed stranger | | 5 | AUDIENCE | Was this issued for us? | Node B reading node A's grant | | 6 | FRESHNESS | Issued/expired windows sane? | Replay from last year | | 7 | REVOCATION | Has the issuer withdrawn it? | Fired admin's policy | **Any stage fails → rejected.** No partial trust, no skip path, no "well the signature was fine". ## Conformance Verification is cross-checked by two independent implementations: - TypeScript production verifier: 100/100 golden crypto vectors. - Rust verifier: 46 golden vectors (41 negative, 5 positive) generated by the TypeScript side and verified without shared code. - Cross-language request-hash vector: identical hash in TS and Rust for the same fixture. ## Related - Previous: [Scoped Approvals & Routing](/governance/approvals.md) - Next: [RunProof — Portable Evidence](/governance/runproof.md)