Interoperability report — BAP conformance cross-validation

Copy Markdown View Source

Status: current for corpus revision 1, certified index digest TLUHKrQP_UsRFlnm1KsgIJICOAUF8fhCS5bSLlM8uRs (base64url SHA-256 of index.json; hex 4cb5072ab40ffd4b111659e6d4ab20209202380505f1f8424b96d22e533cb91b). Every figure in this report is machine-derived: the certified digests and corpus revisions come from the corpus identity gates that run in mix quality; the case counts come from the certified indexes; the per-implementation verdicts come from each implementation's own runner executed against the identical corpus. A stale figure here fails the docs-currency tests.

Last regenerated November 9, 2026. Every result below was re-executed that day at these identities:

ImplementationIdentityToolchain
Elixir referenceprotocol commit 205d1b598f6fc01de4e412798ed1e81578ccc69e (pre-release source of 1.0.0)Elixir 1.20.2, Erlang/OTP 29
TypeScript verifierbounded_authority_protocol_typescript commit 88e86762e908e483ca054e14e6abbd18f3e65e8f (package version 1.0.0 plus the unreleased erratum 6)Node 22.23.1, pnpm 10.20.0
Python SDKsdks/python 0.1.0 at the protocol commit aboveCPython 3.13.13, cryptography 50.0.2
Rust SDKsdks/rust 0.1.0 at the protocol commit aboveRust 1.81.0, the crate's declared minimum
Go SDKsdks/go at the protocol commit aboveGo 1.25.14, the module's declared floor
Independent Node runnersconformance/*.mjs at the protocol commit aboveNode 22.23.1

Framing: test vectors + independent cross-validation

This is NOT an implementer's-list document. The evidence norm used here is the test-vectors-plus-independent-cross-validation model: the contract-major 1 conformance corpus is a set of 283 published test vectors across 28 verification surfaces, and interoperability is demonstrated by independent implementations agreeing on every vector's verdict — including the two-boundary public-key census — not by listing organizations. An implementation appears here only with its independently re-executed result against the certified corpus snapshot or in-place binding named above.

Summary

Agreed cases out of the certified total, per implementation and corpus:

CorpusCasesElixirTypeScriptPythonRustGo
Contract-major 1283283/283283/283283/283283/283283/283
Contract-major 2268268/268268/268268/268268/268268/268
Contract-major 3292292/292292/292292/292292/292292/292
bap-strict-ed25519/12,4102410/24102410/24102410/2410pass2410/2410
bap-producer-canonicality/17575/7575/7575/75pass75/75
bap-selector-float-zero/1161161/161161/161161/161pass161/161
Local-loopback HTTP36 URI + 8 proof36/36, 8/836/36, 8/8passpasspass
Role attestation4040/4040/40passpasspass
Content assertion131 + 9 + 14pass131 + 9 + 14passpasspass

"pass" means the implementation's certified-corpus test passed: it asserts the pinned index and the exact case counts and fails on any disagreement, but prints no agreement count. No run disagreed on any case.

The implementations

Reference implementation

  • Elixir (bounded_authority_protocol) — the reference verifier. Its deterministic CLI executes the full corpus: 283/283 agreed, 0 disagreed, census two-way equal (11 keys), asserting the certified index digest at startup.

Cross-language verifier SDKs (independent reimplementations)

Each SDK's behavior is defined by the specifications and the certified conformance corpora, not by the Elixir code; the Python, Rust, and Go sources carry comments that cross-reference the Elixir reference implementation by file for traceability. Each carries its own per-language permissiveness mutation gate proving its closures red-capable.

SDKLanguage surfaceCorpus bindingContract-major 1 result
@bounded-authority-protocol/verifierTypeScript, Node >= 22, node:crypto onlygraduated repository (baselabs/bounded_authority_protocol_typescript), vendored snapshot, startup digest assertion283/283 agreed + census (11 keys)
bounded-authority-verifierPython >= 3.10, cryptographyin-place monorepo corpus, startup digest assertion283/283 agreed + census (11 keys)
bounded-authority-protocolRust, MSRV 1.81, ed25519-dalek+p256+sha2vendored self-contained snapshot, startup digest assertion283/283 agreed + census (11 keys)
bounded_authority_protocol_goGo 1.25, stdlib onlyvendored self-contained snapshot, startup digest assertion283/283 agreed + census (11 keys)

The TypeScript verifier is published to npm; the Python, Rust, and Go SDKs are not yet published to any registry.

Local-loopback HTTP application-profile implementations

The byte-distinct bap-application-proof/local-loopback-http/1 profile is certified by its own revision-1 corpus at priv/conformance/application-profiles/local-loopback-http/v1. Its exact index SHA-256 is 10fc4cf05affcddc9e6340ff392c247e25ab038cd938f2557829a7ce63b1a5e4; the index binds exactly profile.json and proof-cases.json.

ImplementationResult
Elixir reference (profile test suite)36/36 URI cases and 8/8 proof cases against the pinned index
Elixir transport drill (mix local_loopback_http.verify)real IPv4 and IPv6 listeners: valid and misleading-authority-header requests verified, wrong nonce rejected; the verifier-bypass, Host-header and forwarded-header mutations each proven red
TypeScript44/44 cases agree (36 URI, 8 proof), producer and assembly byte symmetry for the IPv4 and IPv6 proofs
Pythoncertified-corpus tests pass
Rustcertified-corpus tests pass
Gocertified-corpus test passes

Every implementation pins the same index and per-file hashes, including signed IPv4 and IPv6 artifacts, exact producer and assembly bytes, trust and invocation binding, the mandatory nonce, meaningful-byte tamper, and mutual standard/local profile rejection.

Contract-majors 2 and 3

Contract-majors 2 and 3 are certified by their own revision-1 corpora, each bound by its index SHA-256: contract-major 2 (priv/conformance/v2/corpus, 268 cases, index 6de6289b7f47b0e0a78ea4610e7844a0f1d5247d8eace02ec9cf9841308f13d0) and contract-major 3 (priv/conformance/v3/corpus, 292 cases, index a5c8075e7534345c3bb6611d0b40292904bcfa3af0702e07ae014fa66926433c).

ImplementationContract-major 2Contract-major 3
Elixir reference CLI268/268 agreed, 0 disagreed292/292 agreed, 0 disagreed
TypeScript268/268 agreed, census two-way (17 keys)292/292 agreed, census two-way (11 keys)
Python268/268 agreed, census two-way (17 keys)292/292 agreed, census two-way (11 keys)
Rust268/268 agreed, census 17/17292/292 agreed, census 11/11
Go268/268 agreed, every discovered key among the 17 declared292/292 agreed, every discovered key among the 11 declared

The census for these majors compares the curated key inputs with the index fingerprints in both directions and requires every discovered key to be declared; the Go runner checks the discovered subset against the declared set. Each runner asserts its corpus index digest before executing any case.

Role-attestation sibling profile

The byte-distinct bap-role-attestation/1 profile (specification) is certified by its revision-1 corpus at priv/conformance/attestation-profiles/role-attestation/v1, index SHA-256 be5275c69539a0f31734242ff00a484c2f855f39181c55689d8b0f671195d62a, binding exactly profile.json and attestation-cases.json.

ImplementationResult
Elixir reference (mix role_attestation.verify)40/40 decode and 40/40 verify agreed, cross-profile rejection against contract-majors 1, 2, and 3
TypeScript40/40 decode and 40/40 verify agreed, producer and assembly bytes equal the certified compact, cross-profile rejection in both directions
Pythoncertified-corpus test passes; asserts 40 cases against the pinned index
Rustcertified-corpus test passes; asserts 40 cases against the pinned index
Gocertified-corpus test passes; asserts 40 cases against the pinned index

Content-assertion sibling profile

The byte-distinct bap-content-assertion/1 profile (specification) is certified by its revision-1 corpus at priv/conformance/attestation-profiles/content-assertion/v1, index SHA-256 14b7436ccf7cc91fece52a1578c3760df6720a93494d147ee5ab523e2ce21876, binding eight files: 131 assertion cases, 9 content-digest cases, and 14 successor cases.

ImplementationResult
Elixir reference (mix content_assertion.verify)corpus consumer passes on the pinned index, 0 failures
TypeScript131 assertions, 9 digests, 14 successors agreed; 38 producer and assembly byte checks
Pythoncertified-corpus tests pass; assert 131, 9, and 14 cases and the 38 producer vectors
Rustcertified-corpus and successor tests pass; case counts equal the pinned index
Gocertified-corpus and successor tests pass; asserts 131, 9, and 14 cases

Strict-Ed25519 corpus

The additive bap-strict-ed25519/1 corpus (erratum 2) is certified by its revision-1 index at priv/conformance/strict-ed25519, SHA-256 732117dfe1881b553998126a9524a95bfb1171257e388d5430a0a099f2287cb9: 2,410 cases in 14 families, with expected verdicts from an independent arithmetic generator and the 12 published "Taming the many EdDSAs" vectors. It changes no figure above.

ImplementationResult
Elixir reference (bounded_authority_conformance --corpus priv/conformance/strict-ed25519)agreed=2410 disagreed=0
TypeScript (conformance:strict-ed25519)every case agrees across 2,410 cases in 14 families
Python (tests/conformance/run_strict.py, reads the corpus in place)2410/2410 cases agree
Go (go test ./conformance/, vendored conformance/corpus-strict)agreed=2410/2410
Rust (cargo test --locked, vendored conformance/corpus-strict)pass
Independent Node runner (node conformance/corpus_independent.mjs --strict priv/conformance/strict-ed25519)agreed=2017 disagreed=0; it implements contract-major 1, so the 393 contract-major 2 and sibling-profile cases are reported as not covered

Producer-canonicality corpus

The additive bap-producer-canonicality/1 corpus (erratum 3) is certified by its revision-1 index at priv/conformance/producer-canonicality, SHA-256 99ee6fbbf32758b03d4630647f721d8d4e349f0628d860493d667fe6e762c601: 75 cases in 4 families (60 refused, 15 accepted at the rule's bound), generated keylessly from certified signatures. It changes no figure above.

ImplementationResult
Elixir reference (bounded_authority_conformance --corpus priv/conformance/producer-canonicality)agreed=75 disagreed=0
TypeScript (conformance:producer-canonicality)75/75 agreed (60 refused, 15 accepted with bytes unchanged)
Python (tests/conformance/run_producer_canonicality.py)75/75 agreed (60 refused, 15 accepted)
Go (go test ./conformance/)75/75 agreed (60 refused, 15 accepted with bytes unchanged)
Rust (cargo test --locked, conformance_producer_canonicality)pass

Selector float-zero corpus

The additive bap-selector-float-zero/1 corpus (erratum 6) is certified by its revision-1 index at priv/conformance/selector-float-zero, SHA-256 97fd7a99cdbf3acc0a78f5ba1c6556e23a63e0ad66f533e31fd69f82dc5f3003: 161 cases (98 rejected, 63 accepted) covering grant decode, envelope verification, and grant signing input on every contract-major. It changes no figure above.

ImplementationResult
Elixir reference (bounded_authority_conformance --corpus priv/conformance/selector-float-zero)agreed=161 disagreed=0
TypeScript (conformance:selector-float-zero)161/161 agreed (98 rejected, 63 accepted with certified outputs)
Python (tests/conformance/run_selector_float_zero.py)161/161 agreed (98 rejected, 63 accepted)
Go (go test ./conformance/)agreed=161/161 disagreed=0 (98 rejected, 63 accepted)
Rust (cargo test --locked, conformance_selector_float_zero)pass
Independent Node runner (node conformance/corpus_independent.mjs --selector-float-zero priv/conformance/selector-float-zero)agreed=43 disagreed=0; the 118 cases outside its contract-major 1 surfaces are reported as not covered

Independent Node second-implementation runners

Three runners written from the corpus, using node:* modules only (the corpus is the normative oracle for their verdicts):

RunnerScopeResult
conformance/corpus_independent.mjsfull 283-case corpus + tamper verbatim auditagreed=283 disagreed=0; census two-way equal (11 keys)
conformance/grant_proof_independent.mjsgrant/proof vectorsok: 3 vectors, 7 tamper cases, 18 URI cases
conformance/chain_archive_independent.mjschain/archive tamper + semantic vectorsok: 3 archives, 2 chain cases, 49 tamper cases, 7 semantic cases

Methodology

  1. The contract-major 1 corpus is the normative test-vector set: 283 cases, 28 surfaces, 16 conformance classes (valid/boundary/exact/maximum-plus-one plus twelve rejection classes), with a tamper-verbatim audit re-deriving every tamper case from its base.
  2. An implementation binds to a corpus either in place (startup digest assertion against the certified value) or through a vendored byte-identical snapshot (sync-gated).
  3. A run reports per-case agreement plus the two-boundary key census (discovered == verify-imported == index fingerprint set); any disagreement, crash, or census asymmetry fails the run.
  4. Every implementation additionally ships a permissiveness mutation battery: the guard families that keep it from being MORE permissive than the reference are each proven red-capable (construct the defect, watch the test go green, fix).
  5. Each application-profile and attestation-profile corpus is separate from the standard corpora. Each implementation verifies the exact declared file set and counts, then executes every case through the profile's separately named surfaces; no implementation infers or retries a profile.

Reproducing

Any implementation can reproduce this report: obtain the corpus (it ships in the package and the repository), verify the certified digest above, run all 283 cases, and check the census. The repository's mix quality runs the reference CLI on every contract-major and additive corpus, the three independent Node runners, the corpus-identity gates, and the real IPv4/IPv6 local-profile transport drill on every change. The Elixir suite and the three in-repository SDKs execute the sibling-profile corpora through their native APIs; the TypeScript runs live in its own repository.

Current limitations (stated, not hidden)

  • Three of the four SDKs — Python, Rust, and Go — are not published to registries; each moves to its own repository on first publication. Their cross-validation above is repository-executed, not registry-distributed. The TypeScript verifier is published from its own repository.
  • The TypeScript row was run at that repository's main, which carries the erratum 6 repair ahead of its next release; the published npm 1.0.0 predates erratum 6 and returns the pre-repair verdicts recorded in the errata registry.
  • Rows marked "pass" report the implementation's certified-corpus test (which asserts the pinned index and the exact case counts and fails on any disagreement), not a printed agreement count.
  • The independent Node runner implements contract-major 1 only, so it reports the strict-Ed25519 and selector float-zero cases of other majors and sibling profiles as not covered; the reference and the four SDKs run all of them.
  • The local-profile real-socket drill is implemented in the Elixir release gate. The other SDK results certify bytes and verdicts against the shared corpus, not live transport composition.