--- layer: to-be status: designed code: [] updated: 2026-10-02 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/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) gave the operator's machine, applied to the two modules that make its agent work. ## 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), and design 38's words on the same day). 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: the control node first for the manager, one workstation first for the agent, then the rest. The cost accepted: 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 never in reach of the failure, 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 Counted 2026-10-02 in the repositories and on the machines. Nothing here is new ground; every package reshapes something standing. | Piece | Today | Becomes | |---|---|---| | the vendor's refresh, the sealed box, the grant file | `anthropic-manager` in the catalogue: a token-endpoint client, a sealed-box primitive, adoption of a grant sealed to a node's key; assigned to nothing | the manager's refresh and adoption, with the lease, the floor and the cadence the predecessor's manager had | | the credentials write, the refresh-token strip, the identity read | `anthropic-consumer` in the catalogue: tested; assigned to nothing | the agent module's write, unchanged in shape | | the predecessor's manager and consumer | two modules in the retired system: the lease per licence, the expiry floor, the lineage comparison, the identity guard, three touchpoints with fallbacks, cooldowns on alarms | ported as logic with its tests; nothing of its registry or its bus | | the host's `process` and `archive` shapes | fetch a bundle by digest and run it supervised; fetch and unpack an artifact | **unchanged** — the manager's daemon is one process; both modules' tools are bundles | | the manifest's `uses`, `claims`, `invokes seat:.`, node-scoped `provides` with `serves: {port}` | all four exist and are used by other modules | **unchanged** — the agent uses the seat and invokes its verbs; the console provides its endpoint | | the console | a container per node, MCP on loopback, no provision | gains one provision; becomes the node-tools runtime's serving mode under design 38's WP3 | | the agent's package | present on both workstations from a build the predecessor's helper made; the distribution's repositories do not carry it | declared; satisfied where present, refused where not, until a package repository seat exists | | the operator account | a column on every node record, **empty on all four** | stated by the operator, before anything home-scoped lands | **One dependency decides the order.** Both modules serve tools and the agent module's tools write under `/etc` and, as the operator, under the home. Under [ADR 0175](../../02-DECISIONS/0175-one-tool-runtime-per-node-serves-every-modules-tools-on-the-host-side.md) tools run in the node's tool runtime, host-side, which design 38 builds in its WP1–WP3. Writing a per-module tool container for these two modules would be building the pattern that record retires, so **the live proofs of WP3 to WP5 below wait for design 38's WP3.** Everything before a live proof — manifests, code, tests — does not, and is written now. ## The order the work allows ``` WP0 the operator states the facts (the live mesh) ── accounts, roles, licences to adopt WP1 the console provides its endpoint (mesh-catalog) ── small, independent WP2 the licence manager, built and tested (mesh-catalog) ──┐ independent of each other; WP3 the agent module, built and tested (mesh-catalog) ──┘ both wait on design 38 WP3 to run │ WP4 the manager live on the control node (the live mesh) ── three licences adopted, a refresh seen WP5 the agent live on one workstation (the live mesh) ── the hand-over, the switch, the instructions WP6 the rest of the nodes, and the predecessor's remains ── adoption from a login, the retirements ``` WP1, WP2 and WP3 touch different directories of one repository and meet only at the seat's name and the provision's name; they are built in parallel. WP4 is the first time anything on a machine changes. WP5 is the proof of the whole. ## WP0 — The operator states the facts *The live mesh. An hour, and it is the operator's.* The account on each node record, through the controller's node command — none is stated today, and [ADR 0181](../../02-DECISIONS/0181-the-operator-account-is-a-node-fact-and-a-home-is-a-placement-root.md) refuses a home-scoped module without one. The role of each node, as the agent module's setting on the node layer, once the module exists. Which three licences exist and what each is called. **Proof.** The controller's node command lists an account for every node. ## WP1 — The console provides its endpoint *mesh-catalog. Half a day.* **What changes.** The console's manifest gains a node-scoped provision — working name `console-endpoint`, fixed when the manifest is written — serving the port the machine gave it, as the local model server already does for its API. Co-location resolves it ([ADR 0027](../../02-DECISIONS/0027-a-provision-names-what-the-consumer-is-coupled-to.md), [to-be 34](34-the-console.md) as amended). When design 38's WP3 moves the console into the node-tools module, the provision moves with it; it is a line in a manifest either way. **Proof.** The controller's plan for a workstation shows a consumer of the provision bound to the console's port; the same consumer on a machine without the console is refused naming the provision; the catalogue's tests pass. ## WP2 — The licence manager, built and tested *mesh-catalog. Two to three days; the largest package.* **What is written**, as design 39 says: 1. **The manifest.** Claims the mesh-scoped seat `anthropic-licence-manager` with its verbs; requires a database, a `secret` for the key its grants are encrypted with, and the bus; a `bundle` of tools; a `process` for the daemon that refreshes, collects usage and notifies, on a schedule; declared settings for the cadence, the usage threshold and the cooldown, each with a default; `invokes` the agent module's `apply`. 2. **The store.** Migrations for licences, bindings, usage and audit, with the lease and the notification slot as columns, numbered and idempotent. 3. **The refresh.** The token-endpoint client and the sealed box from `anthropic-manager`; the plan (floor, cadence, forced, cannot) and the lease from the predecessor, as pure functions with their tests; the vendor's reason logged on failure; counted failures, one notification per cooldown. 4. **Adoption.** From a file on the manager's node for the API key; from a sealed grant a node offers; the identity guard that refuses a mismatch and notifies. 5. **Usage.** The vendor's reading per licence on a schedule, stored raw and normalised ([ADR 0054](../../02-DECISIONS/0054-model-usage-is-recorded-at-two-grains.md)), one notification per threshold crossing. 6. **The verbs**: `licences`, `bindings`, `bind`, `switch`, `release`, `refresh`, `usage`, `adopt`, `register`, `current` — the last answering a consumer's token sealed to the key that consumer registered. 7. **The hand-over**: on rotation or switch, one call to `claude-code.apply@` per bound node, the token sealed to that node's key, the answer recorded. **Proof, before anything runs live.** Unit tests: two refresh runs started together rotate one grant once; a grant with a mismatching identity is refused; a worker bound to a dead licence is refused and never lent another; every event the daemon emits is free of a token; the hand-over payload opens only with the registered key. The catalogue's checks: no installation named, no secret in a declared file. ## WP3 — The agent module, built and tested *mesh-catalog. Two days.* **What is written**, as design 36 says: 1. **The manifest.** The agent's package; the state directory; the facts file carrying the node's name, the operator account and its home, the console's bound port, the role and the extra tool servers from settings; requires the console's endpoint and the bus; `uses` the seat and `invokes` its `register`, `current` and `adopt`; a `bundle` of tools. **No file resource under a home or under `/etc`.** 2. **The renderer.** From the facts file and the current binding, the managed settings file (the tool servers under the entry `mesh`, the attribution trailers, and the key-helper for an API-key binding) and the managed instruction file (§3 of design 36), written under the agent's managed directory with the escalation the tool performs for itself; idempotent; re-run when the facts file changes. 3. **The keypair**, made once in the state directory, the public half registered with the seat at start and at every start. 4. **The consumer side**: `apply` (a rotation applied only if newer within one lineage, a switch applied regardless, the answer naming the outcome and never a token); the pull at start and near expiry; the credentials write as the operator, access-token-only, from `anthropic-consumer` with its tests; the key-helper program for the API key; the offer of a login to the seat, sealed, after reading the account's identity. 5. **The tools**: `apply`, `licence_status`, `mcp_configure` (validates a server, sets the module's setting through the controller's settings verb), `render` (re-render now, for a person). 6. **The documentation**: the six predecessor files and the hand-made console entry a person removes on a workstation that carried the predecessor. **Proof, before anything runs live.** Unit tests: the renderer writes only the mesh's keys and leaves every other key of a seeded settings file; the credentials write strips a refresh token and is atomic; the lineage comparison from the predecessor, with its cases; a login offer carries the identity it read. The catalogue's checks pass. ## WP4 — The manager live on the control node *The live mesh. Half a day, after design 38's WP3.* **Order.** Assign the manager on the control node; push. Adopt the API key from a file there. Adopt the two subscription grants: a login in a throwaway home on the control node, offered to the seat the way a node's agent module will. 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 `licences` shows a later expiry; a forced `refresh` on one licence is logged with the vendor's answer; the two retired catalogue modules are still assigned to nothing. ## WP5 — The agent live on one workstation *The live mesh. Half a day. The proof of the whole.* **Order.** Set the workstation's role in the module's settings. Record the checksums of everything under the person's agent directory. Assign the module; push. Remove the six predecessor files and the hand-made console entry. Start a new session. **Proof.** The managed directory holds the settings and instruction files, owned by root. Everything under the person's agent directory is byte-identical to before except the credentials file, which is owned by the operator, readable by nobody else, and names no refresh token. The new session lists the mesh's tools under `mesh` once, answers *which node am I* from the instruction file, and makes a model request. `anthropic-licence-manager.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 licence, 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.* **Order.** Assign the module on the second workstation and on the servers whose account is stated; remove the predecessor's files on the second workstation. Log in on a workstation under a licence's account and watch the offer be adopted — and under the wrong account, and watch it refused and notified. Retire `anthropic-manager` and `anthropic-consumer` from the catalogue. Set designs 36 and 39 to `implemented` for what runs, with the as-is written ([playbook 02](../../00-META/process/02-graduation.md)). **Proof.** Every node with an account runs the module and `licence_status` answers on each; the refused login'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). A fresh node refuses the module in the package manager's words until it exists. - **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's bindings and fallbacks know them from WP2; the consumers themselves do not exist yet ([to-be 15](15-the-agent-session.md), [ADR 0003](../../02-DECISIONS/0003-agents-are-persistent-employees.md)). - **Whether a refresh token is single-use.** WP4 may measure it on a licence deliberately refreshed twice; 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 WP5 is proven, designs 36 and 39 move to `in-progress` with their owning repository, and when WP6 is proven to `implemented`, with the as-is written.