Skip to main content

Module contract

Module contract 

Source
Expand description

v0.177 (#643): the canonical normal form of a cross-context contract, and its hash.

A workers build compiles context A against context B’s contract, and nothing at runtime checks that the deployed B still matches what A was compiled against — deploy --context NAME institutionalises the skew. The fix is to stamp a hash of the compiled contract beside X-Bynk-Caller and fail closed on mismatch (ADR 0092’s pattern: a compile-time constant in a reserved header, metadata beside the payload, no crypto).

The hash is only as good as the form it hashes. Two rules make it usable:

  1. Semantically-equal contracts must hash equal, or a working deployment 409s spuriously — which is worse than no check at all, because it breaks what worked and destroys trust in the mechanism. This is why the form is canonical (predicates as a sorted set, record fields sorted by name) rather than a rendering of source order.
  2. Both sides must canonicalise the same thing. The callee’s contract is canonicalised in the callee’s own namespace, from the callee’s own type table, on both sides — never in the caller’s. The caller reaches that table through consumed_types[callee] and the callee through its own combined table; both are produced by the same combined_types_for, so the two views cannot diverge by construction. A caller never canonicalises a consumed type in its own namespace, where its rebranding would make the same type render differently.

Functions§

canon_capability_op_signature
P8.1 (#1512, [DECISION C]): the canonical form of a CapabilityOpSignature — added by PR #1517’s own bot review (finding #3): a capability declaration’s own ops are the abstract signature a consumer’s Cap.op(...) call site compiles against.
canon_fn_signature
P8.1 (#1512, [DECISION C]): the canonical form of a FnSignature — extends this module’s own canon_type (ADR 0200) to a shape it doesn’t reach today. Body-free by construction ([DECISION B]): there is no body/requires/ensures field on FnSignature to accidentally include here.
canon_handler_signature
P8.1 (#1512, [DECISION C]): the canonical form of a HandlerSignature. given renders sorted — its rendered CapRef names have no meaningful order to preserve (it’s a set, not a sequence). kind is rendered first (PR #1517’s own bot review, finding #1) — two handlers that differ only in HTTP method or route, or in on call vs. on message, must not canonicalise identically.
canon_predicate
canon_refinement
Predicates canonicalise as a sorted set.
canon_store_field_signature
P8.1 (#1512, [DECISION C]): the canonical form of a StoreFieldSignature.
canon_unit_signature
P8.1 (#1512, [DECISION C]): UnitSignature::canonical’s own implementation — the single rendering R3.14’s own stability proof compares. Every category is rendered sorted (by the caller’s own BTreeMap/BTreeSet keys, or an explicit sort for Vec-shaped fields like a handler’s own given), so construction order never perturbs the form — the same “compare the canonical string, not map/vec iteration order” discipline service_normal_form’s record-field sort already established for ADR 0200.
contract_hash
FNV-1a (64-bit) over the canonical form, rendered as 16 lowercase hex chars.
own_contract_hashes
v0.177 (#643): a context’s own on call contract hashes, keyed by service name — the constants its Worker entry compares an incoming X-Bynk-Contract against.
service_contract_hash
The stamped contract hash for one consumed service.
service_normal_form
The canonical normal form of one on call service contract.