CAP never authorizes.
The closed algorithm registry — one row per accepted JWS alg name.
This table IS the algorithm registry spec/evolution.md describes as
data-driven: a new algorithm lands by the same registry-and-revision act
(a row here plus the key grammar its key_algorithm column requires),
never by a parallel artifact family, media type, or header shape. Each
row carries the accepted alg name, the minimum protocol_revision the
name is legal at, the key algorithm it verifies with, and that key
algorithm's exact public-key and signature byte lengths — the single
source of truth the framing layer, key grammar, and producer seam all
consult.
For revisions 1–2 both classical rows verify with Ed25519 keys: RFC 9864's
fully-specified Ed25519 names exactly the RFC 8032
EdDSA-with-Ed25519-key operation CAP already performs. Revision 3 admits
ML-DSA (FIPS 204) under its RFC 9964 JOSE names — pure ML-DSA with the
context fixed to the empty string — exercising the registry's second key
grammar and second cryptographic primitive.
The binding rule (per-artifact, not per-view)
Decoding accepts alg: "EdDSA" at any accepted protocol_revision;
alg: "Ed25519" requires protocol_revision >= 2; each alg: "ML-DSA-*"
name requires protocol_revision >= 3; unknown revisions fail closed. An
artifact carrying a name below its row's minimum is rejected — no honest
producer could have minted the pair. Views mix revisions freely; the rule
binds per artifact.
Emission
New minting is exactly the pairs ("Ed25519", protocol_revision 2) and
("ML-DSA-65", protocol_revision 3): the producer emits one of the
fully-specified names at its emission revision. Old artifacts verify
forever; nothing new mints a registry-deprecated identifier (RFC 9864
marks EdDSA Deprecated, not Prohibited — see
docs/adr/algorithm-name-agility.md and docs/adr/ml-dsa-admission.md).
Summary
Functions
Whether the name is a registry row (any revision).
The accepted protocol_revision set (unknown revisions fail closed).
Whether the (alg, protocol_revision) pair is legal on ONE artifact.
The emission name producers use when the caller selects none.
The closed mint set: each emission alg name paired with the exact protocol_revision its producer mints.
The registry row for one key algorithm, or nil.
The closed registry (one row per accepted alg name).
The registry row for one alg name, or nil for unknown names.
Types
@type row() :: %{ name: binary(), min_protocol_revision: pos_integer(), key_algorithm: binary(), public_key_bytes: pos_integer(), signature_bytes: pos_integer() }
Functions
Whether the name is a registry row (any revision).
@spec accepted_protocol_revisions() :: [pos_integer()]
The accepted protocol_revision set (unknown revisions fail closed).
Whether the (alg, protocol_revision) pair is legal on ONE artifact.
The binding rule: the name must be a registry row, the revision must be accepted, and the revision must meet the row's minimum. Revision range alone is separately enforced by the per-artifact schemas; this check binds the name to the revision.
@spec default_emission_name() :: binary()
The emission name producers use when the caller selects none.
@spec emissions() :: %{required(binary()) => pos_integer()}
The closed mint set: each emission alg name paired with the exact protocol_revision its producer mints.
The registry row for one key algorithm, or nil.
The descriptor key grammar is written in key-algorithm terms: this lookup
carries the exact public-key byte length each algorithm member value
requires.
@spec registry() :: [row()]
The closed registry (one row per accepted alg name).
The registry row for one alg name, or nil for unknown names.