From 9fafbcfd5842bcc4a62b4b6d05f9fcf840ac56b1 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 5 Nov 2026 14:19:32 +0100 Subject: [PATCH] =?UTF-8?q?The=20seats=20are=20called=20mesh-module-assign?= =?UTF-8?q?er=20and=20mesh-node-enroller=20in=20mesh-cli,=20claude-code,?= =?UTF-8?q?=20the=20checks,=20mesh-config,=20mesh-vault,=20conditions,=20s?= =?UTF-8?q?elf-check=20and=20the=20provisioner=20client=20(ADR=200634=20?= =?UTF-8?q?=C2=A79;=20K-21;=20issue=201966)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- checks/controllerdeps/controllerdeps_test.go | 2 +- checks/noplacement/main.go | 6 ++-- checks/noplacement/main_test.go | 2 +- checks/words/main_test.go | 2 +- .../claude-code/cmd/claude-code/guard_test.go | 6 ++-- .../cmd/claude-code/insteadof_test.go | 16 ++++----- .../cmd/claude-code/instructions.go | 2 +- modules/claude-code/cmd/claude-code/mesh.go | 4 +-- .../testdata/rendered-by-typescript.json | 4 +-- modules/mesh-cli/README.md | 2 +- modules/mesh-cli/cmd/mesh-cli/commands.go | 34 +++++++++---------- modules/mesh-cli/cmd/mesh-cli/enrol.go | 4 +-- modules/mesh-cli/cmd/mesh-cli/main_test.go | 26 +++++++------- .../cmd/mesh-conditions/hold_test.go | 6 ++-- .../cmd/mesh-conditions/keeper.go | 2 +- modules/mesh-config/README.md | 2 +- .../cmd/mesh-config/config_test.go | 2 +- .../mesh-config/cmd/mesh-config/declared.go | 2 +- modules/mesh-config/cmd/mesh-config/main.go | 2 +- .../mesh-config/cmd/mesh-config/resolve.go | 2 +- .../mesh-config/cmd/mesh-config/sources.go | 6 ++-- modules/mesh-provisioner-client/README.md | 4 +-- .../cmd/mesh-provisioner-client/client.go | 8 ++--- .../mesh-provisioner-client/client_test.go | 6 ++-- .../cmd/mesh-self-check/probes_mesh.go | 2 +- .../mesh-vault/cmd/mesh-vault/enrolment.go | 8 ++--- .../cmd/mesh-vault/enrolment_test.go | 2 +- .../cmd/mesh-vault/enrolment_tools.go | 4 +-- modules/mesh-vault/cmd/mesh-vault/main.go | 2 +- modules/mesh-vault/cmd/mesh-vault/placed.go | 4 +-- .../mesh-vault/cmd/mesh-vault/placed_test.go | 2 +- .../cmd/mesh-vault/placementview.go | 2 +- modules/mesh-vault/cmd/mesh-vault/signing.go | 6 ++-- modules/mesh-vault/cmd/mesh-vault/vault.go | 2 +- 34 files changed, 93 insertions(+), 93 deletions(-) diff --git a/checks/controllerdeps/controllerdeps_test.go b/checks/controllerdeps/controllerdeps_test.go index 0a05e0ae0..6565ab9f4 100644 --- a/checks/controllerdeps/controllerdeps_test.go +++ b/checks/controllerdeps/controllerdeps_test.go @@ -39,7 +39,7 @@ func TestRefusalsJudgeATree(t *testing.T) { {"a bucket in a test is its data", map[string]string{"modules/e/cmd/e/main_test.go": "package main\n// mesh-controller_lease\n"}, ""}, {"a fixture copied from elsewhere", map[string]string{"modules/e/cmd/e/testdata/x.md": "mesh-controller_rollouts\n"}, ""}, {"an owner and prose pass", map[string]string{"modules/f/module.json": `{"module":"f","config":{"owners":{"default":["mesh-controller","mesh-controller modules/route-proxy"]}},"why":"the mesh-controller module is gone"}`}, ""}, - {"the seat's successors pass", map[string]string{"modules/g/module.json": `{"module":"g","reads":["mesh-placement.placement"],"invokes":["seat:mesh-hand-acts.hand-act"]}`}, ""}, + {"the seat's successors pass", map[string]string{"modules/g/module.json": `{"module":"g","reads":["mesh-module-assigner.placement"],"invokes":["seat:mesh-hand-acts.hand-act"]}`}, ""}, } { t.Run(row.name, func(t *testing.T) { root := t.TempDir() diff --git a/checks/noplacement/main.go b/checks/noplacement/main.go index 1bcce1995..dbf23bd0a 100644 --- a/checks/noplacement/main.go +++ b/checks/noplacement/main.go @@ -1,6 +1,6 @@ // Command noplacement refuses what the repository path of placement left behind (novox/hq ADR 0567 §10, §12). // -// Placement, which module runs on which node, is bus state held by the seat mesh-placement; no file of the +// Placement, which module runs on which node, is bus state held by the seat mesh-module-assigner; no file of the // catalogue says it, and no manifest reads it from the delivery indexer, which no longer keeps it. It refuses: // // 1. a `placement` directory (or file) at the root of the catalogue; @@ -34,7 +34,7 @@ var Prefixes = []string{"mesh-delivery-indexer.placement", "mesh-delivery-indexe func Findings(root string) ([]string, error) { var out []string if _, err := os.Lstat(filepath.Join(root, "placement")); err == nil { - out = append(out, "placement: the repository holds no placement; it is bus state of the seat mesh-placement (novox/hq ADR 0567 §10)") + out = append(out, "placement: the repository holds no placement; it is bus state of the seat mesh-module-assigner (novox/hq ADR 0567 §10)") } if _, err := os.Lstat(filepath.Join(root, "particulars")); err == nil { out = append(out, "particulars: the repository lists no node names; the checker hands them to the check (novox/hq ADR 0567 §16)") @@ -55,7 +55,7 @@ func Findings(root string) ([]string, error) { } module := filepath.Base(filepath.Dir(file)) for _, s := range named(doc, nil) { - out = append(out, fmt.Sprintf("%s: names %q, which the indexer no longer keeps; placement is the seat mesh-placement's (novox/hq ADR 0567 §12)", module, s)) + out = append(out, fmt.Sprintf("%s: names %q, which the indexer no longer keeps; placement is the seat mesh-module-assigner's (novox/hq ADR 0567 §12)", module, s)) } } sort.Strings(out) diff --git a/checks/noplacement/main_test.go b/checks/noplacement/main_test.go index 0db98f067..e9cfa615c 100644 --- a/checks/noplacement/main_test.go +++ b/checks/noplacement/main_test.go @@ -19,7 +19,7 @@ func TestFindingsRefuseWhatThePlacementPathLeft(t *testing.T) { {"a read of the indexer's placement", map[string]string{"modules/a/module.json": `{"module":"a","reads":["mesh-delivery-indexer.placement"]}`}, `a: names "mesh-delivery-indexer.placement"`}, {"a read of its candidates", map[string]string{"modules/b/module.json": `{"module":"b","reads":["mesh-delivery-indexer.placement-candidates"]}`}, "placement-candidates"}, {"its event", map[string]string{"modules/c/module.json": `{"module":"c","on":[{"event":"mesh-delivery-indexer.placement-changed"}]}`}, "placement-changed"}, - {"the seat's own state is allowed", map[string]string{"modules/d/module.json": `{"module":"d","reads":["mesh-placement.placement"]}`}, ""}, + {"the seat's own state is allowed", map[string]string{"modules/d/module.json": `{"module":"d","reads":["mesh-module-assigner.placement"]}`}, ""}, } { t.Run(row.name, func(t *testing.T) { root := t.TempDir() diff --git a/checks/words/main_test.go b/checks/words/main_test.go index 2f05f0ed1..82b5f781a 100644 --- a/checks/words/main_test.go +++ b/checks/words/main_test.go @@ -109,7 +109,7 @@ func TestCheckAddressesRefusesTheControllersAddresses(t *testing.T) { {"`mesh-controller.`", true}, {"the mesh-controller module is gone.", false}, {"located in mesh-controller#246", false}, - {"ask mesh-placement.placement", false}, + {"ask mesh-module-assigner.placement", false}, } { got := checkAddresses([]text{{file: "m/a.go", line: 1, s: c.s}}) if (len(got) == 1) != c.want { diff --git a/modules/claude-code/cmd/claude-code/guard_test.go b/modules/claude-code/cmd/claude-code/guard_test.go index 7acf464d2..152c4c18d 100644 --- a/modules/claude-code/cmd/claude-code/guard_test.go +++ b/modules/claude-code/cmd/claude-code/guard_test.go @@ -16,7 +16,7 @@ import ( // seats' contract and the modules' manifests say them. func meshForTheGuard() GuardData { defined := []seats.Seat{ - {Name: "mesh-placement", Scope: "mesh", Serves: []seats.Verb{ + {Name: "mesh-module-assigner", Scope: "mesh", Serves: []seats.Verb{ {Name: "placement", Description: "Read placement: one node's key.", Replaces: []string{"hostnamectl", "uptime"}}}}, {Name: "node-service-manager", Scope: "node", Serves: []seats.Verb{ {Name: "status", Description: "One unit as the service manager sees it now: its states.", Replaces: []string{"systemctl status", "systemctl is-active"}}, @@ -80,14 +80,14 @@ func TestSSHToAMeshMachineIsRefusedNamingTheTool(t *testing.T) { "ssh -o StrictHostKeyChecking=no 10.10.0.1 docker ps -a": "anchor/docker.docker_list", "ssh anchor docker logs --tail 100 nats": "anchor/docker.docker_logs", "ssh laptop docker logs x": "anchor/docker.docker_logs", - "ssh a uptime": "mesh-placement.placement", + "ssh a uptime": "mesh-module-assigner.placement", "cd /tmp && ssh anchor journalctl": "anchor/node-service-manager.journal", "sudo -u root ssh anchor journalctl": "anchor/node-service-manager.journal", "timeout 10 ssh anchor journalctl": "anchor/node-service-manager.journal", "env LANG=C ssh anchor journalctl": "anchor/node-service-manager.journal", "bash -c 'ssh anchor journalctl -u x'": "anchor/node-service-manager.journal", `echo "$(ssh anchor journalctl -n 5)" | tail`: "anchor/node-service-manager.journal", - "for n in anchor laptop; do ssh $n uptime; done; ssh anchor uptime": "mesh-placement.placement", + "for n in anchor laptop; do ssh $n uptime; done; ssh anchor uptime": "mesh-module-assigner.placement", "ssh -J anchor 203.0.113.9 journalctl": "anchor/node-service-manager.journal", "ssh via-anchor journalctl": "anchor/node-service-manager.journal", "ssh nas.lan journalctl": "anchor/node-service-manager.journal", diff --git a/modules/claude-code/cmd/claude-code/insteadof_test.go b/modules/claude-code/cmd/claude-code/insteadof_test.go index 8e5815001..6d67609ab 100644 --- a/modules/claude-code/cmd/claude-code/insteadof_test.go +++ b/modules/claude-code/cmd/claude-code/insteadof_test.go @@ -39,7 +39,7 @@ func (b aBus) Get(read, key string) ([]byte, bool, error) { // someSeats are two seats as the seats' contract says them: one held once for the mesh, one on every machine. func someSeats() []seats.Seat { return []seats.Seat{ - {Name: "mesh-placement", Scope: "mesh", Serves: []seats.Verb{ + {Name: "mesh-module-assigner", Scope: "mesh", Serves: []seats.Verb{ {Name: "placement", Description: "Read placement: one node's key.", Replaces: []string{"hostnamectl", "uptime"}}, {Name: "propose", Description: "Propose a change."}}}, {Name: "node-service-manager", Scope: "node", Serves: []seats.Verb{ @@ -49,7 +49,7 @@ func someSeats() []seats.Seat { } // aMesh is two machines, anchor (with a public domain) and laptop, docker and zsh placed on anchor, docker's manifest -// saying what its tool replaces, as the seat mesh-placement and the indexer keep them on the bus. +// saying what its tool replaces, as the seat mesh-module-assigner and the indexer keep them on the bus. func aMesh(t *testing.T) aBus { t.Helper() b := aBus{PlacementRead: {}, ModulesRead: {}, ManifestsRead: {}} @@ -100,7 +100,7 @@ func TestTheMeshsToolsAreReadFromTheBus(t *testing.T) { for _, r := range m.Replacements { addresses = append(addresses, r.Address) } - if got := strings.Join(addresses, ","); got != "mesh-placement.placement,node-service-manager.status,node-service-manager.journal,docker.docker_logs" { + if got := strings.Join(addresses, ","); got != "mesh-module-assigner.placement,node-service-manager.status,node-service-manager.journal,docker.docker_logs" { t.Errorf("replacements: %s", got) } if len(m.Machines) != 2 || strings.Join(m.Machines[0].Domains, ",") != "anchor.internal,anchor.example" || @@ -120,7 +120,7 @@ func TestTheInsteadOfTableIsGeneratedFromTheRecords(t *testing.T) { for _, want := range []string{ "| `/node-service-manager.` | `status` — `systemctl status`, `systemctl is-active` · `journal` — `journalctl` |", "| `/docker.` | `docker_logs` — `docker logs` |", - "| `mesh-placement.` | `placement` — `hostnamectl`, `uptime` |", + "| `mesh-module-assigner.` | `placement` — `hostnamectl`, `uptime` |", "Never `ssh` to a mesh machine", } { if !strings.Contains(table, want) { @@ -128,14 +128,14 @@ func TestTheInsteadOfTableIsGeneratedFromTheRecords(t *testing.T) { } } if strings.Index(table, "node-service-manager.") > strings.Index(table, "docker.") || - strings.Index(table, "docker.") > strings.Index(table, "`mesh-placement.`") { + strings.Index(table, "docker.") > strings.Index(table, "`mesh-module-assigner.`") { t.Errorf("not the machines' seats, then modules, then the mesh's:\n%s", table) } // What the guard here named most comes first: its row, and in its row its verb. - m.Refused = map[string]int{"node-service-manager.journal": 3, "mesh-placement.placement": 1} + m.Refused = map[string]int{"node-service-manager.journal": 3, "mesh-module-assigner.placement": 1} ranked := InsteadOf(&m) if !strings.Contains(ranked, "| `/node-service-manager.` | `journal` — `journalctl` · `status`") || - strings.Index(ranked, "`mesh-placement.`") > strings.Index(ranked, "`/docker.`") { + strings.Index(ranked, "`mesh-module-assigner.`") > strings.Index(ranked, "`/docker.`") { t.Errorf("not ranked by the guard's record:\n%s", ranked) } m.Refused = nil @@ -182,7 +182,7 @@ func TestTheMeshsToolsAreKeptOnlyWhenTheyChange(t *testing.T) { } } -// Where a module runs is read from the seat mesh-placement's placement (issue 1126 B13), never the controller's answer. +// Where a module runs is read from the seat mesh-module-assigner's placement (issue 1126 B13), never the controller's answer. func TestTheMachinesRunningAModuleAreReadFromPlacement(t *testing.T) { b := aMesh(t) if got, err := NodesRunning(b, "zsh"); err != nil || strings.Join(got, ",") != "anchor" { diff --git a/modules/claude-code/cmd/claude-code/instructions.go b/modules/claude-code/cmd/claude-code/instructions.go index 0fc2eb1a4..678d9e40a 100644 --- a/modules/claude-code/cmd/claude-code/instructions.go +++ b/modules/claude-code/cmd/claude-code/instructions.go @@ -9,5 +9,5 @@ func instructionsText(node, role string) string { node + "`\n- **Role:** " + role + - "\n- The other nodes, their roles and what runs where: ask the placement seat (`mesh-placement.placement`),\n or `mesh_overview` and `mesh_machine`. Nothing here lists them, because a copy drifts.\n\n## How a session on this mesh works\n\nThe console is the only way to the mesh: the MCP server named `mesh`. It offers five tools, and\neverything else is an address you find and call through them:\n\n- `mesh_search` — words in, matching addresses out. `mesh_describe` — one address's arguments.\n- `mesh_call` — call an address. A seat the mesh holds once is `.` (the mesh's own seats\n include `mesh-placement`, `mesh-delivery`, `mesh-config` and `mesh-conditions`);\n a module on a machine is `/.`.\n- `mesh_overview` and `mesh_machine` — the mesh's seats and machines, and what one machine runs.\n\n- **Symptom first.** For an error, a failing service or anything unexpected, search the record with the\n literal text before forming a hypothesis: the records module's `records_search`, then\n `records_read`.\n- **Ask the mesh before changing it**, and change it through the seats' verbs or the catalog.\n- **A licence** through the `anthropic-licence-manager` seat's verbs. Never edit the agent's credentials\n file by hand, never print or ask for a token.\n\n## Hard rules\n\n- A file the mesh manages is changed through the verb or the catalog that owns it, never on disk. If\n unsure, `/node-engine.composition` for the module says what the mesh writes there.\n- Never write to a store's database by hand; schema changes are numbered migrations.\n- Never push to a main branch: a branch, a pull request, and a human approval for every merge.\n- The mesh creates no symlinks, and nobody else does either.\n- A package is declared in a module, never installed by hand.\n\n## Conventions\n\n- Commit messages are concise, in the imperative, about why.\n- Test before pushing: nodes update unattended.\n- The playbooks in the record say how research, decisions, designs, issues and hand-offs are done.\n" + "\n- The other nodes, their roles and what runs where: ask the placement seat (`mesh-module-assigner.placement`),\n or `mesh_overview` and `mesh_machine`. Nothing here lists them, because a copy drifts.\n\n## How a session on this mesh works\n\nThe console is the only way to the mesh: the MCP server named `mesh`. It offers five tools, and\neverything else is an address you find and call through them:\n\n- `mesh_search` — words in, matching addresses out. `mesh_describe` — one address's arguments.\n- `mesh_call` — call an address. A seat the mesh holds once is `.` (the mesh's own seats\n include `mesh-module-assigner`, `mesh-delivery`, `mesh-config` and `mesh-conditions`);\n a module on a machine is `/.`.\n- `mesh_overview` and `mesh_machine` — the mesh's seats and machines, and what one machine runs.\n\n- **Symptom first.** For an error, a failing service or anything unexpected, search the record with the\n literal text before forming a hypothesis: the records module's `records_search`, then\n `records_read`.\n- **Ask the mesh before changing it**, and change it through the seats' verbs or the catalog.\n- **A licence** through the `anthropic-licence-manager` seat's verbs. Never edit the agent's credentials\n file by hand, never print or ask for a token.\n\n## Hard rules\n\n- A file the mesh manages is changed through the verb or the catalog that owns it, never on disk. If\n unsure, `/node-engine.composition` for the module says what the mesh writes there.\n- Never write to a store's database by hand; schema changes are numbered migrations.\n- Never push to a main branch: a branch, a pull request, and a human approval for every merge.\n- The mesh creates no symlinks, and nobody else does either.\n- A package is declared in a module, never installed by hand.\n\n## Conventions\n\n- Commit messages are concise, in the imperative, about why.\n- Test before pushing: nodes update unattended.\n- The playbooks in the record say how research, decisions, designs, issues and hand-offs are done.\n" } diff --git a/modules/claude-code/cmd/claude-code/mesh.go b/modules/claude-code/cmd/claude-code/mesh.go index 380cf1366..fd1d6df00 100644 --- a/modules/claude-code/cmd/claude-code/mesh.go +++ b/modules/claude-code/cmd/claude-code/mesh.go @@ -7,7 +7,7 @@ package main // Read from the bus at start and every few minutes (issue 1126 B13; the controller that answered this before is // not placed, novox/hq ADR 0590): the seats' verbs from the seats' contract (mesh-contracts), the modules' // own tools from the manifests the indexer keeps (`mesh-delivery-indexer.modules` and `.manifests`), and the -// machines and where each module runs from the seat mesh-placement's `placement`. Kept in the module's state so +// machines and where each module runs from the seat mesh-module-assigner's `placement`. Kept in the module's state so // a render never waits for the bus, and rendered whenever it changes. Nothing here is written by hand: a verb // that gains a `replaces` is in the next render's table and the guard's next refusal. @@ -104,7 +104,7 @@ type ModuleTools struct { Replaces map[string][]string } -// placements is every node's placement, from the seat mesh-placement's state. +// placements is every node's placement, from the seat mesh-module-assigner's state. func placements(st States) (map[string]delivery.Placement, error) { keys, err := st.Keys(PlacementRead) if err != nil { diff --git a/modules/claude-code/cmd/claude-code/testdata/rendered-by-typescript.json b/modules/claude-code/cmd/claude-code/testdata/rendered-by-typescript.json index 76bab54b4..fdf0b29ef 100644 --- a/modules/claude-code/cmd/claude-code/testdata/rendered-by-typescript.json +++ b/modules/claude-code/cmd/claude-code/testdata/rendered-by-typescript.json @@ -32,11 +32,11 @@ "withKey": { "managed-mcp.json": "{\n \"mcpServers\": {\n \"anton\": {\n \"type\": \"stdio\",\n \"command\": \"node\",\n \"args\": [\n \"/a/b.js\"\n ],\n \"env\": {}\n },\n \"docs\": {\n \"type\": \"stdio\",\n \"command\": \"docs-mcp\",\n \"args\": [\n \"--x\"\n ]\n },\n \"mesh\": {\n \"type\": \"http\",\n \"url\": \"http://127.0.0.1:4270/mcp\"\n },\n \"search\": {\n \"type\": \"http\",\n \"url\": \"https://s.example/mcp\"\n }\n }\n}\n", "managed-settings.json": "{\n \"attribution\": {\n \"commit\": \"\",\n \"pr\": \"\"\n },\n \"allowAllClaudeAiMcps\": true,\n \"apiKeyHelper\": \"/state/api-key-helper\"\n}\n", - "CLAUDE.md": "# This machine is a node of a Novox mesh\n\nWritten by the mesh's `claude-code` module. Edit the module's settings or the catalog, never this file:\nit is rewritten whenever the module renders.\n\n## Who this node is\n\n- **Node:** `workstation`\n- **Role:** the laptop\n- The other nodes, their roles and what runs where: ask the placement seat (`mesh-placement.placement`),\n or `mesh_overview` and `mesh_machine`. Nothing here lists them, because a copy drifts.\n\n## How a session on this mesh works\n\nThe console is the only way to the mesh: the MCP server named `mesh`. It offers five tools, and\neverything else is an address you find and call through them:\n\n- `mesh_search` — words in, matching addresses out. `mesh_describe` — one address's arguments.\n- `mesh_call` — call an address. A seat the mesh holds once is `.` (the mesh's own seats\n include `mesh-placement`, `mesh-delivery`, `mesh-config` and `mesh-conditions`);\n a module on a machine is `/.`.\n- `mesh_overview` and `mesh_machine` — the mesh's seats and machines, and what one machine runs.\n\n- **Symptom first.** For an error, a failing service or anything unexpected, search the record with the\n literal text before forming a hypothesis: the records module's `records_search`, then\n `records_read`.\n- **Ask the mesh before changing it**, and change it through the seats' verbs or the catalog.\n- **A licence** through the `anthropic-licence-manager` seat's verbs. Never edit the agent's credentials\n file by hand, never print or ask for a token.\n\n## Hard rules\n\n- A file the mesh manages is changed through the verb or the catalog that owns it, never on disk. If\n unsure, `/node-engine.composition` for the module says what the mesh writes there.\n- Never write to a store's database by hand; schema changes are numbered migrations.\n- Never push to a main branch: a branch, a pull request, and a human approval for every merge.\n- The mesh creates no symlinks, and nobody else does either.\n- A package is declared in a module, never installed by hand.\n\n## Conventions\n\n- Commit messages are concise, in the imperative, about why.\n- Test before pushing: nodes update unattended.\n- The playbooks in the record say how research, decisions, designs, issues and hand-offs are done.\n" + "CLAUDE.md": "# This machine is a node of a Novox mesh\n\nWritten by the mesh's `claude-code` module. Edit the module's settings or the catalog, never this file:\nit is rewritten whenever the module renders.\n\n## Who this node is\n\n- **Node:** `workstation`\n- **Role:** the laptop\n- The other nodes, their roles and what runs where: ask the placement seat (`mesh-module-assigner.placement`),\n or `mesh_overview` and `mesh_machine`. Nothing here lists them, because a copy drifts.\n\n## How a session on this mesh works\n\nThe console is the only way to the mesh: the MCP server named `mesh`. It offers five tools, and\neverything else is an address you find and call through them:\n\n- `mesh_search` — words in, matching addresses out. `mesh_describe` — one address's arguments.\n- `mesh_call` — call an address. A seat the mesh holds once is `.` (the mesh's own seats\n include `mesh-module-assigner`, `mesh-delivery`, `mesh-config` and `mesh-conditions`);\n a module on a machine is `/.`.\n- `mesh_overview` and `mesh_machine` — the mesh's seats and machines, and what one machine runs.\n\n- **Symptom first.** For an error, a failing service or anything unexpected, search the record with the\n literal text before forming a hypothesis: the records module's `records_search`, then\n `records_read`.\n- **Ask the mesh before changing it**, and change it through the seats' verbs or the catalog.\n- **A licence** through the `anthropic-licence-manager` seat's verbs. Never edit the agent's credentials\n file by hand, never print or ask for a token.\n\n## Hard rules\n\n- A file the mesh manages is changed through the verb or the catalog that owns it, never on disk. If\n unsure, `/node-engine.composition` for the module says what the mesh writes there.\n- Never write to a store's database by hand; schema changes are numbered migrations.\n- Never push to a main branch: a branch, a pull request, and a human approval for every merge.\n- The mesh creates no symlinks, and nobody else does either.\n- A package is declared in a module, never installed by hand.\n\n## Conventions\n\n- Commit messages are concise, in the imperative, about why.\n- Test before pushing: nodes update unattended.\n- The playbooks in the record say how research, decisions, designs, issues and hand-offs are done.\n" }, "plain": { "managed-mcp.json": "{\n \"mcpServers\": {\n \"mesh\": {\n \"type\": \"http\",\n \"url\": \"http://127.0.0.1:4270/mcp\"\n }\n }\n}\n", "managed-settings.json": "{\n \"attribution\": {\n \"commit\": \"\",\n \"pr\": \"\"\n },\n \"allowAllClaudeAiMcps\": true\n}\n", - "CLAUDE.md": "# This machine is a node of a Novox mesh\n\nWritten by the mesh's `claude-code` module. Edit the module's settings or the catalog, never this file:\nit is rewritten whenever the module renders.\n\n## Who this node is\n\n- **Node:** `workstation`\n- **Role:** not stated — set it in this module's settings for the node\n- The other nodes, their roles and what runs where: ask the placement seat (`mesh-placement.placement`),\n or `mesh_overview` and `mesh_machine`. Nothing here lists them, because a copy drifts.\n\n## How a session on this mesh works\n\nThe console is the only way to the mesh: the MCP server named `mesh`. It offers five tools, and\neverything else is an address you find and call through them:\n\n- `mesh_search` — words in, matching addresses out. `mesh_describe` — one address's arguments.\n- `mesh_call` — call an address. A seat the mesh holds once is `.` (the mesh's own seats\n include `mesh-placement`, `mesh-delivery`, `mesh-config` and `mesh-conditions`);\n a module on a machine is `/.`.\n- `mesh_overview` and `mesh_machine` — the mesh's seats and machines, and what one machine runs.\n\n- **Symptom first.** For an error, a failing service or anything unexpected, search the record with the\n literal text before forming a hypothesis: the records module's `records_search`, then\n `records_read`.\n- **Ask the mesh before changing it**, and change it through the seats' verbs or the catalog.\n- **A licence** through the `anthropic-licence-manager` seat's verbs. Never edit the agent's credentials\n file by hand, never print or ask for a token.\n\n## Hard rules\n\n- A file the mesh manages is changed through the verb or the catalog that owns it, never on disk. If\n unsure, `/node-engine.composition` for the module says what the mesh writes there.\n- Never write to a store's database by hand; schema changes are numbered migrations.\n- Never push to a main branch: a branch, a pull request, and a human approval for every merge.\n- The mesh creates no symlinks, and nobody else does either.\n- A package is declared in a module, never installed by hand.\n\n## Conventions\n\n- Commit messages are concise, in the imperative, about why.\n- Test before pushing: nodes update unattended.\n- The playbooks in the record say how research, decisions, designs, issues and hand-offs are done.\n" + "CLAUDE.md": "# This machine is a node of a Novox mesh\n\nWritten by the mesh's `claude-code` module. Edit the module's settings or the catalog, never this file:\nit is rewritten whenever the module renders.\n\n## Who this node is\n\n- **Node:** `workstation`\n- **Role:** not stated — set it in this module's settings for the node\n- The other nodes, their roles and what runs where: ask the placement seat (`mesh-module-assigner.placement`),\n or `mesh_overview` and `mesh_machine`. Nothing here lists them, because a copy drifts.\n\n## How a session on this mesh works\n\nThe console is the only way to the mesh: the MCP server named `mesh`. It offers five tools, and\neverything else is an address you find and call through them:\n\n- `mesh_search` — words in, matching addresses out. `mesh_describe` — one address's arguments.\n- `mesh_call` — call an address. A seat the mesh holds once is `.` (the mesh's own seats\n include `mesh-module-assigner`, `mesh-delivery`, `mesh-config` and `mesh-conditions`);\n a module on a machine is `/.`.\n- `mesh_overview` and `mesh_machine` — the mesh's seats and machines, and what one machine runs.\n\n- **Symptom first.** For an error, a failing service or anything unexpected, search the record with the\n literal text before forming a hypothesis: the records module's `records_search`, then\n `records_read`.\n- **Ask the mesh before changing it**, and change it through the seats' verbs or the catalog.\n- **A licence** through the `anthropic-licence-manager` seat's verbs. Never edit the agent's credentials\n file by hand, never print or ask for a token.\n\n## Hard rules\n\n- A file the mesh manages is changed through the verb or the catalog that owns it, never on disk. If\n unsure, `/node-engine.composition` for the module says what the mesh writes there.\n- Never write to a store's database by hand; schema changes are numbered migrations.\n- Never push to a main branch: a branch, a pull request, and a human approval for every merge.\n- The mesh creates no symlinks, and nobody else does either.\n- A package is declared in a module, never installed by hand.\n\n## Conventions\n\n- Commit messages are concise, in the imperative, about why.\n- Test before pushing: nodes update unattended.\n- The playbooks in the record say how research, decisions, designs, issues and hand-offs are done.\n" } } \ No newline at end of file diff --git a/modules/mesh-cli/README.md b/modules/mesh-cli/README.md index 2bb2687b8..770586666 100644 --- a/modules/mesh-cli/README.md +++ b/modules/mesh-cli/README.md @@ -34,7 +34,7 @@ puts the call on the bus, as every agent session on the machine does. The consol `/etc/mesh-cli/console`, or `MESH_CONSOLE` when set, or node-tools' declared port when the file is not there yet. - **Who judges.** The seat that owns the job: a change of placement is a proposal the operator approves - (`mesh-placement.propose`), a config value is set with its why (`mesh-config.config`), a silence or a hand act is + (`mesh-module-assigner.propose`), a config value is set with its why (`mesh-config.config`), a silence or a hand act is recorded as one. Until novox/hq issue 1126 the controller ran these lines and judged the account (ADR 0272); with the controller unassigned, that judgement went with it. - **The map.** Every line the controller ran, and the seat verb or tool that does its job now, or none, is diff --git a/modules/mesh-cli/cmd/mesh-cli/commands.go b/modules/mesh-cli/cmd/mesh-cli/commands.go index 93f564057..97ca602f8 100644 --- a/modules/mesh-cli/cmd/mesh-cli/commands.go +++ b/modules/mesh-cli/cmd/mesh-cli/commands.go @@ -111,17 +111,17 @@ var commands = []command{ // What runs where. {words: []string{"status"}, does: "what is wrong, what is quiet, what is moving (the delivery view)", build: fixed("mesh-delivery-view.view_status")}, - {words: []string{"nodes"}, does: "the nodes placement holds", build: fixed("mesh-placement.placement"), + {words: []string{"nodes"}, does: "the nodes placement holds", build: fixed("mesh-module-assigner.placement"), render: renderNodes}, - {words: []string{"node", "list"}, does: "the nodes placement holds", build: fixed("mesh-placement.placement"), + {words: []string{"node", "list"}, does: "the nodes placement holds", build: fixed("mesh-module-assigner.placement"), render: renderNodes}, {words: []string{"node", "show"}, usage: "", does: "one node's placement: what it runs and its decided fields", - build: nodeArg("mesh-placement.placement")}, + build: nodeArg("mesh-module-assigner.placement")}, {words: []string{"node", "public-domain"}, usage: " [ | --clear] [--why ]", does: "the domain a node composes its routed names under; with a domain or --clear, proposed to placement", allowed: []string{"clear", "why"}, build: publicDomain}, - {words: []string{"node", "add"}, instead: "a new machine joins through the seat mesh-enrolment: nox enrol issue --why "}, - {words: []string{"node", "networks"}, instead: "no seat keeps a node's routed networks yet; mesh-placement.placement shows what a node decides"}, + {words: []string{"node", "add"}, instead: "a new machine joins through the seat mesh-node-enroller: nox enrol issue --why "}, + {words: []string{"node", "networks"}, instead: "no seat keeps a node's routed networks yet; mesh-module-assigner.placement shows what a node decides"}, {words: []string{"plan"}, usage: "", does: "what the assigner wants the node to run", build: optNode("mesh-delivery-view.assigner_wants")}, {words: []string{"haves"}, usage: "[]", does: "what each node runs, as its node-engine said", build: optNode("mesh-delivery-view.node_haves")}, {words: []string{"switch"}, does: "what each node runs, as its node-engine said", build: fixed("mesh-delivery-view.node_haves")}, @@ -133,9 +133,9 @@ var commands = []command{ return call{l.pos[0] + "/node-engine.composition", map[string]any{"module": l.pos[1]}}, nil }}, {words: []string{"seats"}, does: "who holds each seat, and where", build: func(line) (call, error) { - return call{"mesh-placement.placement", map[string]any{"seats": "true"}}, nil + return call{"mesh-module-assigner.placement", map[string]any{"seats": "true"}}, nil }}, - {words: []string{"seat"}, instead: "a seat is held by placing its module: nox assign --why (mesh-placement.propose)"}, + {words: []string{"seat"}, instead: "a seat is held by placing its module: nox assign --why (mesh-module-assigner.propose)"}, {words: []string{"assign"}, usage: " ... --why ", does: "propose placing modules on a node", allowed: []string{"why"}, build: placeModules("place")}, {words: []string{"unassign"}, usage: " ... --why ", does: "propose taking modules off a node", @@ -155,9 +155,9 @@ var commands = []command{ } return propose(l, map[string]any{"op": "unpin", "node": l.pos[0], "provision": l.pos[1]}) }}, - {words: []string{"proposals"}, usage: "[]", does: "the open proposals of placement", build: optArg("mesh-placement.proposals", "id")}, - {words: []string{"overlay", "show"}, does: "every node's placement, with its tunnel", build: fixed("mesh-placement.placement")}, - {words: []string{"overlay"}, instead: "a node's tunnel is a decided field of its placement: mesh-placement.propose with op decide"}, + {words: []string{"proposals"}, usage: "[]", does: "the open proposals of placement", build: optArg("mesh-module-assigner.proposals", "id")}, + {words: []string{"overlay", "show"}, does: "every node's placement, with its tunnel", build: fixed("mesh-module-assigner.placement")}, + {words: []string{"overlay"}, instead: "a node's tunnel is a decided field of its placement: mesh-module-assigner.propose with op decide"}, // Deliveries and builds. {words: []string{"deliveries"}, usage: "[--state s] [--repository owner/repo] [--group g] [--all]", @@ -458,7 +458,7 @@ var commands = []command{ return call{"knowledge-base.progress", a}, nil }}, - // Enrolment (the seat mesh-enrolment; `enrol open` is local, in main.go). + // Enrolment (the seat mesh-node-enroller; `enrol open` is local, in main.go). {words: []string{"enrol", "issue"}, usage: " --why [--expires 1h]", does: "a one-time token for a new machine, on the operator's Approve", allowed: []string{"why", "expires"}, build: enrolIssue}, {words: []string{"token", "issue"}, usage: "--new --why ", does: "the same as nox enrol issue", @@ -472,15 +472,15 @@ var commands = []command{ } return enrolIssue(l) }}, - {words: []string{"enrol", "tokens"}, usage: "[]", does: "every open enrolment, or one", build: optArg("mesh-enrolment.tokens", "node")}, + {words: []string{"enrol", "tokens"}, usage: "[]", does: "every open enrolment, or one", build: optArg("mesh-node-enroller.tokens", "node")}, {words: []string{"enrol", "revoke"}, usage: " --why ", does: "end an enrolment at any stage", allowed: []string{"why"}, build: func(l line) (call, error) { if len(l.pos) != 1 || !l.has("why") { return call{}, usageErr("give the node and --why") } - return call{"mesh-enrolment.revoke", map[string]any{"node": l.pos[0], "why": l.flags["why"]}}, nil + return call{"mesh-node-enroller.revoke", map[string]any{"node": l.pos[0], "why": l.flags["why"]}}, nil }}, - {words: []string{"enrol", "again"}, usage: "", does: "raise an enrolment's ask again", build: needArg("mesh-enrolment.again", "node")}, + {words: []string{"enrol", "again"}, usage: "", does: "raise an enrolment's ask again", build: needArg("mesh-node-enroller.again", "node")}, // Any address. {words: []string{"call"}, usage: "
[]", does: "call any seat verb or module tool, e.g. ace/node-service-manager.status", @@ -630,7 +630,7 @@ func propose(l line, changes ...map[string]any) (call, error) { for i, c := range changes { list[i] = c } - return call{"mesh-placement.propose", map[string]any{"why": l.flags["why"], "changes": list}}, nil + return call{"mesh-module-assigner.propose", map[string]any{"why": l.flags["why"], "changes": list}}, nil } func placeModules(op string) func(line) (call, error) { @@ -649,7 +649,7 @@ func placeModules(op string) func(line) (call, error) { func publicDomain(l line) (call, error) { switch { case len(l.pos) == 1 && !l.has("clear"): - return call{"mesh-placement.placement", map[string]any{"node": l.pos[0]}}, nil + return call{"mesh-module-assigner.placement", map[string]any{"node": l.pos[0]}}, nil case len(l.pos) == 1: return propose(l, map[string]any{"op": "decide", "node": l.pos[0], "field": "public-domain", "value": nil}) case len(l.pos) == 2 && !l.has("clear"): @@ -705,7 +705,7 @@ func enrolIssue(l line) (call, error) { } a := pick(l, "why", "expires") a["node"] = l.pos[0] - return call{"mesh-enrolment.issue", a}, nil + return call{"mesh-node-enroller.issue", a}, nil } func addressCall(address string, rest []string) (call, error) { diff --git a/modules/mesh-cli/cmd/mesh-cli/enrol.go b/modules/mesh-cli/cmd/mesh-cli/enrol.go index b18a81c82..b04e59a25 100644 --- a/modules/mesh-cli/cmd/mesh-cli/enrol.go +++ b/modules/mesh-cli/cmd/mesh-cli/enrol.go @@ -2,7 +2,7 @@ package main // `nox enrol open`: the operator opens an enrolment token at their own terminal (novox/hq ADR 0587 §6, §8). // -// The seat mesh-enrolment's `tokens` answers the token sealed to the operator key, which only the operator's private key +// The seat mesh-node-enroller's `tokens` answers the token sealed to the operator key, which only the operator's private key // opens; the mesh never holds it. This subcommand is local: it asks nothing of the node-engine's socket and nothing of // the controller or the bus. It reads the sealed token (the base64 of the sealed box) on standard input and the private // key from a file (`--key`, the raw X25519 key in base64 that `operator key make` wrote), opens the box, and prints the @@ -22,7 +22,7 @@ import ( const enrolUsage = `nox enrol open --key -Opens an enrolment token sealed to the operator key (the answer of the seat mesh-enrolment's tokens) and prints the token +Opens an enrolment token sealed to the operator key (the answer of the seat mesh-node-enroller's tokens) and prints the token to type on the new machine. The sealed token is read on standard input; this runs here and asks nothing of the mesh. ` diff --git a/modules/mesh-cli/cmd/mesh-cli/main_test.go b/modules/mesh-cli/cmd/mesh-cli/main_test.go index 3caa08979..e33e212ff 100644 --- a/modules/mesh-cli/cmd/mesh-cli/main_test.go +++ b/modules/mesh-cli/cmd/mesh-cli/main_test.go @@ -87,17 +87,17 @@ func TestEachLineCallsItsOwner(t *testing.T) { address string args string }{ - {"node show ace", "mesh-placement.placement", `{"node":"ace"}`}, - {"node public-domain ace", "mesh-placement.placement", `{"node":"ace"}`}, - {"node public-domain ace example.org --why moved", "mesh-placement.propose", `{"changes":[{"field":"public-domain","node":"ace","op":"decide","value":"example.org"}],"why":"moved"}`}, + {"node show ace", "mesh-module-assigner.placement", `{"node":"ace"}`}, + {"node public-domain ace", "mesh-module-assigner.placement", `{"node":"ace"}`}, + {"node public-domain ace example.org --why moved", "mesh-module-assigner.propose", `{"changes":[{"field":"public-domain","node":"ace","op":"decide","value":"example.org"}],"why":"moved"}`}, {"plan ace", "mesh-delivery-view.assigner_wants", `{"node":"ace"}`}, {"haves", "mesh-delivery-view.node_haves", `{}`}, {"composition ace plex", "ace/node-engine.composition", `{"module":"plex"}`}, - {"seats", "mesh-placement.placement", `{"seats":"true"}`}, - {"assign ace plex sonarr --why=media", "mesh-placement.propose", `{"changes":[{"module":"plex","node":"ace","op":"place"},{"module":"sonarr","node":"ace","op":"place"}],"why":"media"}`}, - {"unassign ace plex --why gone", "mesh-placement.propose", `{"changes":[{"module":"plex","node":"ace","op":"take-off"}],"why":"gone"}`}, - {"pin ace postgres-database novox postgres --why one", "mesh-placement.propose", `{"changes":[{"node":"ace","op":"pin","provider":{"module":"postgres","node":"novox"},"provision":"postgres-database"}],"why":"one"}`}, - {"unpin ace postgres-database --why back", "mesh-placement.propose", `{"changes":[{"node":"ace","op":"unpin","provision":"postgres-database"}],"why":"back"}`}, + {"seats", "mesh-module-assigner.placement", `{"seats":"true"}`}, + {"assign ace plex sonarr --why=media", "mesh-module-assigner.propose", `{"changes":[{"module":"plex","node":"ace","op":"place"},{"module":"sonarr","node":"ace","op":"place"}],"why":"media"}`}, + {"unassign ace plex --why gone", "mesh-module-assigner.propose", `{"changes":[{"module":"plex","node":"ace","op":"take-off"}],"why":"gone"}`}, + {"pin ace postgres-database novox postgres --why one", "mesh-module-assigner.propose", `{"changes":[{"node":"ace","op":"pin","provider":{"module":"postgres","node":"novox"},"provision":"postgres-database"}],"why":"one"}`}, + {"unpin ace postgres-database --why back", "mesh-module-assigner.propose", `{"changes":[{"node":"ace","op":"unpin","provision":"postgres-database"}],"why":"back"}`}, {"deliveries --state merged --json", "mesh-delivery.deliveries", `{"state":"merged"}`}, {"delivery novox/mesh-sdk@dff0ce2abb21", "mesh-delivery.show", `{"id":"novox/mesh-sdk@dff0ce2abb21"}`}, {"checks novox/mesh-catalog --number 591", "mesh-delivery.checks", `{"number":"591","repository":"novox/mesh-catalog"}`}, @@ -132,9 +132,9 @@ func TestEachLineCallsItsOwner(t *testing.T) { {"kb ask what holds about the merge window", "knowledge-base.ask", `{"question":"what holds about the merge window"}`}, {"kb get 587 --reasoning", "knowledge-base.get", `{"number":587,"reasoning":true}`}, {"progress 47", "knowledge-base.progress", `{"of":"design 47"}`}, - {"enrol issue new1 --why laptop --expires 2h", "mesh-enrolment.issue", `{"expires":"2h","node":"new1","why":"laptop"}`}, - {"token issue --new new1 --why laptop", "mesh-enrolment.issue", `{"node":"new1","why":"laptop"}`}, - {"enrol tokens", "mesh-enrolment.tokens", `{}`}, + {"enrol issue new1 --why laptop --expires 2h", "mesh-node-enroller.issue", `{"expires":"2h","node":"new1","why":"laptop"}`}, + {"token issue --new new1 --why laptop", "mesh-node-enroller.issue", `{"node":"new1","why":"laptop"}`}, + {"enrol tokens", "mesh-node-enroller.tokens", `{}`}, {"call ace/node-service-manager.status {\"unit\":\"plex\"}", "ace/node-service-manager.status", `{"unit":"plex"}`}, {"ask mesh-catalog catalog_modules", "mesh-catalog.catalog_modules", `{}`}, } { @@ -190,13 +190,13 @@ func TestALineWithNoOwnerOrNotReadCallsNothingAndSaysWhy(t *testing.T) { // What the console says is printed as said: an answer it marks an error on standard error with exit 1, a console that // does not answer as nothing called, a verb's process refused before anything is called; nodes are one line each. func TestAnswersRefusalsAndSilenceAreSaid(t *testing.T) { - got := console(t, map[string]string{"mesh-enrolment.tokens": "!nothing serves seat:mesh-enrolment.tokens"}) + got := console(t, map[string]string{"mesh-node-enroller.tokens": "!nothing serves seat:mesh-node-enroller.tokens"}) if code, out, errOut := runLine("enrol", "tokens"); code != 1 || out != "" || !strings.Contains(errOut, "nothing serves") { t.Errorf("an error answer: exit %d, stdout %q, stderr %q", code, out, errOut) } placement := `{"keys":{"novox":{"placement":{"decided":{"address":"10.10.0.1","site":"hub"},"modules":[{},{}]}},` + `"ace":{"placement":{"decided":{"address":"10.10.0.2"},"modules":[{}]}}}}` - console(t, map[string]string{"mesh-placement.placement": placement}) + console(t, map[string]string{"mesh-module-assigner.placement": placement}) if code, out, _ := runLine("nodes"); code != 0 || !strings.HasPrefix(out, "ace ") || !strings.Contains(out, "10.10.0.1") || !strings.Contains(out, "2 modules") || !strings.HasSuffix(out, "answered by ace\n") { t.Errorf("nodes: exit %d, %q", code, out) diff --git a/modules/mesh-conditions/cmd/mesh-conditions/hold_test.go b/modules/mesh-conditions/cmd/mesh-conditions/hold_test.go index ef555a03b..bff33be8d 100644 --- a/modules/mesh-conditions/cmd/mesh-conditions/hold_test.go +++ b/modules/mesh-conditions/cmd/mesh-conditions/hold_test.go @@ -94,7 +94,7 @@ func TestADeliveryHoldsItsOwnFindingsUntilItEnds(t *testing.T) { } } // A seat's finding is about the module the placement says holds the seat on that node (the lead, 2026-10-29): held - // while the assigner is delivered on ace, though the seat is named mesh-placement. + // while the assigner is delivered on ace, though the seat is named mesh-module-assigner. r := newRig() // Research 072 row 37: the placement in its keys per module and node; a stale legacy key beside them is not read. stale, err := delivery.EncodePlacement(delivery.Placement{Node: "ace"}) @@ -103,7 +103,7 @@ func TestADeliveryHoldsItsOwnFindingsUntilItEnds(t *testing.T) { } r.k.Placement("placement.ace", stale, false) placed, err := delivery.PlacementValues(delivery.Placement{Node: "ace", Modules: []delivery.PlacedModule{{Module: "mesh-delivery-assigner"}}, - Holds: []delivery.Holding{{Claim: "mesh-placement", Scope: "mesh", Module: "mesh-delivery-assigner"}}}) + Holds: []delivery.Holding{{Claim: "mesh-module-assigner", Scope: "mesh", Module: "mesh-delivery-assigner"}}}) if err != nil { t.Fatal(err) } @@ -111,7 +111,7 @@ func TestADeliveryHoldsItsOwnFindingsUntilItEnds(t *testing.T) { r.k.Placement("ace.node", placed["ace.node"], false) _ = r.k.Want("want.ace.mesh-delivery-assigner", want(ctrlNext, ctrlNextComp), false) _ = r.k.Have("ace.mesh-delivery-assigner", have(ctrlRunning, ctrlComposed, delivery.PhaseRunning, delivery.HealthOK), false) - seat, seatRaw := finding(t, selfCheck, health.ScopeSeat, "mesh-placement.ace", "holder-silent", "D3", health.Warning, r.now) + seat, seatRaw := finding(t, selfCheck, health.ScopeSeat, "mesh-module-assigner.ace", "holder-silent", "D3", health.Warning, r.now) _ = r.k.Finding(selfCheck, seat, seatRaw, false) if got := r.changes(); got != "" || len(r.k.Held()) != 1 || r.k.Held()[0].Module != "mesh-delivery-assigner" { t.Errorf("a seat's finding while its holder is delivered: said %q, held %+v", got, r.k.Held()) diff --git a/modules/mesh-conditions/cmd/mesh-conditions/keeper.go b/modules/mesh-conditions/cmd/mesh-conditions/keeper.go index a982fe5c7..ae70c5d5b 100644 --- a/modules/mesh-conditions/cmd/mesh-conditions/keeper.go +++ b/modules/mesh-conditions/cmd/mesh-conditions/keeper.go @@ -54,7 +54,7 @@ var Observers = []string{health.WatchmanModule, health.SelfCheckModule, health.H const ( AttemptsRead = health.HealersModule + "." + health.AttemptsState WantsRead = delivery.AssignerModule + ".wants" - // PlacementRead is the mesh-placement seat's placement, read for which module holds a seat on a node (hold.go; the + // PlacementRead is the mesh-module-assigner seat's placement, read for which module holds a seat on a node (hold.go; the // lead, 2026-10-29, for ADR 0564 clause 2's inputs). PlacementRead = delivery.PlacementRead HavesRead = "node-engine.have" diff --git a/modules/mesh-config/README.md b/modules/mesh-config/README.md index db8e61a79..4435a66a7 100644 --- a/modules/mesh-config/README.md +++ b/modules/mesh-config/README.md @@ -21,7 +21,7 @@ account alone writes its buckets. ## How a value resolves -For every module the seat mesh-placement places on a node (`mesh-delivery-assigner.placement`), from the module's +For every module the seat mesh-module-assigner places on a node (`mesh-delivery-assigner.placement`), from the module's own manifests as the delivery built them, never from the controller (issue 1953): the trunk's, which the indexer's `modules.` names in its manifests by digest (`mesh-delivery-indexer.modules`, `.manifests`), with the build the node's want names (`mesh-delivery-assigner.wants`, the builder's `mesh-delivery-builder.builds` naming its manifest) diff --git a/modules/mesh-config/cmd/mesh-config/config_test.go b/modules/mesh-config/cmd/mesh-config/config_test.go index 5b4334d04..9888a750c 100644 --- a/modules/mesh-config/cmd/mesh-config/config_test.go +++ b/modules/mesh-config/cmd/mesh-config/config_test.go @@ -146,7 +146,7 @@ func (m *memStore) mirror(t *testing.T, read, key, raw string) { m.states[read][key] = []byte(raw) } -// assign places a module on a node, in the seat mesh-placement's key for the node. +// assign places a module on a node, in the seat mesh-module-assigner's key for the node. func (m *memStore) assign(t *testing.T, node, module string) { t.Helper() m.place(t, node, module, true) diff --git a/modules/mesh-config/cmd/mesh-config/declared.go b/modules/mesh-config/cmd/mesh-config/declared.go index b4c0d340c..cf9d2f7e9 100644 --- a/modules/mesh-config/cmd/mesh-config/declared.go +++ b/modules/mesh-config/cmd/mesh-config/declared.go @@ -148,7 +148,7 @@ type Published struct { Commit string `json:"commit"` } -// Assignment is a module placed on a node, as the seat mesh-placement's key `placement.` names it. +// Assignment is a module placed on a node, as the seat mesh-module-assigner's key `placement.` names it. type Assignment struct { Node string `json:"node"` Module string `json:"module"` diff --git a/modules/mesh-config/cmd/mesh-config/main.go b/modules/mesh-config/cmd/mesh-config/main.go index 43aa99c07..83be0a303 100644 --- a/modules/mesh-config/cmd/mesh-config/main.go +++ b/modules/mesh-config/cmd/mesh-config/main.go @@ -4,7 +4,7 @@ // node), mesh-config_resolved (each module's value on each node, with its source), mesh-config_predefined (the // published list of predefined keys) and mesh-config_proposals (each value proposed for the operator's Approve, // asked under this module's own name, design 57 K4). -// It resolves from where the seat mesh-placement places each module, and each module's declarations as its own +// It resolves from where the seat mesh-module-assigner places each module, and each module's declarations as its own // manifests declare them, the trunk's and its wanted build's (the indexer's and the builder's state, issue 1953); the // list of predefined keys comes from the indexer's (ADR 0565 §2); the controller's records are no longer read (issue 774). stdout is the MCP channel; what this module says, it says on stderr. package main diff --git a/modules/mesh-config/cmd/mesh-config/resolve.go b/modules/mesh-config/cmd/mesh-config/resolve.go index 72f41fd81..bc00f098c 100644 --- a/modules/mesh-config/cmd/mesh-config/resolve.go +++ b/modules/mesh-config/cmd/mesh-config/resolve.go @@ -22,7 +22,7 @@ const ( PredefinedState = "predefined" ProposalsState = "proposals" - // PlacementRead is the seat mesh-placement's state, held by the assigner (novox/hq ADR 0567 §1, §8): each + // PlacementRead is the seat mesh-module-assigner's state, held by the assigner (novox/hq ADR 0567 §1, §8): each // node's key `placement.` with the modules placed there. It is the one source of which module runs where // (issue 1953): the controller's assignments are no longer read. PlacementRead = delivery.PlacementRead diff --git a/modules/mesh-config/cmd/mesh-config/sources.go b/modules/mesh-config/cmd/mesh-config/sources.go index 9a0620e0a..c70c04001 100644 --- a/modules/mesh-config/cmd/mesh-config/sources.go +++ b/modules/mesh-config/cmd/mesh-config/sources.go @@ -13,14 +13,14 @@ import ( // Reading the sources, writing the resolved values, and publishing the list of predefined keys. // sources reads everything a resolution reads, from the bus as it is now, from the source the switch names -// (takeover.go): which modules are placed where from the seat mesh-placement, and each placed module's declarations +// (takeover.go): which modules are placed where from the seat mesh-module-assigner, and each placed module's declarations // from its own manifests as built (issue 1953, ADR 0565 §3); the controller's records are no longer read. func (c *Config) sources() (Sources, error) { s := Sources{Declared: map[string]ModuleDeclarations{}, OnNode: map[string]ModuleDeclarations{}, Predefined: map[string]Published{}, Values: map[string]Value{}, Renames: map[string]Rename{}} var problems []string if err := c.readPlacement(&s); err != nil { - return s, fmt.Errorf("the seat mesh-placement's placement cannot be read: %w", err) + return s, fmt.Errorf("the seat mesh-module-assigner's placement cannot be read: %w", err) } if err := c.readDeclarations(&s); err != nil { return s, fmt.Errorf("the modules' declarations cannot be read: %w", err) @@ -63,7 +63,7 @@ func (c *Config) sources() (Sources, error) { return s, nil } -// readPlacement is every module the seat mesh-placement places on a node (ADR 0567 §1, §9), from the state's keys in +// readPlacement is every module the seat mesh-module-assigner places on a node (ADR 0567 §1, §9), from the state's keys in // either form: a node key and its module keys, or the form before, `placement.` (delivery.PlacementsOf; // research 072 row 37). By node in name order, each node's modules in the order its placement names them. func (c *Config) readPlacement(s *Sources) error { diff --git a/modules/mesh-provisioner-client/README.md b/modules/mesh-provisioner-client/README.md index 1132b5d91..1e833d7d3 100644 --- a/modules/mesh-provisioner-client/README.md +++ b/modules/mesh-provisioner-client/README.md @@ -5,12 +5,12 @@ P5). Go, one binary (`cmd/mesh-provisioner-client`), run as a service of its own `mesh-provisioner-client`, outside the tool runner, on a bus account of its own, `provisioner.`, delivered as its own secret `provisioner-broker` (mesh-sdk `buscompose/provisioner.go`). The bus grants that account its own machine's keys and, to read alone, the seat mesh-provisioner's whole `plans`, where a provider's consumers on any -machine are bound to it (ADR 0373), and the seat mesh-placement's whole `placement`; nothing else. +machine are bound to it (ADR 0373), and the seat mesh-module-assigner's whole `placement`; nothing else. ## What it does For each module placed on its node — a plan in the seat mesh-provisioner's `plans` (`mesh-provisioner_plans`, -`.`, novox/hq ADR 0570 clause 2); a module the seat mesh-placement still places here stays while the +`.`, novox/hq ADR 0570 clause 2); a module the seat mesh-module-assigner still places here stays while the seat holds no plan of it, filled from its last plan, and leaves only when neither names it (issue 1126): the templates archive by reference and digest, the files it fills (path, template, `owner-at-runtime`, how its program takes a change) and the placement values its templates name — the client: diff --git a/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/client.go b/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/client.go index ee345c4ac..438899cc2 100644 --- a/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/client.go +++ b/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/client.go @@ -37,7 +37,7 @@ import ( // The owners it fills from are placement (in the module's plan), config (mesh-config_resolved) and the vault, asked for // each secret the module's plan names (secrets.go), and for each consumer's credential a provider here lists // (consumers.go); and each provider's entries for a consumer here. Every key it writes is its own machine's; it reads -// the plans whole, for who binds a provider here (ADR 0373), and the seat mesh-placement's placement, for which +// the plans whole, for who binds a provider here (ADR 0373), and the seat mesh-module-assigner's placement, for which // modules stay here: its bus account is granted no other. // The buckets the client reads and writes, and the subject it reports on. @@ -45,7 +45,7 @@ const ( // PlansBucket is where each module's provisioning plan on each node is read: the seat mesh-provisioner's // `plans` (novox/hq ADR 0570 clause 2), read as an assignment's value carried it (asAssignment). PlansBucket = provisions.PlansBucket - // PlacementBucket is the seat mesh-placement's placement (novox/hq ADR 0567): a module it names on this node stays + // PlacementBucket is the seat mesh-module-assigner's placement (novox/hq ADR 0567): a module it names on this node stays // here while the seat mesh-provisioner holds no plan of it (nats on novox runs without a want), filled from its // last plan, and leaves only when neither names it (issue 1126 B12; the controller's assignments mirror, read for // this before, is frozen since the controller's end, ADR 0590). @@ -155,7 +155,7 @@ type state struct { plans map[string]Plan // seatPlans is the seat's plan by key, as an assignment's value reads. seatPlans map[string][]byte - // placement is the seat mesh-placement's keys as read, and placed the modules it names on this node. + // placement is the seat mesh-module-assigner's keys as read, and placed the modules it names on this node. placement *delivery.PlacementKeys placed map[string]bool refused map[string]string // a module whose plan cannot be acted on, and why @@ -1161,7 +1161,7 @@ func (c *Client) forgetItems(ctx context.Context, kvs map[string]jetstream.KeyVa return removed } -// takePlacement folds one key of the seat mesh-placement's placement in, and answers the modules of this node it moved: +// takePlacement folds one key of the seat mesh-module-assigner's placement in, and answers the modules of this node it moved: // one it names now stays here without a plan; one it no longer names, with no plan of the seat, leaves. func (c *Client) takePlacement(s *state, key string, value []byte, revision uint64, gone bool) []string { node, err := s.placement.Put(key, value, revision, gone) diff --git a/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/client_test.go b/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/client_test.go index dd0c49a56..86c9fde0b 100644 --- a/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/client_test.go +++ b/modules/mesh-provisioner-client/cmd/mesh-provisioner-client/client_test.go @@ -97,7 +97,7 @@ func startBus(t *testing.T) *aBus { `"bucket":"mesh-provisioner_collect","key":".."}`) } for _, kind := range placementKinds { - b.put(t, RegistryBucket, kind, `{"kind":"`+kind+`","domain":"mesh-placement","from":"bucket",`+ + b.put(t, RegistryBucket, kind, `{"kind":"`+kind+`","domain":"mesh-module-assigner","from":"bucket",`+ `"bucket":"mesh-provisioner_plans","key":"."}`) } return b @@ -122,7 +122,7 @@ func (b *aBus) put(t *testing.T, bucket, key, value string) { } } -// place writes this node's placement as the seat mesh-placement keeps it, naming exactly these modules. +// place writes this node's placement as the seat mesh-module-assigner keeps it, naming exactly these modules. func (b *aBus) place(t *testing.T, modules ...string) { t.Helper() p := delivery.Placement{V: 1, Node: node} @@ -659,7 +659,7 @@ func TestNatsAModuleTakenOffTheNodeLosesItsReport(t *testing.T) { } // Issue 1126 B12 (ADR 0590): the controller's assignments are frozen and go, so what places a module here is the seat -// mesh-placement's placement alone. A module stays while placement names it, even with no plan of the seat +// mesh-module-assigner's placement alone. A module stays while placement names it, even with no plan of the seat // mesh-provisioner (nats on novox runs without a want): its last plan keeps being filled, and it leaves only when // neither its plan nor its placement is there. func TestNatsAModuleStaysWhilePlacementNamesItAndLeavesOnlyWhenNeitherPlacesIt(t *testing.T) { diff --git a/modules/mesh-self-check/cmd/mesh-self-check/probes_mesh.go b/modules/mesh-self-check/cmd/mesh-self-check/probes_mesh.go index af57290a0..0970c7517 100644 --- a/modules/mesh-self-check/cmd/mesh-self-check/probes_mesh.go +++ b/modules/mesh-self-check/cmd/mesh-self-check/probes_mesh.go @@ -1,7 +1,7 @@ package main // The probes of the mesh's machines (novox/hq ADR 0564 §6, issue 1952): each reads its facts where they live on the -// bus — placement (the seat mesh-placement's state), who holds which seat (its seat-holders), whether a node is heard +// bus — placement (the seat mesh-module-assigner's state), who holds which seat (its seat-holders), whether a node is heard // from (the watchman's presence) — and asks each node's seat holder what only that node knows. Its assertion, kind, // key and words are the controller's (mesh-controller probes.go), so the condition the keeper raises from it is the one // the controller raised. diff --git a/modules/mesh-vault/cmd/mesh-vault/enrolment.go b/modules/mesh-vault/cmd/mesh-vault/enrolment.go index 87f694711..04c48b236 100644 --- a/modules/mesh-vault/cmd/mesh-vault/enrolment.go +++ b/modules/mesh-vault/cmd/mesh-vault/enrolment.go @@ -2,14 +2,14 @@ package main // The vault's part of enrolment (novox/hq ADR 0587 §3, §5, §8; ADR 0561 §4, §5; issue 774). // -// A machine joins with a token a person types. The seat mesh-enrolment decides who may join; the vault holds the secrets. +// A machine joins with a token a person types. The seat mesh-node-enroller decides who may join; the vault holds the secrets. // Its verb `enrolment-token` makes the token's one-time secret, keeps it with its operator copy as `enrol//token`, // writes its bcrypt hash under `bus-accounts` as the user `enrol.`, and answers at issue the public fields alone // (never the token). Asked to show it, it answers the whole token sealed to the operator key, which the operator opens at // their own terminal (`nox enrol open`); asked to drop it, it takes the token and its hash away. Its verb `node-account` // makes the account `node.` of a joining machine at the redeem: once for a node and a set of keys, sealed to the key // the machine presented, with the node's key in `node-logins` naming that login in use and nothing rotating. Only the -// seat mesh-enrolment may call either: the runtime proves who asks. +// seat mesh-node-enroller may call either: the runtime proves who asks. import ( "crypto/ecdh" @@ -32,7 +32,7 @@ import ( "golang.org/x/crypto/bcrypt" ) -// The names enrolment gives: the module that holds the seat mesh-enrolment, the prefix of a token's bus user, and the +// The names enrolment gives: the module that holds the seat mesh-node-enroller, the prefix of a token's bus user, and the // vault's state of each node's logins. const ( EnrolmentModule = delivery.EnrolmentModule @@ -115,7 +115,7 @@ func (v *Vault) loginKeyRefusal(caller, publicKey string) string { return "" } -// fromEnrolment refuses every caller but the seat mesh-enrolment, as the runtime proved it. +// fromEnrolment refuses every caller but the seat mesh-node-enroller, as the runtime proved it. func (v *Vault) fromEnrolment(caller, verb string) error { callers := v.EnrolCallers if callers == nil { diff --git a/modules/mesh-vault/cmd/mesh-vault/enrolment_test.go b/modules/mesh-vault/cmd/mesh-vault/enrolment_test.go index 031b46299..e25511f69 100644 --- a/modules/mesh-vault/cmd/mesh-vault/enrolment_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/enrolment_test.go @@ -199,7 +199,7 @@ func TestTheVaultsEnrolmentAnswersAreMeshSDKsWireShapes(t *testing.T) { filled []string // the json fields the holder reads, which must not be empty refused string // a part of the refusal, when refused }{ - // Only the seat mesh-enrolment is answered: not the controller, a node, a person or a caller not proven. + // Only the seat mesh-node-enroller is answered: not the controller, a node, a person or a caller not proven. {"a node asks a token", "enrolment-token", "node.g14", map[string]any{"node": "new1", "tunnel": tunnel}, nil, nil, "mesh-enrolment"}, {"the controller asks a token", "enrolment-token", "controller", map[string]any{"node": "new1", "tunnel": tunnel}, nil, nil, "mesh-enrolment"}, {"a person asks an account", "node-account", "person.jochen", map[string]any{"node": "new1"}, nil, nil, "mesh-enrolment"}, diff --git a/modules/mesh-vault/cmd/mesh-vault/enrolment_tools.go b/modules/mesh-vault/cmd/mesh-vault/enrolment_tools.go index a976eb3b6..efeaa308e 100644 --- a/modules/mesh-vault/cmd/mesh-vault/enrolment_tools.go +++ b/modules/mesh-vault/cmd/mesh-vault/enrolment_tools.go @@ -55,7 +55,7 @@ func enrolmentTools(env *Env) []toolDef { node := str("the node's name") return []toolDef{ {Name: Seat + ".enrolment-token", - Description: "The enrolment token of a joining machine, for the seat mesh-enrolment alone (novox/hq ADR 0587 §3, §5, " + + Description: "The enrolment token of a joining machine, for the seat mesh-node-enroller alone (novox/hq ADR 0587 §3, §5, " + "§8). Issue (the default): takes the machine's first tunnel, makes the one-time secret, keeps both with the operator " + "copy, writes the secret's hash as the bus user enrol., and answers the bus's address, its certificate's " + "fingerprint and the vault's signing key, never the token. sealed: the whole token sealed to the operator key, " + @@ -78,7 +78,7 @@ func enrolmentTools(env *Env) []toolDef { Tunnel: tunnel, Sealed: isTrue(a["sealed"]), Drop: isTrue(a["drop"])}) }}, {Name: Seat + ".node-account", - Description: "A joining node's account node., for the seat mesh-enrolment alone at the redeem (novox/hq ADR 0587 " + + Description: "A joining node's account node., for the seat mesh-node-enroller alone at the redeem (novox/hq ADR 0587 " + "§3): made once for a node and the keys it presented, answered sealed to the sealing key presented, with the " + "node's key in node-logins naming the login in use. Asked again for the same keys it answers the same account. " + "retire: the account, its value and its key taken away at a revoke.", diff --git a/modules/mesh-vault/cmd/mesh-vault/main.go b/modules/mesh-vault/cmd/mesh-vault/main.go index ebc3b88c5..67ae3fb0c 100644 --- a/modules/mesh-vault/cmd/mesh-vault/main.go +++ b/modules/mesh-vault/cmd/mesh-vault/main.go @@ -238,7 +238,7 @@ func watchCredentialAsks(env *Env, kick chan<- struct{}) bool { return true } -// placement reads the seat mesh-placement's placement through its owner's tool and events (placementview.go), never the +// placement reads the seat mesh-module-assigner's placement through its owner's tool and events (placementview.go), never the // owner's bucket. var placement = viewPlacement(func() *views.Follower { return placementView }) diff --git a/modules/mesh-vault/cmd/mesh-vault/placed.go b/modules/mesh-vault/cmd/mesh-vault/placed.go index a51059f24..4c072fa9b 100644 --- a/modules/mesh-vault/cmd/mesh-vault/placed.go +++ b/modules/mesh-vault/cmd/mesh-vault/placed.go @@ -1,6 +1,6 @@ package main -// Where modules stand, from the placement (novox/hq ADR 0549 §3, §5; ADR 0561; issue 774), the seat mesh-placement's +// Where modules stand, from the placement (novox/hq ADR 0549 §3, §5; ADR 0561; issue 774), the seat mesh-module-assigner's // state held by the assigner (ADR 0567). The controller's assignments mirror goes with its lease, so the vault reads which // module stands on which node from the seat's placement first, and the assignments beside it while both stand: a module either names stands. The provisioner's plan, // which only an assignment's value carries, is read from the assignments still: its home after the lease is a subtask of @@ -16,7 +16,7 @@ import ( "git.novox.be/novox/mesh-sdk/go/delivery" ) -// PlacementRead is the seat mesh-placement's placement, as the vault's manifest reads it (mesh-sdk's contract). +// PlacementRead is the seat mesh-module-assigner's placement, as the vault's manifest reads it (mesh-sdk's contract). const PlacementRead = delivery.PlacementRead // PlacementReader reads the seat's placement: every key, and one key's value (nil when there is none). diff --git a/modules/mesh-vault/cmd/mesh-vault/placed_test.go b/modules/mesh-vault/cmd/mesh-vault/placed_test.go index 4a49a4c28..122d9f247 100644 --- a/modules/mesh-vault/cmd/mesh-vault/placed_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/placed_test.go @@ -7,7 +7,7 @@ import ( "git.novox.be/novox/mesh-sdk/go/delivery" ) -// placementsOf is the seat mesh-placement's placement of each node, as the vault reads it. +// placementsOf is the seat mesh-module-assigner's placement of each node, as the vault reads it. func placementsOf(t *testing.T, nodes map[string][]string) PlacementReader { t.Helper() values := map[string][]byte{} diff --git a/modules/mesh-vault/cmd/mesh-vault/placementview.go b/modules/mesh-vault/cmd/mesh-vault/placementview.go index 35b4effc1..111874e01 100644 --- a/modules/mesh-vault/cmd/mesh-vault/placementview.go +++ b/modules/mesh-vault/cmd/mesh-vault/placementview.go @@ -1,6 +1,6 @@ package main -// The vault's reading of the seat mesh-placement's placement, through its owner (novox/hq ADR 0615 §1, §4 to §6, ADR +// The vault's reading of the seat mesh-module-assigner's placement, through its owner (novox/hq ADR 0615 §1, §4 to §6, ADR // 0596): the assigner's tool `assigner_read_placement` asked for the whole state at start, the owner's `views.placement` // events after it, and the tool once more only on a gap. Started while the assigner is down it keeps asking and says so; // it never reads the assigner's bucket instead. (The vault's other reads, the node-engines' haves, the grants part's diff --git a/modules/mesh-vault/cmd/mesh-vault/signing.go b/modules/mesh-vault/cmd/mesh-vault/signing.go index 80faad1f9..8500f12c2 100644 --- a/modules/mesh-vault/cmd/mesh-vault/signing.go +++ b/modules/mesh-vault/cmd/mesh-vault/signing.go @@ -277,7 +277,7 @@ func (v *Vault) Sign(caller string, a SignArgs) (meshvault.SignAnswer, error) { return meshvault.SignAnswer{}, fmt.Errorf("%q is not a kind the vault signs (%s)", a.Kind, strings.Join(delivery.SignKinds, ", ")) } -// redeeming says node has an enrolment token held: a machine joining, which the seat mesh-enrolment redeems. +// redeeming says node has an enrolment token held: a machine joining, which the seat mesh-node-enroller redeems. func (v *Vault) redeeming(node string) error { if err := enrolNode(node); err != nil { return err @@ -290,7 +290,7 @@ func (v *Vault) redeeming(node string) error { return nil } -// signRedeemingCertificate signs the certificate of a machine that is joining, for the seat mesh-enrolment at the redeem +// signRedeemingCertificate signs the certificate of a machine that is joining, for the seat mesh-node-enroller at the redeem // (ADR 0587 §6). The machine has written no record yet, so the serving key is the one it presented at the redeem, which // counts only when the four keys presented have the digest node-account recorded for its account; the name is its // placement's, which mesh-enrolment writes before it asks. @@ -410,7 +410,7 @@ func (v *Vault) internalName(node string) (string, error) { return "", fmt.Errorf(notYetPrefix+"the placement of %s could not be read: %w", node, err) } if !found { - return "", fmt.Errorf("%s has no placement of the seat mesh-placement, so it has no name inside the mesh", node) + return "", fmt.Errorf("%s has no placement of the seat mesh-module-assigner, so it has no name inside the mesh", node) } if decided.Address == "" { return "", fmt.Errorf("%s is not on the private network (its placement names no address), so it has no name inside the mesh to be certified for", node) diff --git a/modules/mesh-vault/cmd/mesh-vault/vault.go b/modules/mesh-vault/cmd/mesh-vault/vault.go index 04db7f074..f246790ab 100644 --- a/modules/mesh-vault/cmd/mesh-vault/vault.go +++ b/modules/mesh-vault/cmd/mesh-vault/vault.go @@ -78,7 +78,7 @@ type Vault struct { // none. Signers SignersStore // EnrolCallers are the callers of the enrolment verbs `enrolment-token` and `node-account` and of `sign` for an - // enrolment: the seat mesh-enrolment (enrolment.go). Nil: that module alone. + // enrolment: the seat mesh-node-enroller (enrolment.go). Nil: that module alone. EnrolCallers stdio.Callers // RetireCallers are the callers of the seat's verb `retire`: the vault's trusted config value `retire-callers`, the // holder of the seat mesh-config alone (ownretire.go). Nil: nobody.