Module client_contract
Expand description
Per-op contract digests (cratestack#1123, EXT-14): the 32 bytes that move only when the wire shape of one op changes.
schema_digest hashes the whole IR, so a policy,
an @@index, a view’s SQL or a new procedure changes it and every signed
client built before that edit is refused. An op’s contract is the closure
a peer decodes it under: its transport, key and kind, its input and
output roots, and every model, type, enum and view reachable from them
(through fields, generic arguments, relations and @computed(params:)),
each in its wire projection (@server_only fields removed).
Out entirely: the datasource, config blocks, extension blocks, the
auth block, the schema-level MCP config, mixins (the parser expands
them into fields), queries, every other op, docs and spans. Attributes
on the reviewed DROPPED_ATTRIBUTES list are filtered; every other
attribute, known or not, stays in, so a new one moves digests until it is
reviewed onto that list. The digest is
SHA-256(OP_CONTRACT_DOMAIN || canonical JSON); if the derivation rules
change, the domain tag moves to op-contract/v2.
The COSE AAD binds the digest of the op a message calls (binding
version 2; ADR 0006 §4); [table] holds the tables generated code
carries and how a route finds its row. cratestack contract digest|print shows the digests.
A server may keep accepting older contracts of an op: ContractLock
records the ones in the field, classify decides which are still
wire-compatible with the current one, and include_server_schema!’s
contracts = argument turns the survivors into ACCEPTED_CONTRACTS
(an incompatible entry is a compile error). cratestack contract lock|check|prune maintain the file.
Structs§
- Contract
Lock - A parsed, integrity-checked lock file.
- Generation
- One locked moment: the client contract digest and each op’s digest then.
- Incompatible
- A locked contract the current one no longer stays compatible with.
- Pruned
- What a prune removed.
Enums§
Constants§
- BATCH_
CONTRACT_ KEY - The row of a signed
/rpc/batch: the route the AAD already binds. - CLIENT_
CONTRACT_ DOMAIN - Domain-separation tag of
client_contract_digest. - LOCK_
FORMAT - The lock file format this build reads and writes.
- OP_
CONTRACT_ DOMAIN - Domain-separation tag of an op digest.
Functions§
- bound_
contracts - The digest a call to
method routebinds, for every key ofschema(what the macros emit asOP_CONTRACTS): each op’s digest, plus thebatchrow fortransport rpc. In key order, which nothing relies on. - classify
- Judge the contract
old(a canonical op contract, as stored in a lock) againstnew(the schema’s current one), both as JSON values of the shapeop_contract_jsonprints. - client_
contract_ digest - A build identity for the client-facing contract: a hash over the sorted
[key, hex(op digest)]table. It moves when any op’s contract moves, a new op appears or one disappears. - digest_
hex - Lowercase hex of a digest.
- find_
contract - The row a call belongs to: an RPC route is its
op_id(orbatch); a REST route is bound as the template, and keyed"<METHOD> <template>". No allocation: an RPC id never starts with a method and a space. AHEADis theGETop’s (axum serves it from that route; the binding still names the method it was sent with). - op_
contract_ digest - The digest of the op
key(an RPCop_id, or"<METHOD> <route>"on REST), orNonewhen the schema exposes no such op. - op_
contract_ digests - Every op’s digest, sorted by key.
- op_
contract_ json - The canonical JSON an op digest hashes (what
cratestack contract printshows), orNonewhen the schema exposes no op with that key. - op_keys
- The key of every op
schemaexposes, sorted: the keys the generated routers and clients expose, asserted equal to the macro’sOPS/ROUTE_TRANSPORTSby the parity test.
Type Aliases§
- Accepted
Contracts - What a server accepts: per op (and
batch), the digests a request may bind, current first, then older compatible ones newest first. - OpContracts
- What a client stamps: one digest per op (and
batch), emitted in key order for a stable diff. Lookup (find_contract) is a linear scan: nothing relies on the order.