Objective
Define and deterministically verify the exact bytes for one issuer-bounded, holder-proven remote invocation. The package returns cryptographic/contextual facts; operational authorization and live state remain outside it.
Standards posture
The protocol is on a standards track governed by the
standards track charter and
ADR 0006: the closed
wire profile is permanent and evolution happens above it through parallel contract-majors; the
current profile is the named suite BAP1-Ed25519-SHA256 with a specified post-quantum succession
and cross-suite evidence-attestation path; names for delegation (ba_dlg,
ba+cap-delegated), principal binding (ba_obo), and status checking are reserved in the
registries with their designs decided; governance, errata, and deprecation
policy are published. Nothing in that posture changes a byte, bound, or verdict of this charter's
verification chain.
Verification chain
- The caller supplies raw credentials and expected issuer/request context to the private runtime.
- The bounded
untrusted_key_locator/2returns only the protected grantkidas an explicitly untrusted lookup hint. - The runtime combines expected issuer context with that hint and resolves a candidate public-key snapshot.
- Outside a database transaction,
verify_grant/3verifies the raw compact grant against the exact candidate key, issuer, audience, explicit time, skew, and bounds. It returns redactedGrantFacts{authorization: :not_evaluated}. - The grant binds an Ed25519 holder key through
cnf.jkt. check_envelope/2accepts raw grant and proof bytes, re-verifies the raw grant rather than accepting the facts, verifies the RFC 9449 proof, and binds holder, grant, method, normalized HTTPS URI, invocation ID, operation, cast-argument digest, time, nonce, and selectors.- The library returns redacted
EnvelopeFacts{authorization: :not_evaluated}, or exactly{:error, :invalid}. - The stateful authority then begins one transaction, re-resolves and locks current key/revocation facts, fingerprint-matches the verified snapshot, requires current eligibility, checks replay, and records its decision/execution claim. The host independently authorizes the business effect.
Neither a decoded struct nor caller-provided GrantFacts/EnvelopeFacts is accepted as
credentials.
Grant
Protocol v1 uses standard compact JWS with exact RFC 7515 signing bytes, alg: EdDSA,
typ: ba+cap, an issuer-controlled kid, and a closed claim schema. Claims cover issuer,
audience, grant ID, coherent times, unique operations, ordered selectors, and holder binding.
Deterministic producers emit JCS protected/payload bytes and return a signing input; the package
never accepts private key material, a signer, or a signing callback.
Unknown versions, algorithms, headers, claims, selectors, duplicate keys, encodings, or
over-limit structures fail closed. The verifier does not use kid to discover trust.
A stateful authority may issue a separate, narrower current-v1 ba+cap to a new holder, but the
resulting compact is an ordinary issuer-signed grant and carries no parent proof. Parent comparison,
lineage, ancestor revocation, and fan-out policy remain online runtime responsibilities. The
current profile still rejects ba_dlg and ba+cap-delegated; portable holder-signed delegation
remains the successor-major design in ADR 0010, as
clarified by ADR 0020.
Holder proof
Each invocation supplies compact RFC 9449 DPoP:
- protected header: exact
typ: dpop+jwt,alg: EdDSA, and public Ed25519 JWK; - claims:
jti, server-derivedhtmand normalized hierarchical HTTPShtu,iat, grant hashath, optional challengednonce, invocation UUIDba_inv, operationba_op, and request digestba_req; ba_req = base64url(SHA-256("BAP1-REQUEST\0" || JCS([operation, typed(cast_arguments)]))), where the prefix is exact ASCII including its final zero byte and the closed recursivetyped/1projection preserves every tagged JSON variant, including integer versus integral-float identity.
Arguments may be any tagged JSON value. all matches any root; path selectors traverse objects
only and compare tagged JSON semantically, including unordered object members. No unprotected
security parameter, private JWK member, caller-selected expected context, or bearer fallback is
accepted.
Verification results
GrantFacts and EnvelopeFacts are immutable, closed, bounded, value-bearing, and redacted. Their
fixed inspection does not expose fields, and they implement no generic encoder. They contain only
the exact identifiers, times, fingerprints, and hashes required by the private runtime, plus
authorization: :not_evaluated; they exclude arguments, selector values, raw credentials,
signatures, JWK containers, and nonces.
Those facts are not operational decisions. The private runtime accepts raw credential bytes at its public boundary and produces facts internally; it never treats a caller-provided facts struct as an execution credential.
Evidence verification
BAP-04 chain/archive functions verify canonical row bytes, sequence, previous-link hashes, caller-supplied range boundaries, signed boundary anchors, authenticated historical-key rollover, complete archive framing/digest/EOF, and exact out-of-band object version. Historical keys and expected context are caller supplied; the package performs no lookup or current-key fallback.
Chain consistency does not certify deletion absence. A separately valid shortened or relinked archive fails only against the original expected boundaries. The package does not read storage, append rows, hold or select keys, create or submit anchors, submit witnesses, remove archives, certify retention, or decide operational authority.