From 89302aa3e05b9e73e5b4b60d02806aa727eea757 Mon Sep 17 00:00:00 2001 From: jochen Date: Tue, 15 Sep 2026 13:40:15 +0200 Subject: [PATCH] The protocol is split per capability, and an SDK implements it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two corrections, both from the operator and both better than what was written. An SDK is an implementation of the mesh's module protocol in one language, and nothing more. The first draft defined it by the test it passes, which describes how you check one rather than what one is — and leaves it sounding like a library that helpers could accumulate in. And the protocol is split per capability, which was missing entirely. 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 an SDK need not implement all of it to be real. That has a precedent here: a host declares which resource kinds it can apply, and a partial host is a real thing rather than a broken one (ADR 0005). An SDK implementing the floor and events is exactly as legitimate, and a module written against it is a module that does events. Which changes what adding a language costs. A Rust SDK doing connection and events is useful the day it exists, with tools and provisioning following when something needs them — rather than a language being unsupported until it is entirely supported, which is what makes adding one a project instead of a contribution. Conformance is therefore per capability too: a monolithic pass or fail would make a partial implementation indistinguishable from a broken one, which is the distinction the whole thing rests on. Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx --- ...074-the-wire-is-specified-not-the-types.md | 60 ++++++++++++++++--- 02-DECISIONS/README.md | 2 +- 2 files changed, 54 insertions(+), 8 deletions(-) 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