Widen the Sig footer from sig96 (96 B) to sig3408 (3408 B) so a full FIPS 204 ML-DSA-65 signature (3309 B) fits inline. Capability struct grows from 260 B to 3572 B; Revocation from 136 B to 3448 B. The field offset of Sig itself (164) is unchanged — only the field width. 3408 is the smallest 16-byte-aligned size that fits ML-DSA-65 with 99 B headroom. Schemes shorter than 3408 (secp256k1 65 B, Ed25519 64 B) are zero-padded on the right; the algorithm tag at Sig[3407] tells the verifier which primitive to dispatch on. Wire-incompatible with v1.0. Per the project's "no backwards compatibility, only forwards perfection" rule, every encoder/decoder updates in lockstep at the v1.1 tag — no compat layer, no union, no version negotiation. Cross-references: - capabilities_kinds.md gains the "Wire schemes" tag table. - SPEC.md §6 documents the v1.0 → v1.1 wire transition.
6.7 KiB
ZAP Capability Enums
The .zap DSL has no native enum primitive — its single-pass codegen is
deliberately minimal. Enum constants are normative here; codegen tools emit
them as named integer constants in the target language alongside the struct
accessors. This file is part of the wire contract. Changes require a new
struct family + bump.
Wire schemes (Capability.Sig algorithm tag, u8)
The final byte of the 3408-byte Sig footer is the algorithm tag. The
verifier dispatches on this byte to pick the right primitive; the tag byte
is inside the signed payload, so tag-substitution attacks are detected by
verifier mismatch. Encoded signature occupies bytes [0..L) where L is
the per-algorithm signature length; the bytes [L..3407) are zero pad and
byte 3407 is the tag.
| Constant | Value | Algorithm | Sig length |
|---|---|---|---|
SchemeReserved |
0x00 | (do not use; verifiers MUST refuse) | n/a |
SchemeSecp256k1 |
0x01 | secp256k1 ECDSA (32B R || 32B S || 1B v) | 65 |
SchemeEd25519 |
0x02 | Ed25519 (RFC 8032) | 64 |
SchemeMLDSA65 |
0x03 | ML-DSA-65 (FIPS 204 Level 3) | 3309 |
SchemeHybrid |
0x04 | Ed25519 || ML-DSA-65 concatenated | 64+3309 |
CapKind (Capability.Kind, u32)
Identifies the authority profile — which Target type, which Permission
semantics, which Caveat kinds make sense. Reserved range 0x0000_0000
through 0x0000_00FF for stack-level kinds; 0x0001_0000+ reserved for
application-defined kinds (registered in this file when stable).
| Constant | Value | Replaces |
|---|---|---|
CapKindReserved |
0x00 | (do not use) |
CapKindIAMSession |
0x01 | bearer JWT session tokens |
CapKindIAMAPIKey |
0x02 | client-credentials API keys |
CapKindKMSAccess |
0x10 | KMS access tokens for read/list |
CapKindKMSSign |
0x11 | KMS signing authority |
CapKindMPCSign |
0x20 | MPC threshold-signing intent |
CapKindATSOrder |
0x30 | ATS order placement authority |
CapKindBridgeXfer |
0x40 | cross-chain transfer authority |
CapKindStake |
0x50 | validator stake-backed authority |
CapKindDelegate |
0xFF | meta: ability to attenuate-and-reissue |
CapKindDelegate is special: a cap whose Kind is CapKindDelegate permits
its Holder to mint child caps of any Kind whose Permissions are a subset of
the delegate's Permissions and whose Target matches. This is how an org
admin grants a service the right to issue session caps to its users.
CaveatKind (Caveat.Kind, u32)
Identifies what the Caveat.Value bytes mean. All values are encoded
little-endian where applicable.
| Constant | Value | Value encoding |
|---|---|---|
CaveatKindExpiresAt |
0x00 | u64 unix seconds |
CaveatKindMaxAmount |
0x01 | u64 amount in smallest denomination of asset |
CaveatKindDestChain |
0x02 | id32 chain identifier |
CaveatKindRateLimit |
0x03 | u32 ops-per-minute LE || u32 burst LE |
CaveatKindIPCIDR |
0x04 | 1 byte AF (4 or 6) || 1 byte prefix-len || addr bytes |
CaveatKindAssetID |
0x05 | id32 allowed asset (repeat caveat for multi) |
CaveatKindOpAllow |
0x06 | u64 bitmask LE, intersected with parent |
CaveatKindMaxDepth |
0x07 | u8 remaining hops the cap chain may extend |
CaveatKindAudience |
0x08 | id32 hash of target service principal pubkey |
CaveatKindNonceHash |
0x09 | id32 of single-use binding (see SPEC.md) |
The verifier MUST refuse any unknown CaveatKind. Unknown caveats are
fail-closed by definition: an issuer that doesn't understand a caveat
cannot enforce it, so it cannot honor a cap that carries it.
Permission bits (Capability.Permissions, u64)
Permission bits are per-CapKind. Each CapKind owns the bottom 32 bits of this field; the top 32 are reserved for cross-cutting bits (audit, delegation lifecycle). The same bit value MAY mean different things in different CapKinds — verifiers MUST dispatch on CapKind first.
Cross-cutting bits (top 32, all CapKinds)
| Bit | Constant | Meaning |
|---|---|---|
| 1 << 32 | PermAttenuate |
may mint child caps with subset perms |
| 1 << 33 | PermAudit |
may read audit trail for Target |
| 1 << 63 | PermRoot |
root-of-trust marker (set on root caps only) |
CapKindIAMSession (0x01) low bits
| Bit | Constant | Meaning |
|---|---|---|
| 1 << 0 | PermSessionRead |
read operations on user resources |
| 1 << 1 | PermSessionWrite |
write operations |
| 1 << 2 | PermSessionDelete |
delete operations |
| 1 << 3 | PermSessionAssumeOrg |
switch active organization |
CapKindKMSSign (0x11) low bits
| Bit | Constant | Meaning |
|---|---|---|
| 1 << 0 | PermSignTx |
sign a transaction |
| 1 << 1 | PermSignBlob |
sign an arbitrary blob |
| 1 << 2 | PermSignAttest |
sign an attestation |
CapKindATSOrder (0x30) low bits
| Bit | Constant | Meaning |
|---|---|---|
| 1 << 0 | PermOrderPlace |
submit new orders |
| 1 << 1 | PermOrderCancel |
cancel orders |
| 1 << 2 | PermOrderModify |
modify resting orders |
| 1 << 3 | PermOrderShort |
enter short positions |
| 1 << 4 | PermOrderMargin |
use margin |
CapKindBridgeXfer (0x40) low bits
| Bit | Constant | Meaning |
|---|---|---|
| 1 << 0 | PermXferOut |
initiate outbound transfer |
| 1 << 1 | PermXferIn |
accept inbound transfer |
Remaining CapKinds reserve their permission bit layout for definition at implementation time; record the assignment here when stabilized.