diff --git a/02-DECISIONS/0181-the-operator-account-is-a-node-fact-and-a-home-is-a-placement-root.md b/02-DECISIONS/0181-the-operator-account-is-a-node-fact-and-a-home-is-a-placement-root.md index 9902909..3dd6848 100644 --- a/02-DECISIONS/0181-the-operator-account-is-a-node-fact-and-a-home-is-a-placement-root.md +++ b/02-DECISIONS/0181-the-operator-account-is-a-node-fact-and-a-home-is-a-placement-root.md @@ -9,6 +9,12 @@ extends: 02-DECISIONS/0112-a-module-definition-names-no-node-mesh-or-path.md # 181. The operator account is a node fact, and a home is a placement root +> **Progressive insight — 2026-10-04.** This record called a resource under a home *home-scoped*, and a +> module that places one a *home-scoped module*. There is no such kind of module +> ([ADR 0173](0173-the-operators-machine-is-the-meshs-and-a-module-is-what-it-declares.md) §2: a module is +> what it declares), so the three places now say *a resource placed under a home* and *a module placing +> files under a home*. What was decided is unchanged. + *Reconstructed. The controller shipped this on 2026-09-27 and [to-be 29](../03-DESIGN/01-to-be/29-a-node-has-operator-accounts.md) recorded it as built without a decision behind it. This record states what was decided, from the code and the design, and adds the @@ -35,7 +41,7 @@ its home; the account and its home are machine facts a definition may name in a and content; a roster file may say it lives under the home, and is then rendered per node, placed under that node's account's home, owned by the account, and left out on a node with no account. On 2026-10-02 **all four nodes of the live mesh carry an empty account**: the fact exists and nobody has -stated it, so no home-scoped resource can land anywhere yet. +stated it, so no resource placed under a home can land anywhere yet. ## Considered Options @@ -68,7 +74,7 @@ account. A definition names the account and its home as machine facts, never as may say it is a home file and is then placed and owned the same way. The controller resolves both at composition, and the host chowns what it creates. -**A node with no account cannot carry a home-scoped resource, and says so.** A roster fact that lives +**A node with no account cannot carry a resource placed under a home, and says so.** A roster fact that lives under the home is left out of that node's declaration rather than written to nowhere. A resource naming the account fact on such a node is refused at composition, naming the fact the machine does not have. A module that writes a person's files is thereby unassignable to a machine with no person on it, which @@ -80,7 +86,7 @@ anything. ## Consequences -- **The operator states the account before any home-scoped module lands.** Today none is stated, so the +- **The operator states the account before any module placing files under a home lands.** Today none is stated, so the first assignment of such a module begins with four node records. - The roster carries each node's account, so a composed ssh configuration logs in as the right person on every machine — the gap that surfaced this, closed by the same fact. diff --git a/02-DECISIONS/0182-inside-a-home-the-mesh-owns-what-it-places-and-holds-the-rest-as-found.md b/02-DECISIONS/0182-inside-a-home-the-mesh-owns-what-it-places-and-holds-the-rest-as-found.md index 358d620..54c9547 100644 --- a/02-DECISIONS/0182-inside-a-home-the-mesh-owns-what-it-places-and-holds-the-rest-as-found.md +++ b/02-DECISIONS/0182-inside-a-home-the-mesh-owns-what-it-places-and-holds-the-rest-as-found.md @@ -9,6 +9,12 @@ extends: 02-DECISIONS/0118-undeclaring-gives-a-unit-back-the-state-it-was-found- # 182. Inside a home, the mesh owns the directory and the files it places, writes into the tool's own files, and holds everything else as found +> **Progressive insight — 2026-10-04.** This record said *a home-scoped module* and *the family of +> home-scoped modules*. There is no such kind of module +> ([ADR 0173](0173-the-operators-machine-is-the-meshs-and-a-module-is-what-it-declares.md) §2), and the rule +> is about a directory under a home, whichever module declares it; the three places now say so. The +> decision, its options and its consequences are unchanged. + ## Context [ADR 0181](0181-the-operator-account-is-a-node-fact-and-a-home-is-a-placement-root.md) lets a module @@ -35,7 +41,7 @@ use tools that no longer exist. Nothing owns them; nothing will ever rewrite or `~/.ssh`: the mesh owns the directory and the files it places; it holds the person's private keys and personal drop-ins as found. That was argued from the lockout `~/.ssh` can cause. The argument here is the same shape with a different stake — the person's work rather than the person's way in — and it has -to hold for every directory the family of home-scoped modules will touch, so it is a rule, not a +to hold for every directory under a home that any module will touch, so it is a rule, not a section. ## Considered Options @@ -52,7 +58,7 @@ section. ## Decision -**A home-scoped module owns the directory it declares: its existence, owner and mode.** The host creates +**A module that declares a directory under a home owns that directory: its existence, owner and mode.** The host creates it if absent, owned by the account, and never removes it while it holds anything ([ADR 0030](0030-data-outlives-the-mesh-that-declared-it.md)). Inside it, every path the module touches is in exactly one of four classes, and **the class is visible in the definition from the shape @@ -105,7 +111,7 @@ finished its definition. | An owned file found with no record is kept once, then written | host tests of ADR 0102's kept-original rule | | Only the declared keys of a written-into file change, and are given back | host tests of ADR 0102: declared keys set, the rest kept, restored when undeclared | | Nothing found is touched | the family's lab check: a machine with a seeded home holding a person's file beside a predecessor's; after apply the person's file is byte-identical, the predecessor's is kept as the original, the mesh's keys are set and the person's keys in the same file remain; after unassign the mesh's files are gone, the keys are restored, the person's files are untouched and the directory stands | -| Every path a home-scoped module touches is classified | a catalogue review rule for this family: each path is a directory, a file, a file written into, a secret-and-step, or absent — the first module written to it is [to-be 36](../03-DESIGN/01-to-be/36-the-operators-agent-on-a-machine.md) | +| Every path a module touches under a home is classified | a catalogue review rule for this family: each path is a directory, a file, a file written into, a secret-and-step, or absent — the first module written to it is [to-be 36](../03-DESIGN/01-to-be/36-the-operators-agent-on-a-machine.md) | ## References diff --git a/03-DESIGN/01-to-be/36-the-operators-agent-on-a-machine.md b/03-DESIGN/01-to-be/36-the-operators-agent-on-a-machine.md index d6527c2..4195067 100644 --- a/03-DESIGN/01-to-be/36-the-operators-agent-on-a-machine.md +++ b/03-DESIGN/01-to-be/36-the-operators-agent-on-a-machine.md @@ -54,8 +54,10 @@ instruction file and the manager's tools: | the console's entry in the agent's user-scope state | the managed settings' tool-server key, from the console's provision (§4) | **The home.** Under [ADR 0182](../../02-DECISIONS/0182-inside-a-home-the-mesh-owns-what-it-places-and-holds-the-rest-as-found.md) -every path under `~/.claude` is *found*, with one exception: the agent's credentials file, which the -module's own code writes for a subscription licence (§5). The person's memory, history, projects, local +the module owns the directory `~/.claude` — that it exists, that the operator owns it, its mode, +`0700` — and declares it, so the mesh refuses a second module owning it. Of what is inside, it owns only +the agent's credentials file, which its own code writes for a subscription licence (§5); every other path +is *found*. The person's memory, history, projects, local settings, their own rules, skills and tool servers are never read or written by the mesh. **The six predecessor files are the operator's to remove, once, on each workstation**; the module's documentation lists them, and until they go the agent reads stale instructions beside the mesh's. @@ -66,7 +68,9 @@ lists them, and until they go the agent reads stale instructions beside the mesh in that directory carrying the node's name and the console's endpoint, and a settings file carrying the role and the extra tool servers, merged from the module's settings layers — the bundle is told the two files' paths, because a bundle's words are paths and constants only (ADR 0192); the bus, the console's provision, and that it uses the `anthropic-licence-manager` seat. -Nothing under the home, nothing under `/etc`. +Two directories, declared so the ownership check sees them: the agent's managed directory under +`/etc`, root's, and `~/.claude` under the operator's home, the operator's. No *file* resource under +either: what is in them is written by the module's code (§2 below) or is the person's. **Written by the module's code**, from the facts file and the manager's hand-over, whenever either changes: @@ -187,7 +191,7 @@ installer is rejected: it puts a self-updating binary under the person's home, i | Check | Defends | |---|---| -| the module's definition names no node, path or login, declares nothing under a home or `/etc`, and no file resource carries a secret | ADR 0112, ADR 0155, ADR 0183 | +| the module's definition names no node, path or login, declares no file under a home or `/etc` (only the two directories), and no file resource carries a secret | ADR 0112, ADR 0155, ADR 0183 | | on a lab machine with an account and a seeded home holding a person's rule file and the predecessor's leftovers: after assign, the managed directory holds the mesh's files, the home is byte-identical except the credentials file, which is owned by the operator and names no refresh token; after unassign, the managed directory's files are gone and the home is untouched | ADR 0182, the host's agnosticism | | on a lab machine with no account, the assignment is refused naming the fact | ADR 0181 | | a switch asked of the seat through the console changes the licence and the token on the node; no tool answer and no log line holds a token | ADR 0183 | diff --git a/03-DESIGN/01-to-be/40-building-the-operators-agent-and-its-licence-manager.md b/03-DESIGN/01-to-be/40-building-the-operators-agent-and-its-licence-manager.md index 0806e71..1f4f4cf 100644 --- a/03-DESIGN/01-to-be/40-building-the-operators-agent-and-its-licence-manager.md +++ b/03-DESIGN/01-to-be/40-building-the-operators-agent-and-its-licence-manager.md @@ -108,8 +108,8 @@ runtime's port; the controller's tests and the catalogue's checks pass. 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`.** + words name the two files, the state directory and nothing else. The two directories it owns declared — the agent's managed + directory and `~/.claude` — and **no file resource under either.** 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