diff --git a/02-DECISIONS/0074-the-wire-is-specified-not-the-types.md b/02-DECISIONS/0074-the-wire-is-specified-not-the-types.md index 21a9f6f..e7f454f 100644 --- a/02-DECISIONS/0074-the-wire-is-specified-not-the-types.md +++ b/02-DECISIONS/0074-the-wire-is-specified-not-the-types.md @@ -7,7 +7,7 @@ reconstructed: false extends: 0039-what-the-sdk-holds-and-refuses.md --- -# 74. The wire is specified; an SDK is whatever passes the conformance suite +# 74. The mesh defines a module protocol; an SDK is an implementation of it ## Context @@ -51,9 +51,47 @@ right is *behaviour*. ## Decision -**The wire is specified, and an SDK is any implementation that passes the conformance suite.** +**The mesh defines a module protocol. An SDK is an implementation of that protocol in one +language, and nothing more.** -What the specification covers is what two implementations can disagree about: +That is the whole of what an SDK is. Not a library a language happens to have, not a convenience +layer, not a place for helpers to accumulate — an implementation of a specified protocol, finished +when it implements it and correct when it agrees with every other implementation. + +### The protocol is split per capability + +**A module does not use all of it, so an SDK need not implement all of it.** A module that only +consumes events uses the event capability. One that serves tools uses the tool capability. A +provider uses provisioning. Nothing about consuming an event requires knowing how a grant is +answered. + +So the protocol is a floor plus capabilities: + +| part | what it covers | who needs it | +|---|---|---| +| **connection** — the floor | reading the sealed credential, pinning the certificate fingerprint, taking identity from the credential rather than the environment | everything | +| **events** | the envelope and its headers, the durable per-consumer queue, binding, at-least-once with dedup on `x-event-id` | a module that emits or consumes | +| **tools** | registration, the shared durable `serve.` queue, request and reply | a module with a surface | +| **provisioning** | a grant in, a credential out, and what each carries | a module that provides something | + +**This is the same shape the host already has.** A host declares which resource kinds it can apply, +and a partial host — one that can write files and run things but not manage users or containers — +is a real thing rather than a broken one ([ADR 0005](0005-the-node-host.md)). An SDK that implements +the floor and events is exactly as legitimate, and a module written against it is a module that +does events. + +**So a language arrives in pieces rather than all at once.** A Rust SDK implementing connection and +events is useful the day it exists; tools and provisioning follow when something needs them. The +alternative — a language is unsupported until it is entirely supported — is what makes adding one a +project rather than a contribution. + +**And what a language can be used for is then a fact the mesh can state**, rather than something an +author discovers by writing a module that cannot be built: the toolchain list says which languages +exist, and the conformance results say what each can do. + +### What the specification covers + +Per capability, what two implementations can disagree about: - **the exchanges and queues** — which exchanges exist, that a consumer's queue is durable and named `..events`, that a tool is served from a shared durable `serve.` @@ -67,6 +105,12 @@ What the specification covers is what two implementations can disagree about: - **provisioning** — a grant in, a credential out, and what each carries - **the vocabulary** — that `consumer` is one thing, named once +### Conformance is per capability + +**A suite per part, and an SDK claims the parts it passes.** A monolithic pass/fail would make a +partial implementation indistinguishable from a broken one, which is the distinction this is built +on. + **And the suite is executable, not prose.** A specification nobody can run is a document two implementations drift from while both believe they conform. Conformance is a set of fixtures — an emitted event, a served tool call, a grant and its answer — that every SDK must produce and consume @@ -91,9 +135,10 @@ second. ## Consequences -**A language is a commitment, and now a measurable one.** Adding one means implementing the wire -and passing the suite. That is more work than transliterating types, and it is the work that was -always there — the difference is that it can now be finished rather than believed. +**A language is a commitment, and now a divisible one.** Adding one means implementing the protocol +and passing the suites for the parts it claims. That is more work than transliterating types, and +it is the work that was always there — the difference is that it can be finished, and finished in +pieces, rather than believed. **Versioning becomes possible.** `x-schema` exists for it and is never written. A specified envelope with a version on the body is what lets a mesh hold a module built against an older SDK, which is @@ -112,6 +157,7 @@ makes polyglot possible to do correctly. A Rust SDK is still a Rust SDK. |---|---| | One vocabulary | A word means one thing across implementations, checked by the fixtures using it. | | The wire is what is specified | Both existing SDKs run the conformance suite in their own test suites, and a change to one that breaks a fixture fails there rather than in a mesh. | -| A new SDK is a passing SDK | A language is not listed as buildable until its SDK passes; the toolchain list and the conformance results name the same set. | +| A new SDK is a passing SDK | A language is not listed as buildable for a capability until its SDK passes that capability's suite; the toolchain list and the conformance results name the same set. | +| A partial SDK is a real thing | An SDK implementing the floor and one capability passes, is listed for that capability, and a module using another is refused with the reason — rather than failing at runtime in a language nobody said was finished. | | An unknown header is ignored | A fixture carries one, and every implementation accepts it. | | Identity comes from the credential | A fixture sets an environment that disagrees with the credential, and the emitted event carries the credential's. | diff --git a/02-DECISIONS/README.md b/02-DECISIONS/README.md index ac152e9..d4e8558 100644 --- a/02-DECISIONS/README.md +++ b/02-DECISIONS/README.md @@ -106,7 +106,7 @@ python3 00-META/checks/index.py fail if stale - **0071** — [Genesis clones from a mesh, and checks what it got](0071-where-genesis-gets-its-source.md) - **0072** — [Two graphs, and a build chain that orders itself](0072-two-graphs-and-the-build-chain.md) - **0073** — [The installer carries a builder, and the registry stays where it is](0073-the-installer-carries-a-builder.md) -- **0074** — [The wire is specified; an SDK is whatever passes the conformance suite](0074-the-wire-is-specified-not-the-types.md) *(proposed)* +- **0074** — [The mesh defines a module protocol; an SDK is an implementation of it](0074-the-wire-is-specified-not-the-types.md) *(proposed)* ### What runs on them, and how it gets there