There is no home-scoped module: ADR 0181 and 0182 say so as progressive insights; design 36 and to-be 40: the module declares the two directories it owns

ADR 0173 §2: a module is what it declares, and there are no kinds of module. The two records called
a resource under a home and a module placing one home-scoped; the wording is corrected in place,
marked and dated, the decisions unchanged. Design 36 and to-be 40 now say the module declares
/etc/claude-code and ~/.claude as directories, so the ownership check sees both, and declares no file
under either (mesh-catalog #244).
This commit is contained in:
jochen
2026-10-03 23:50:06 +02:00
parent baf82b1cdb
commit e3755d5b60
4 changed files with 28 additions and 12 deletions
@@ -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 # 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 *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 [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 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 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 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 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 ## 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 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. 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 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. 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 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 ## 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. 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 - 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. on every machine — the gap that surfaced this, closed by the same fact.
@@ -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 # 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 ## Context
[ADR 0181](0181-the-operator-account-is-a-node-fact-and-a-home-is-a-placement-root.md) lets a module [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 `~/.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 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 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. section.
## Considered Options ## Considered Options
@@ -52,7 +58,7 @@ section.
## Decision ## 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 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 ([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 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 | | 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 | | 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 | | 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 ## References
@@ -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 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) **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 the module owns the directory `~/.claude` — that it exists, that the operator owns it, its mode,
module's own code writes for a subscription licence (§5). The person's memory, history, projects, local `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 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 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. 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 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 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. 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 **Written by the module's code**, from the facts file and the manager's hand-over, whenever either
changes: changes:
@@ -187,7 +191,7 @@ installer is rejected: it puts a self-updating binary under the person's home, i
| Check | Defends | | 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 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 | | 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 | | 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 |
@@ -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: 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 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 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 words name the two files, the state directory and nothing else. The two directories it owns declared — the agent's managed
under `/etc`.** 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 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 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 key-helper for an API-key binding) and the managed instruction file, written under the agent's