Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e306fcb4c |
@@ -0,0 +1,226 @@
|
||||
---
|
||||
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:<seat>.<verb>`, 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@<node>` 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.
|
||||
Reference in New Issue
Block a user