Design 29: tools, not serves; WBS 3.9 partly done

The manifest already uses serves for a provision's facts, so a module's
tools take their own key. Declaring them is itself new — until now a
module's tools existed only in a runtime environment variable.
This commit is contained in:
2026-09-26 22:17:17 +02:00
parent 0b8e84334f
commit b759e36bfd
2 changed files with 20 additions and 6 deletions
+11 -4
View File
@@ -237,10 +237,17 @@ pays for itself furthest away.
- [ ] 3.8 **the declaration model** of [design 29](29-what-a-module-declares.md): local names
derived to subjects, the three namespaces, permissions computed from a declaration, and a
manifest that contains no subject
- [ ] 3.9 **seats declared by modules** — registration creates a seat's streams and refuses a
`mesh-*` name, a duplicate declarer, an undeclared `uses`, and a holder that does not
satisfy the protocol; assignment creates the holder's work-queue consumer and refuses a
second holder
- [~] 3.9 **seats declared by modules** — the manifest now carries `seats` (name, scope,
accepts/emits/serves, retention) and `uses`, and registration refuses a `mesh-*` name, a
duplicate declarer, an undeclared `uses` or claim, a seat with no protocol, a scope
mismatch, and a holder that does not answer what its seat promises. **Still to do**:
creating a seat's streams at registration and its holder's work-queue consumer at
assignment, which need the JetStream client wired in.
The refusal for an unknown claim *moved* rather than disappeared — the parser cannot judge
it from one manifest any more, because another module may legitimately declare that seat,
so it is registration's. The test that encoded the old rule was rewritten rather than
deleted, and a second one pins the case the parser could not distinguish.
- [ ] 3.10 **the ten seat renames**, carried as a migration with a mapping rather than an edit,
and the beds that name seats moved with them
@@ -29,7 +29,7 @@ those, and a manifest never contains one.
**The requirement delivers the connection; the declarations shape the authority.** `requires:
mesh-bus` says *this module talks to the mesh* and grants no subject by itself. `emits`,
`consumes`, `serves`, `uses` and a declared seat say what it may say and hear. Declaring a subject
`consumes`, `tools`, `uses` and a declared seat say what it may say and hear. Declaring a subject
without requiring the bus is incoherent and refused at registration.
This document is the declaration model. [Design 25](25-the-bus-on-nats.md) is the bus itself —
@@ -49,10 +49,17 @@ the catalogue, and the mesh would have hundreds of copies of a decision it made
|---|---|
| `emits: order.placed` | publish on `mesh.mod.<module>.event.order.placed` |
| `consumes: billing.order.placed` | durable consumer on `mesh.mod.billing.event.order.placed` |
| `serves: status` | queue-group subscription on `mesh.mod.<module>.tool.status` |
| `tools: status` | queue-group subscription on `mesh.mod.<module>.tool.status` |
| seat `telegram-sender`, `accepts: send` | work-queue consumer on `mesh.seat.telegram-sender.accept.send` |
| `uses: telegram-sender` | publish on that seat's `accept` subjects, and nothing else |
**It is `tools:`, not `serves:`.** Revision, found while implementing: the manifest already uses
`serves` for the facts a consumer needs in order to reach a provision, and two meanings under one
key in the file a module author reads most is a footgun. Worth noting that until now a module's
tools were not declared at all — they were known only at runtime, from an environment variable in
its image — so declaring them is new, and is what lets the mesh check that a module claiming a
seat answers what that seat's protocol promises.
**The `event` / `tool` / `accept` token is load-bearing, not decoration.** Revision, found while
defining the streams: a stream is defined by a subject filter, so a namespace holding both a
module's events and its tool calls cannot be filtered into an events stream without capturing