Files
hq/03-DESIGN/01-to-be/40-building-the-operators-agent-and-its-licence-manager.md
T
jochen 8a5dbaeb98 To-be 40 revised for the tools refactor; the manager starts every exchange (ADR 0183 dated note, designs 36 and 39)
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.
2026-10-03 16:01:37 +02:00

209 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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.