Files
mesh-sdk/go
jschoubben 0de3006415
mesh/delivery merged: source.main moved to novox/mesh-sdk@98f2f2406921
mesh/delivery-group group fix/1126-apply-culprit merged: every member is merged
mesh/check pass 0de30064156a on 7aedd28f01dc | unit 2667 run, 590 kept, 36 skipped | integration 2676 run, 633 kept, 29 skipped | over bound: unit (sl…
A module refused alone is held, composed as what runs of it, on the node that applies as in its answer: one rule for both paths (issue 1126)
The applying path (frombus.Compose) composed with no culprit, so one module's
refusal came back as the whole node's: novox's apply would have refused all its
modules for de-spiegel's unset route names. composeEach is now the one rule
Compose and Answer both follow:
- a module whose stub changes the refusal is held (compose.Node.Held); in the
  applying path a stand-in for a module placed here holds that module; only a
  refusal of no single module refuses the node;
- a held module is composed from what runs of it (compose.Carried of its own
  composition in Running) and carried in the node's own wherever that runs it,
  folded or leaving the fold, so the node's own apply never removes it (issue
  1945 by a new path) and what the others read of it is what runs;
- none of a held module's own composition is in what is applied;
- a module whose composition differs when the held ones are composed as stubs
  is held too; the node's own differing refuses the node;
- since a held module is composed from its new manifest, what reads that
  manifest is held with it: the providers of what it contributes to (the
  proxy its routes) and, when it listens, the filter's holder.

Quick fix weighed: a culprit loop in Compose alone. Thorough, chosen: one
shared function, since the kind met twice (seed-8 shadow, now the apply), and
review rounds 1 and 2 found its leaks.
2026-10-28 17:22:35 +01:00
..

mesh-sdk for Go

stdio.Serve("", tools) speaks MCP over stdio to the node's tool runtime, as the module the runtime names (novox/hq ADR 0188, ADR 0193). A Tool is a name, a description, an argument schema and a function; calls run concurrently. stdio.CallerOf(args) inside a tool is who called it: the bus user the runtime took from the subject the call arrived on, named in the call's _meta, never read from the arguments — or stdio.Unproven when the runtime named none (novox/hq issue 365). A tool named <seat>.<verb> is the seat's implementation. stdio.Emit(type, body) publishes an event as the module, stdio.Subscribe(pattern, handler) receives the module's events (taken when the handler returns nil, offered again when it returns an error — the one rule is in the repository README, "Taking an event") and stdio.Ask(key, body) calls a tool, and stdio.State(name) gets, puts, deletes, lists, watches and reads the kept history of the module's declared state, and stdio.Log(name) appends to, reads, and measures a log of operations the module declared — all through the runtime (novox/hq ADR 0193, 0198, 0201, 0297, 0307). stdio.Config(key) and stdio.Bound(provision, key) read, and stdio.WatchConfig and stdio.WatchBound watch, the module's own config values and the non-secret values of what it is bound to, for what its manifest declares: the runtime asks its machine's provisioner client as the module it launched, never a module the code names. stdio.Secret(name) is refused while the module's code runs in the tool runner; its secrets reach it through its files (novox/hq ADR 0349 §14, ADR 0370). provider is a providing module's half of a binding (novox/hq ADR 0349 §12, issue 678): it sees each consumer that binds the provider in the plans of the assignments mirror, writes one entry per consumer to <module>_bound (<node>.<module>.<provision>[.<local>]: served values composed with the consumer's identity, the login, and the name of the vault's credential, never a secret), hands the provider's adapter the vault's value (provision/<provider>/<provision> shared, pair/<provider>/<provision>/<node>/<module>[/<local>] per consumer), refuses a derived value to a consumer bound under a local name, naming both ends, and removes the entry of one that unbinds; the bus and the vault are interfaces the provider wires, the vault as provider.ConsumersFile, the file its machine's provisioner client fills from ${consumers:<provision>} with each bound consumer's credential (novox/hq ADR 0373), since a provider in the tool runner never asks the vault itself. Standard library only.

Installing

GOPRIVATE=git.novox.be go get git.novox.be/novox/mesh-sdk/go@latest

Releases are tagged go/vX.Y.Z in this repository, the subdirectory form Go's module system expects, at the same version as the TypeScript package.

What it holds, under ADR 0039's test: the stdio loop and the tool type, and cli, the local protocol mesh-cli speaks to the node-engine on its machine (novox/hq ADR 0272): the socket's path and one request and one answer; and seal, the mesh's sealed box (novox/hq ADR 0206: X25519, HKDF-SHA256, AES-256-GCM, {v, eph, iv, tag, ct}), byte for byte the box the licence manager made before it lived here and the TypeScript @novox/mesh-sdk/seal makes. Nothing else — no bus, no client, nothing of any module's. go build ./example and pipe a tools/list request into it.

From release 4a of design 47 (novox/hq ADR 0453 clause 3, ADR 0446 clause 4) it also holds the composition of a machine's declaration, over a plain input and with nothing behind it: declaration and validate, the node-engine's parser and its validator, copied from mesh-host; catalogue, the manifests, their resolution and rendering, and overlay, the private network's generator, copied from mesh-controller; compose, the controller's planFor, renderingFor and declarationWith as functions of an Input (the composition never allocates, makes, keeps or writes: what a send would do it names as foreseen or returns); sdkversion, which mesh-sdk version a program was built with; and, in delivery, the layouts of the keys the builder, the checker and the indexer write (the source fingerprint's new form, the builds, the verdicts and kept verdicts, the manifests by digest). None of them holds a bus, a store or a vault client, which go list -deps of compose shows.