Skip to content

Repository files navigation

Charter Agreement Protocol

Portable, non-authorizing charter-agreement format and verification protocol for bilateral commercial agreements. CAP verifies signed, byte-exact evidence of what two parties agreed, which revision governed a given instant, and which agreement state governed a signed action — without a central authority, and without ever making the decision for you.

CAP verifies. It never authorizes. Every facts record carries a closed twelve-item not_verified floor — authority, execution, billing, term satisfaction, legal validity, and more — that no API can shrink. Hosts read the evidence and decide.

What it does

Artifact Form Proves
Party Descriptor signed JWS (cap+party) A party's declared key history (Ed25519, and ML-DSA from protocol_revision 3) with predecessor-bound transitions and fork evidence
Charter Revision canonical JSON Agreed terms: parties, roles, legal-text digest, precedence, effective window, termination reasons, exact deployment bindings
Acceptance signed JWS (cap+acceptance) Bilateral signed assent to exact revision bytes
Termination Notice signed JWS (cap+termination) Signed closure of the charter at a pure UTC instant
Receipt signed JWS (cap+receipt) A signed action bound to exact revision coordinates, deployment digest, and grant evidence

Set-level verification composes the artifacts into structural facts: verify_chain/5 re-verifies everything from raw bytes; governing_revision/2 answers "which revision governed at this instant" with a digest, :contested, or :none — never a silent tie-break. Same-signer equivocation is retained as signed evidence with no winner. The only repair for a contested view is a countersigned supersession revision.

The foundation is byte-exact by construction: strict unpadded base64url, deterministic tagged JSON decoding, RFC 8785 canonicalization, and domain-separated SHA-256 digests. A certified 100-case corpus runs through a pure Elixir runner and a builtins-only Node TypeScript verifier that must produce byte-identical canonical reports — two independent implementations, zero shared code.

When to use it — and when not

Use CAP when two independent parties need portable, re-verifiable agreement evidence exchanged as bytes: agent commerce charters, bilateral supplier terms, key-history continuity proofs, action receipts for audit.

Do not use CAP for authorization decisions, live revocation checks, term evaluation (CAP leaves term_satisfaction in its omission floor), legal adjudication, or single-party self-attestation — every one of those is explicitly outside what verification proves. See the security model for the full proves/never-proves table.

Quick start

Elixir ~> 1.19 (tested lines 1.19.x and 1.20.x) on Erlang/OTP 28 or 29 — the range and the supported-OTP set are enforced in-repo (Mix refuses an Elixir outside the range and config/config.exs refuses an OTP major outside the set, both before anything compiles), and they move in lockstep with .tool-versions and the CI lanes (see the supported-toolchain ADR). Zero runtime dependencies (OTP :crypto only). From protocol_revision 3 the runtime floor has a second axis: ML-DSA verification needs an OTP runtime whose linked crypto library is OpenSSL ≥ 3.5 (FIPS 204 landed there; OTP ≥ 28.1 with OpenSSL ≥ 3.5 is the declared floor — a runtime linked against OpenSSL 3.0.x cannot generate or verify ML-DSA keys, and OTP 27 exposes no ML-DSA algorithms to :crypto even with OpenSSL ≥ 3.5 linked). The shipped corpus contains ML-DSA cases, so the quick-start verification below needs that floor too:

{:charter_agreement_protocol, "~> 0.4.0"}

Then verify the shipped, certified corpus from your dependent project:

$ mix run -e 'System.halt(CharterAgreementProtocol.Conformance.Cli.run(["--corpus", "deps/charter_agreement_protocol/priv/conformance"]))'

The command prints the canonical JSON report and exits 0 when all 100 certified cases recomputed and agreed. Full walkthrough: Getting started.

Try it

  • TypeScript verifier on npm: npm install @charter-agreement-protocol/verifier — the independent second verifier as a standalone package under the charter-agreement-protocol organization, with the certified corpus vendored inside.
  • Runnable notebooks: charter tour and fork repair — a complete bilateral charter with real Ed25519 signatures, and a manufactured equivocation with its countersigned repair.
  • Repository demo: mix run examples/supplier_fork_demo.exs — equivocation evidence, contested governing view, an action receipt inside the fork, and the repair, in nine lines of output.

Guarantees at the call boundary

  • Failures are typed and value-free — closed error codes, protocol-owned subjects, never rejected input — so verification failures are safe to log.
  • Facts implement redacted inspection — retained signed artifacts never appear in logs.
  • Verification is pure: no clock, filesystem, network, or environment. Callers supply time, limits, trust anchors, and keys.
  • Key custody stays outside the protocol: CAP builds the exact RFC 7515 signing input, you sign it, assemble_compact/2 accepts only an external raw signature at the registry row's exact length (64 bytes for Ed25519; 2420/3309/4627 for the ML-DSA parameterizations), and hosts post-verify before serving the compact. A reviewed companion signer implements that host glue for you — charter_agreement_signer (atomic kid/key snapshot, wrong-key guard, post-sign verify, refusal surfacing); verifiers never depend on it, and hosts may always hand-roll per the spec instead.

Guides

Status

The approved protocol core, normative specification set, certified corpus with four recorded identities, independent second verifier, mutation battery, and release-candidate gates are implemented and green in CI. The 0.3.x line carries protocol_revision 3 — the ML-DSA registry act (RFC 9964): the ML-DSA-44/65/87 names verify from revision 3, the descriptor key grammar admits ML-DSA keys gated on revision, producers mint ML-DSA-65 at revision 3 alongside Ed25519 at revision 2, and the resource boundary is byte-weighted for PQ-sized artifacts. 0.3.1 corrects the declared runtime floor (OTP ≥ 28.1 with a linked OpenSSL ≥ 3.5), runs CI on an ML-DSA-capable substrate, and re-trues the shipped documentation to the revision-3 surface. protocol_revision 2 (RFC 9864 alg names) and revision-1 artifacts remain verifiable. Building an archive remains verification evidence only — never authority to publish.

Development

mix deps.get
mix quality

mix quality is the complete gate — audits, formatting, warnings-as-errors compile, strict credo, the full test suite with its coverage threshold, certified-conformance verification and regeneration identity, all 25 named source mutations, Elixir/TypeScript verifier agreement over repository and unpacked-package corpora, dialyzer, docs, and the reproducible release-candidate archive. Contribution bar and invariants: CONTRIBUTING.md.

License

Apache-2.0 — see LICENSE.