Design 38's WP1-WP4b ran: the node's tool runtime is live on all four machines as the operator account, tools are bundles given only their declared words, and a bundle has no bus credential. So the wait on design 38 WP3 is over, the agent module calls nothing and the manager starts every exchange (key, hand-over, waiting login, reconcile), and the manager's daemon now waits on WP4c's record instead. Accounts are stated on all four, sudo -n works for each, the agent is installed on all four; the plan's WP0 shrinks and WP2 gets a configuration-only live proof before any licence.
209 lines
14 KiB
Markdown
209 lines
14 KiB
Markdown
---
|
||
layer: to-be
|
||
status: designed
|
||
code: []
|
||
updated: 2026-10-03
|
||
decisions:
|
||
- 02-DECISIONS/0183-the-anthropic-licence-manager-is-a-module-and-hands-tokens-to-the-agent-over-the-bus.md
|
||
- 02-DECISIONS/0181-the-operator-account-is-a-node-fact-and-a-home-is-a-placement-root.md
|
||
- 02-DECISIONS/0182-inside-a-home-the-mesh-owns-what-it-places-and-holds-the-rest-as-found.md
|
||
- 02-DECISIONS/0175-one-tool-runtime-per-node-serves-every-modules-tools-on-the-host-side.md
|
||
- 02-DECISIONS/0188-a-modules-own-code-is-bundles-in-any-language-and-a-tools-bundle-speaks-mcp-to-the-runtime.md
|
||
- 02-DECISIONS/0192-a-tools-bundle-declares-what-it-is-given-and-the-runtime-hands-it-to-that-bundle-alone.md
|
||
- 02-DECISIONS/0149-the-live-mesh-is-the-test-bed.md
|
||
- 02-DECISIONS/0027-a-provision-names-what-the-consumer-is-coupled-to.md
|
||
---
|
||
|
||
# 40. Building the operator's agent and its licence manager
|
||
|
||
**The work of [design 36](36-the-operators-agent-on-a-machine.md) and [design 39](39-the-anthropic-licence-manager.md),
|
||
broken into packages that each end at something a person can see run, in the order their
|
||
dependencies allow.** The two designs are the authority on *what* is built; this document holds the
|
||
packages, their order, their sizes and their proofs, and is wrong the moment it disagrees with them.
|
||
It is the shape [design 38](38-building-the-operators-machine.md) gives the operator's machine.
|
||
|
||
*Revised 2026-10-03, after design 38's WP1–WP4b ran:* the node's tool runtime is live on all four
|
||
machines, tools are bundles it serves and each is given only the words its artifact declares, and a
|
||
bundle has no bus credential of its own. Three things in the first version of this plan changed with
|
||
that: the wait on design 38's WP3 is over; the agent module calls nothing, so the manager starts every
|
||
exchange (ADR 0183's dated note); and the manager's own process now waits on a different question,
|
||
named under WP4.
|
||
|
||
## How this is built, and where it is run
|
||
|
||
**On the live mesh, by the operator's decision** ([ADR 0149](../../02-DECISIONS/0149-the-live-mesh-is-the-test-bed.md)).
|
||
Every package is written with unit tests, committed on one branch per repository
|
||
([playbook 07](../../00-META/process/07-feature-branches.md)), and proven on the machines: one
|
||
workstation first for the agent, the control node first for the manager, then the rest. A broken agent
|
||
module leaves a workstation's agent without the mesh's instructions or with a stale token until the next
|
||
push; the person's own files under the home are out of the failure's reach, by
|
||
[ADR 0182](../../02-DECISIONS/0182-inside-a-home-the-mesh-owns-what-it-places-and-holds-the-rest-as-found.md).
|
||
|
||
Each package names what proves it. A package that cannot name its proof is divided until it can.
|
||
|
||
## What exists already, measured
|
||
|
||
Measured 2026-10-03 on the four machines and in the repositories.
|
||
|
||
| Piece | Today | Becomes |
|
||
|---|---|---|
|
||
| the node's tool runtime | live on all four, a host process; **runs as the operator account**; listens for the console on loopback at a port its own code fixes; launches or imports every assigned module's tools bundle and hands each its declared words | serves the agent module's tools; gains one provision for its endpoint (WP1) |
|
||
| the operator account | **stated on all four** — the runtime runs as it | read by the agent module from the runtime's own words |
|
||
| escalation | passwordless `sudo` for the operator account on all four — a fact about the machines, checked by nobody | how the agent module writes its managed directory under `/etc` |
|
||
| the agent itself | installed on all four, at four different versions, all above the one the managed tool-server key needs | declared as the module's package |
|
||
| a bundle's words | paths and constants written with `${dir:…}` and `${port:…}` only; a fact the mesh knows reaches a bundle as a file whose path is a word | the agent module's facts file and settings file |
|
||
| a bundle calling a tool | **not possible**: a bundle answers calls; it holds no bus credential | the manager starts every exchange |
|
||
| a module's own long-running process with a bus credential | **undecided** — design 38's WP4c names it as the question its next record answers | the manager's daemon (WP4) |
|
||
| the vendor's refresh, the sealed box, the grant file | `anthropic-manager` in the catalogue, built on the controller placement ADR 0183 moved away from; assigned to nothing | its client ported into the manager; the module retired (WP6) |
|
||
| the credentials write, the strip, the identity read | `anthropic-consumer` in the catalogue; tested; assigned to nothing | ported into the agent module with its tests; the module retired (WP6) |
|
||
| the predecessor's manager and consumer | the lease per licence, the expiry floor, the lineage comparison, the identity guard, three touchpoints, cooldowns | ported as logic with its tests |
|
||
|
||
## The order the work allows
|
||
|
||
```
|
||
WP0 the operator names the licences and each node's role (the live mesh) ── an hour
|
||
WP1 the runtime provides its endpoint (mesh-tools) ── small
|
||
WP2 the agent module (mesh-catalog) ──┐ WP2 needs WP1;
|
||
WP3 the manager's code, built and tested (mesh-catalog) ──┘ WP3 is independent
|
||
│
|
||
WP2 live: one workstation, configuration only — no licence yet ── the first live proof
|
||
│
|
||
WP4 the manager live on the control node ── waits on design 38 WP4c's record (a process's bus credential)
|
||
WP5 the licence end to end on one workstation
|
||
WP6 the rest of the nodes, and the predecessor's remains
|
||
```
|
||
|
||
## WP0 — The operator names the licences and each node's role
|
||
|
||
*The live mesh. An hour, and it is the operator's.* The accounts are stated already. What remains: the
|
||
names of the two subscription licences and the API key; each node's role, as the agent module's setting
|
||
on the node layer once the module is registered.
|
||
|
||
**Proof.** The module's settings list a role for every node; the licences have names.
|
||
|
||
## WP1 — The runtime provides its endpoint
|
||
|
||
*mesh-tools. An hour.*
|
||
|
||
**What changes.** The `node-tools` manifest provides a node-scoped provision, `mcp-endpoint`, serving
|
||
the port its code listens on, the way the local model server serves its API
|
||
([ADR 0027](../../02-DECISIONS/0027-a-provision-names-what-the-consumer-is-coupled-to.md)). Co-location
|
||
resolves it. The runtime's port stays what its code fixes; assigning it is
|
||
[issue 192](../../04-ISSUES/192-the-meshs-tools-reach-a-person-only-by-a-registration-made-by-hand/00-report.md)'s
|
||
second question and not this package's.
|
||
|
||
**Proof.** The plan for a workstation carrying a consumer of `mcp-endpoint` shows it bound to the
|
||
runtime's port; the controller's tests and the catalogue's checks pass.
|
||
|
||
## WP2 — The agent module
|
||
|
||
*mesh-catalog. A day and a half.*
|
||
|
||
**What is written**, as design 36 says:
|
||
|
||
1. **The manifest.** The agent's package. A state directory. A facts file in it, rendered by the mesh:
|
||
the node's name and the console's address from `mcp-endpoint`. A settings file in it, merged from
|
||
the module's settings layers: the node's role and the extra tool servers. A tools bundle whose
|
||
words name the two files, the state directory and nothing else. **No file resource under a home or
|
||
under `/etc`.**
|
||
2. **The renderer**, run whenever the runtime collects the module's tools: from the two files, the
|
||
managed settings file (the tool servers under the entry `mesh`, the attribution trailers, the
|
||
key-helper for an API-key binding) and the managed instruction file, written under the agent's
|
||
managed directory through the account's escalation, only when their content changed.
|
||
3. **The keypair**, made once in the state directory; X25519 and an authenticated cipher from the
|
||
language's own library, so the bundle carries no dependency.
|
||
4. **The tools**: `claude_code_status` (what is rendered, what licence is held, when its token expires,
|
||
fingerprints only); `claude_code_render` (render now); `claude_code_public_key`;
|
||
`claude_code_apply` (a sealed token, applied only if newer within one lineage unless it is a switch;
|
||
the credentials write as the operator, access-token-only, atomic; the key-helper program for an API
|
||
key); `claude_code_pending_login` (a full grant found in the credentials file, sealed to the key the
|
||
caller gives, with the account's identity).
|
||
5. **The documentation**: the six predecessor files and the hand-made console entry a person removes.
|
||
|
||
**Proof, before anything runs live.** Unit tests: the renderer writes the mesh's keys and nothing else;
|
||
it writes nothing when nothing changed; the credentials write strips a refresh token and is atomic; the
|
||
lineage cases from the predecessor; a sealed hand-over opens only with the module's key; no tool's answer
|
||
contains a token. The catalogue's checks pass.
|
||
|
||
**Proof, live, on one workstation, configuration only.** Assign the module; set the node's role; push.
|
||
The agent's managed directory holds the two files; everything under the person's agent directory is
|
||
byte-identical to before; a new session lists the mesh's tools under `mesh` and answers *which node am
|
||
I* from the managed instruction file. `claude_code_status` answers through the console. No licence is
|
||
touched: the module writes the credentials file only when it is handed a token.
|
||
|
||
## WP3 — The manager's code, built and tested
|
||
|
||
*mesh-catalog. Two to three days.*
|
||
|
||
**What is written**, as design 39 says: the manifest (the seat and its verbs, a database, a `secret`
|
||
for the key the grants are encrypted with, a tools bundle, a process bundle for the daemon, settings
|
||
with defaults); the store's migrations; the refresh with its plan, lease, floor and cadence as pure
|
||
functions; the vendor client from `anthropic-manager`; adoption from a file and from a node's waiting
|
||
login with the identity guard; usage and its threshold; the visit — key, hand-over, waiting login — per
|
||
bound node; the seat's verbs.
|
||
|
||
**Proof, before anything runs live.** Unit tests: two refresh runs started together rotate one grant
|
||
once; a mismatching identity is refused; a worker bound to a dead licence is refused and never lent
|
||
another; nothing the daemon emits carries a token; a hand-over sealed for one node opens with no other
|
||
node's key.
|
||
|
||
## WP4 — The manager live on the control node
|
||
|
||
*The live mesh. Half a day.* **Waits on design 38 WP4c's record** — how a module's own long-running
|
||
process is given a bus credential and its subscriptions — because the daemon must call the agent module
|
||
on every node. Until that record exists, nothing in this plan works around it: no tool container, no
|
||
credential copied by hand.
|
||
|
||
**Order.** Assign the manager on the control node; push. Adopt the API key from a file there. Adopt the
|
||
two subscription grants: a login on a workstation carrying the agent module, collected by the manager's
|
||
visit. Bind each node's agent to a licence.
|
||
|
||
**Proof.** Through the console: `anthropic-licence-manager.licences` lists three licences with identity
|
||
and expiry; within the cadence the audit shows a rotation and a later expiry; a forced `refresh` is
|
||
logged with the vendor's answer.
|
||
|
||
## WP5 — The licence end to end on one workstation
|
||
|
||
*The live mesh. Half a day. The proof of the whole.*
|
||
|
||
**Order.** Record the checksums under the person's agent directory. Bind the workstation to a
|
||
subscription licence. Remove the six predecessor files and the hand-made console entry. Start a session.
|
||
|
||
**Proof.** Everything under the person's agent directory is byte-identical but the credentials file,
|
||
which is owned by the operator, readable by nobody else, and names no refresh token. A session makes a
|
||
model request. `switch` to the second subscription licence changes the token on the workstation within a
|
||
minute, and neither the verb's answer nor either module's log holds a token. Switched to the API key, the
|
||
credentials file is left as it was and the agent authenticates through the key-helper. Switched back.
|
||
|
||
## WP6 — The rest of the nodes, and the predecessor's remains
|
||
|
||
*The live mesh and mesh-catalog. One day.* The module on every node, the predecessor's files removed on
|
||
the second workstation; a login under a licence's account collected and adopted, and one under the wrong
|
||
account refused and notified; `anthropic-manager` and `anthropic-consumer` retired from the catalogue;
|
||
designs 36 and 39 set to `implemented` with the as-is written
|
||
([playbook 02](../../00-META/process/02-graduation.md)).
|
||
|
||
**Proof.** `claude_code_status` answers on every node; the refusal's notification arrived; the catalogue
|
||
has no module built on the old placement.
|
||
|
||
## What is deliberately not here
|
||
|
||
- **The package repository seat** for a distribution that does not carry the agent's package (design 36
|
||
§7). The four machines have the package; a fifth would refuse the module in its package manager's
|
||
words.
|
||
- **Escalation as a checked fact.** The agent module's write under `/etc` relies on the operator
|
||
account's passwordless `sudo`, true on all four and checked by nothing. A machine without it refuses
|
||
the render in the tool's own words; making escalation a reported capability is design 38's to decide.
|
||
- **An automated switch on exhaustion.** The readings are kept from WP4; the policy is a later record.
|
||
- **Workers and the mesh's own sessions as consumers.** The manager knows them from WP3; the consumers do
|
||
not exist yet ([to-be 15](15-the-agent-session.md)).
|
||
- **Whether a refresh token is single-use.** WP4 may measure it; the design holds either way.
|
||
|
||
## How this list is kept true
|
||
|
||
Each package's proof is run when the package is finished and its line here gains the date and the
|
||
commit, as design 38 does. A package whose proof fails is not reworded; the failure is recorded under it
|
||
and the package stays open. When WP2's live proof runs, design 36 moves to `in-progress` with its owning
|
||
repository; when WP5's does, design 39 does too; and when WP6's does, both move to `implemented`, with
|
||
the as-is written.
|