From a40595fa088ed765b762e6e989ef939c512bba82 Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 16 Sep 2026 00:06:49 +0200 Subject: [PATCH] =?UTF-8?q?ADR=200074:=20correct=20the=20evidence=20?= =?UTF-8?q?=E2=80=94=20the=20live=20wire=20agrees?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The record claimed the two implementations already disagreed. Inspection showed the live wire agrees: the disagreeing grant types were dead (removed), and the envelope's two extra headers are optional and set when relevant, not missing. The danger was dead types contradicting the wire, not live disagreement — which is a sharper reason for specifying the wire and checking against it, not a weaker one. The model stands; the conformance suite's job is prevention rather than repairing a present break. Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx --- ...074-the-wire-is-specified-not-the-types.md | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 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 8517c20..e1ffe2f 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 @@ -19,16 +19,24 @@ There is already more than one. **The contracts are expressed twice** — as Go plane and the host, and as TypeScript types in the SDK — and nobody has felt it because both live in one repository and one head. -**They already disagree.** Not in some future where a second language is added; today: +**A correction, made after inspecting the wire rather than the types** (2026-09-16). This record +first claimed the two implementations already disagreed — `resource` vs `Provision`, `consumer` +meaning the module in one and the node in the other, headers declared on one side and emitted by +neither. **On inspection the live wire agrees**, and the claim was wrong: -| | TypeScript | Go | -|---|---|---| -| the provision's field | `resource` | `Provision` | -| what `consumer` means | **the module** | **the node**; the module is `From` | -| event headers | six, including `x-causation-id` and `x-schema` | four — the other two are never written | +- The grant types that disagreed (`Grant`, `Interface`, `Credential` in the SDK's `contracts`) + were **dead** — exported and imported by nothing. The live provisioning wire is the contributions + file, whose shape (`as`, `secret`, `node`, `at`, `values`) is the same on both sides. Those dead + types have been removed. +- The envelope agrees too: Go emits all five required headers, and `x-causation-id`/`x-schema` are + **optional** — the SDK sets them when a handler has a causation or a schema, and a bare event + carrying neither is correct, not a drift. -So one word means two things in the two halves of one mesh, and the header that exists so a body's -shape can change without silent misreads is declared on one side and emitted by neither. +So the danger was never live disagreement. It was **dead types that contradicted the live wire**, +which read as the contract and were not — and are exactly what led this record to assert a drift +that inspection did not find. That is a sharper reason for the decision below, not a weaker one: a +type is only as good as its being the wire, and the way to guarantee that is to specify the wire and +check implementations against it, rather than to trust a hand-kept type to still describe it. A failure of this kind does not announce itself. Two implementations that disagree about an envelope do not fail to compile — they ignore each other's messages, and a mesh where a module @@ -144,9 +152,10 @@ pieces, rather than believed. with a version on the body is what lets a mesh hold a module built against an older SDK, which is the ordinary state of any mesh that has been running for a while. -**The two current implementations will be found wrong.** They disagree, so at least one is. Fixing -that is the point rather than a cost, but it is not free: something is emitting or expecting -something it should not. +**The two current implementations agree on the live wire** — inspection showed it. What was wrong +was a set of dead types beside the wire, now removed. The suite's job here is therefore prevention: +to keep that agreement true as the wire changes, and to hold a new language's SDK to it, rather than +to repair a break that exists today. **This does not make the mesh polyglot by itself**, and should not be reported as though it does. It makes polyglot possible to do correctly. A Rust SDK is still a Rust SDK.