From d33e6baa73ecb327e83bb3ef3dd88821c2ebb10d Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 22 Oct 2026 21:26:05 +0200 Subject: [PATCH 1/5] Name no node in nodered's, netcheck's, telegram's and nfs-server's fixtures (issue 1838) --- modules/netcheck/cmd/netcheck/ask_test.go | 16 +++++----- modules/netcheck/cmd/netcheck/tunnel_test.go | 14 ++++----- .../nfs-server/cmd/nfs-server/backup_test.go | 14 ++++----- .../nfs-server/cmd/nfs-server/guards_test.go | 4 +-- modules/nodered/mqtt/connection.ts | 2 +- modules/nodered/test/mqtt.test.ts | 30 +++++++++---------- modules/telegram/cmd/telegram/channel_test.go | 22 +++++++------- modules/telegram/cmd/telegram/render_test.go | 2 +- 8 files changed, 52 insertions(+), 52 deletions(-) diff --git a/modules/netcheck/cmd/netcheck/ask_test.go b/modules/netcheck/cmd/netcheck/ask_test.go index 1ad2c293..6bdf4349 100644 --- a/modules/netcheck/cmd/netcheck/ask_test.go +++ b/modules/netcheck/cmd/netcheck/ask_test.go @@ -10,7 +10,7 @@ import ( "time" ) -// respond answers one query: novox.internal A 10.10.0.1 via a compressed name, anything else rcode. +// respond answers one query: node-c.internal A 10.10.0.1 via a compressed name, anything else rcode. func respond(q []byte, rcode byte) []byte { end := 12 for q[end] != 0 { @@ -20,7 +20,7 @@ func respond(q []byte, rcode byte) []byte { name := strings.ToLower(string(q[13:end])) r := append([]byte{}, q[:2]...) r = append(r, 0x81, 0x80|rcode, 0, 1) - answer := rcode == 0 && strings.Contains(name, "novox") && binary.BigEndian.Uint16(q[end+1:]) == 1 + answer := rcode == 0 && strings.Contains(name, "node-c") && binary.BigEndian.Uint16(q[end+1:]) == 1 if answer { r = append(r, 0, 1, 0, 0, 0, 0) } else { @@ -80,11 +80,11 @@ func tcpResolver(t *testing.T) string { // Issue 348: the question that could not be asked during the outage — does the resolver at one address answer? func TestDNSAsksANamedResolverOverUDPAndTCPAndSaysItsResponseCode(t *testing.T) { - got, err := AskDNS("novox.internal", "A", udpResolver(t, 0), false, time.Second) + got, err := AskDNS("node-c.internal", "A", udpResolver(t, 0), false, time.Second) if err != nil || got.Rcode != "NOERROR" || got.Protocol != "udp" || len(got.Answers) != 1 || got.Answers[0] != "10.10.0.1" || got.Error != "" { t.Fatalf("udp: %+v, %v", got, err) } - got, err = AskDNS("novox.internal", "A", tcpResolver(t), true, time.Second) + got, err = AskDNS("node-c.internal", "A", tcpResolver(t), true, time.Second) if err != nil || got.Rcode != "NOERROR" || got.Protocol != "tcp" || len(got.Answers) != 1 || got.Answers[0] != "10.10.0.1" { t.Fatalf("tcp: %+v, %v", got, err) } @@ -92,7 +92,7 @@ func TestDNSAsksANamedResolverOverUDPAndTCPAndSaysItsResponseCode(t *testing.T) if got.Rcode != "NXDOMAIN" || got.Error == "" || len(got.Answers) != 0 { t.Fatalf("no such name is a result with its code: %+v", got) } - got, _ = AskDNS("novox.internal", "A", udpResolver(t, 5), false, time.Second) + got, _ = AskDNS("node-c.internal", "A", udpResolver(t, 5), false, time.Second) if got.Rcode != "REFUSED" || got.Error == "" { t.Fatalf("a refusal: %+v", got) } @@ -102,14 +102,14 @@ func TestDNSSaysARefusedPortAndRefusesANameAsServer(t *testing.T) { l, _ := net.Listen("tcp", "127.0.0.1:0") addr := l.Addr().String() l.Close() - got, err := AskDNS("novox.internal", "A", addr, true, time.Second) + got, err := AskDNS("node-c.internal", "A", addr, true, time.Second) if err != nil || !strings.Contains(got.Error, "connection refused") { t.Fatalf("nothing listening is a result naming it: %+v, %v", got, err) } - if _, err := AskDNS("novox.internal", "A", "resolver.example", false, time.Second); err == nil { + if _, err := AskDNS("node-c.internal", "A", "resolver.example", false, time.Second); err == nil { t.Fatal("a server given by name was accepted") } - if _, err := AskDNS("novox.internal", "A", "", true, time.Second); err == nil { + if _, err := AskDNS("node-c.internal", "A", "", true, time.Second); err == nil { t.Fatal("tcp without a server was accepted") } if a, _ := serverAddress("10.10.0.1"); a != "10.10.0.1:53" { diff --git a/modules/netcheck/cmd/netcheck/tunnel_test.go b/modules/netcheck/cmd/netcheck/tunnel_test.go index 29f85b78..c5737cd4 100644 --- a/modules/netcheck/cmd/netcheck/tunnel_test.go +++ b/modules/netcheck/cmd/netcheck/tunnel_test.go @@ -13,8 +13,8 @@ func dump(now time.Time) string { fresh := now.Add(-40 * time.Second).Unix() old := now.Add(-10 * time.Minute).Unix() return privateKey + "\tPUBkeyOfTheHubAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\t51820\toff\n" + - "PUBkeyAceAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\t(none)\t84.193.151.6:40122\t10.10.0.2/32\t" + itoa(old) + "\t1000\t2000\t25\n" + - "PUBkeyShanksAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\t(none)\t84.193.151.6:51820\t10.10.0.3/32\t" + itoa(fresh) + "\t3000\t4000\toff\n" + + "PUBkeyNodeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\t(none)\t84.193.151.6:40122\t10.10.0.2/32\t" + itoa(old) + "\t1000\t2000\t25\n" + + "PUBkeyNodeDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\t(none)\t84.193.151.6:51820\t10.10.0.3/32\t" + itoa(fresh) + "\t3000\t4000\toff\n" + "PUBkeyNewAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\t(none)\t(none)\t10.10.0.9/32\t0\t0\t0\toff\n" } @@ -33,12 +33,12 @@ func TestTheDumpIsReadAndNoKeyIsSaid(t *testing.T) { if tun.ListenPort != 51820 || len(tun.Peers) != 3 { t.Fatalf("got %+v", tun) } - ace, shanks, fresh := tun.Peers[0], tun.Peers[1], tun.Peers[2] - if ace.Endpoint != "84.193.151.6:40122" || ace.HandshakeAge != 600 || !ace.Stale || ace.Keepalive != "25s" || ace.Sent != 2000 { - t.Errorf("ace %+v", ace) + nodeA, nodeD, fresh := tun.Peers[0], tun.Peers[1], tun.Peers[2] + if nodeA.Endpoint != "84.193.151.6:40122" || nodeA.HandshakeAge != 600 || !nodeA.Stale || nodeA.Keepalive != "25s" || nodeA.Sent != 2000 { + t.Errorf("nodeA %+v", nodeA) } - if shanks.Stale || shanks.HandshakeAge != 40 || shanks.Keepalive != "" { - t.Errorf("shanks %+v", shanks) + if nodeD.Stale || nodeD.HandshakeAge != 40 || nodeD.Keepalive != "" { + t.Errorf("nodeD %+v", nodeD) } if fresh.Endpoint != "" || fresh.HandshakeAge != -1 || !fresh.Stale || fresh.Handshake != "" { t.Errorf("a peer never heard from %+v", fresh) diff --git a/modules/nfs-server/cmd/nfs-server/backup_test.go b/modules/nfs-server/cmd/nfs-server/backup_test.go index 7ae3298b..0af8bd31 100644 --- a/modules/nfs-server/cmd/nfs-server/backup_test.go +++ b/modules/nfs-server/cmd/nfs-server/backup_test.go @@ -81,16 +81,16 @@ func TestWithoutTheBackupListTheExportsStayAndItIsSaid(t *testing.T) { } func TestBackupFromTheSeatsAndTheData(t *testing.T) { - seats := json.RawMessage(`{"answer":{"seats":[{"seat":"node-backup","scope":"node","holders":[{"module":"restic","node":"ace"},{"module":"borg","node":"shanks"}]}]},"ok":true}`) - data := json.RawMessage(`{"answer":{"data":[{"machine":"ace","module":"restic","item":"repository","path":"/storage/restic"},{"machine":"ace","module":"restic","item":"state","path":"/var/lib/restic"},{"machine":"ace","module":"plex","item":"data","path":"/mnt/plex/data"}]},"ok":true}`) - holder, paths, err := BackupFrom("ace", seats, data) + seats := json.RawMessage(`{"answer":{"seats":[{"seat":"node-backup","scope":"node","holders":[{"module":"restic","node":"node-a"},{"module":"borg","node":"node-d"}]}]},"ok":true}`) + data := json.RawMessage(`{"answer":{"data":[{"machine":"node-a","module":"restic","item":"repository","path":"/storage/restic"},{"machine":"node-a","module":"restic","item":"state","path":"/var/lib/restic"},{"machine":"node-a","module":"plex","item":"data","path":"/mnt/plex/data"}]},"ok":true}`) + holder, paths, err := BackupFrom("node-a", seats, data) if err != nil || holder != "restic" || strings.Join(paths, " ") != "/storage/restic /var/lib/restic" { t.Errorf("got %q %v %v", holder, paths, err) } - if _, _, err := BackupFrom("g14", seats, data); err == nil { + if _, _, err := BackupFrom("node-b", seats, data); err == nil { t.Errorf("a machine whose backup seat nobody holds is not said") } - if _, _, err := BackupFrom("ace", seats, json.RawMessage(`{"ok":true}`)); err == nil { + if _, _, err := BackupFrom("node-a", seats, json.RawMessage(`{"ok":true}`)); err == nil { t.Errorf("an answer with no data list reads as an empty list") } } @@ -99,11 +99,11 @@ func TestBackupFromTheSeatsAndTheData(t *testing.T) { func TestAFailedAskKeepsTheLastBackupPaths(t *testing.T) { f := newFake(t) m := f.machine() - m.TakeBackupWith("ace", func(string, any) (json.RawMessage, error) { + m.TakeBackupWith("node-a", func(string, any) (json.RawMessage, error) { return nil, errors.New("no responders") }) f.backup("restic", "/storage/restic") - m.TakeBackupWith("ace", func(string, any) (json.RawMessage, error) { + m.TakeBackupWith("node-a", func(string, any) (json.RawMessage, error) { return nil, errors.New("timeout") }) var b BackupFromBus diff --git a/modules/nfs-server/cmd/nfs-server/guards_test.go b/modules/nfs-server/cmd/nfs-server/guards_test.go index add729ff..1c43676c 100644 --- a/modules/nfs-server/cmd/nfs-server/guards_test.go +++ b/modules/nfs-server/cmd/nfs-server/guards_test.go @@ -64,9 +64,9 @@ func TestAFailedReloadIsTriedAgainWhenNothingElseAsks(t *testing.T) { } func TestBackupFromRefusesAnAnswerWithoutADataList(t *testing.T) { - seats := json.RawMessage(`{"answer":{"seats":[{"seat":"node-backup","holders":[{"module":"restic","node":"ace"}]}]}}`) + seats := json.RawMessage(`{"answer":{"seats":[{"seat":"node-backup","holders":[{"module":"restic","node":"node-a"}]}]}}`) for _, data := range []string{`{"answer":{}}`, `{"answer":{"data":null}}`} { - if _, paths, err := BackupFrom("ace", seats, json.RawMessage(data)); err == nil { + if _, paths, err := BackupFrom("node-a", seats, json.RawMessage(data)); err == nil { t.Errorf("%s was read as the empty list %v: never \"nothing to fear\"", data, paths) } } diff --git a/modules/nodered/mqtt/connection.ts b/modules/nodered/mqtt/connection.ts index c7204413..a9deaa09 100644 --- a/modules/nodered/mqtt/connection.ts +++ b/modules/nodered/mqtt/connection.ts @@ -8,7 +8,7 @@ // // **Which broker nodes are the mesh's.** Never guessed: a flow may talk to a broker that has nothing // to do with this mesh. The step owns the node it creates itself (id `mesh-mqtt-topic`, "mesh: -// mqtt-topic") and the ones an assignment names in settings (`mqtt.brokers`: node ids — how ace's +// mqtt-topic") and the ones an assignment names in settings (`mqtt.brokers`: node ids — how node-a's // existing broker node, which every one of its MQTT flows uses, is handed over). With none named and // none made yet, it makes one, so a fresh Node-RED has a broker the flows can pick. // diff --git a/modules/nodered/test/mqtt.test.ts b/modules/nodered/test/mqtt.test.ts index 59a1f6a0..25e33b54 100644 --- a/modules/nodered/test/mqtt.test.ts +++ b/modules/nodered/test/mqtt.test.ts @@ -4,7 +4,7 @@ // differs; a node that is not named is never touched; a loopback broker address is refused. // // Node-RED and the broker are fakes answering as the real ones do (admin API v2 of nodered/node-red -// 5.0.7, the build ace runs). +// 5.0.7, the build node-a runs). import { test } from "node:test"; import assert from "node:assert/strict"; @@ -13,10 +13,10 @@ import { MESH_BROKER_ID, namedBrokers, reconcileBrokers, type Binding, type Flow import type { Probe } from "../mqtt/probe.ts"; const MINTED = "mesh-minted-password"; -const binding = (at = "ace.internal"): Binding => ({ provision: "mqtt-topic", from: "ace", at, as: "mesh_ace_nodered", serves: { scheme: "mqtt", port: 1883 } }); +const binding = (at = "node-a.internal"): Binding => ({ provision: "mqtt-topic", from: "node-a", at, as: "mesh_node_a_nodered", serves: { scheme: "mqtt", port: 1883 } }); -/** ace's flows, reduced: its one broker node (dead, zurag.be:1884) and a node that uses it. */ -function aceFlows(): FlowNode[] { +/** node-a's flows, reduced: its one broker node (dead, zurag.be:1884) and a node that uses it. */ +function nodeAFlows(): FlowNode[] { return [ { id: "2b0aece9c5f3b307", type: "mqtt-broker", name: "MQTT Broker", broker: "zurag.be", port: "1884", clientid: "", usetls: false, protocolVersion: "4", keepalive: "60" }, { id: "fe0cae96f1e3ae4d", type: "mqtt in", topic: "stat/sonoff_office_light_switch/RESULT", broker: "2b0aece9c5f3b307", z: "t" }, @@ -52,17 +52,17 @@ const marks = (): Marks & { store: Map } => { const store = new Map(); return { store, get: async (k) => store.get(k), set: async (k, v) => void store.set(k, v) }; }; -const takes: Probe = async (_h, _p, user, pass) => ({ connack: user === "mesh_ace_nodered" && pass === MINTED ? 0 : 5, suback: 0 }); +const takes: Probe = async (_h, _p, user, pass) => ({ connack: user === "mesh_node_a_nodered" && pass === MINTED ? 0 : 5, suback: 0 }); -test("ace: the named broker node is moved to the bound broker and login; the other broker is not touched", async () => { - const f = fakeNodeRed(aceFlows(), { "2b0aece9c5f3b307": { user: "luffy", password: "old" }, "other-broker": { user: "x", password: "y" } }); +test("node-a: the named broker node is moved to the bound broker and login; the other broker is not touched", async () => { + const f = fakeNodeRed(nodeAFlows(), { "2b0aece9c5f3b307": { user: "luffy", password: "old" }, "other-broker": { user: "x", password: "y" } }); const m = marks(); const out = await reconcileBrokers({ nodered: f.nodered, probe: takes, marks: m }, binding(), `${MINTED}\n`, ["2b0aece9c5f3b307"]); assert.deepEqual(out, [{ what: "broker 2b0aece9c5f3b307", result: "written", fields: ["broker", "port", "user", "password"] }]); const node = f.flows.find((n) => n.id === "2b0aece9c5f3b307"); - assert.deepEqual(node, { ...aceFlows()[0], broker: "ace.internal", port: "1883", usetls: false }); - assert.deepEqual(f.creds["2b0aece9c5f3b307"], { user: "mesh_ace_nodered", password: MINTED }); - assert.deepEqual(f.flows.find((n) => n.id === "other-broker"), aceFlows()[2]); + assert.deepEqual(node, { ...nodeAFlows()[0], broker: "node-a.internal", port: "1883", usetls: false }); + assert.deepEqual(f.creds["2b0aece9c5f3b307"], { user: "mesh_node_a_nodered", password: MINTED }); + assert.deepEqual(f.flows.find((n) => n.id === "other-broker"), nodeAFlows()[2]); assert.deepEqual(f.creds["other-broker"], { user: "x", password: "y" }); // Only the changed node carried credentials in the deploy. assert.deepEqual(f.deploys[0].filter((n) => n.credentials).map((n) => n.id), ["2b0aece9c5f3b307"]); @@ -78,19 +78,19 @@ test("fresh: with nothing named, the step makes its own broker node", async () = const out = await reconcileBrokers({ nodered: f.nodered, probe: takes, marks: marks() }, binding(), MINTED, []); assert.deepEqual(out, [{ what: `broker ${MESH_BROKER_ID}`, result: "written", fields: ["node"] }]); assert.equal(f.flows[0].type, "mqtt-broker"); - assert.equal(f.flows[0].broker, "ace.internal"); - assert.deepEqual(f.creds[MESH_BROKER_ID], { user: "mesh_ace_nodered", password: MINTED }); + assert.equal(f.flows[0].broker, "node-a.internal"); + assert.deepEqual(f.creds[MESH_BROKER_ID], { user: "mesh_node_a_nodered", password: MINTED }); }); test("a login the broker does not take is never written", async () => { - const f = fakeNodeRed(aceFlows()); + const f = fakeNodeRed(nodeAFlows()); const out = await reconcileBrokers({ nodered: f.nodered, probe: async () => ({ connack: 5 }), marks: marks() }, binding(), MINTED, ["2b0aece9c5f3b307"]); assert.equal(out[0].result, "refused"); assert.equal(f.deploys.length, 0); }); test("a named node that is not there, or a loopback broker, is refused", async () => { - const f = fakeNodeRed(aceFlows()); + const f = fakeNodeRed(nodeAFlows()); const out = await reconcileBrokers({ nodered: f.nodered, probe: takes, marks: marks() }, binding(), MINTED, ["gone"]); assert.match((out[0] as { problem: string }).problem, /no such node/); const lo = await reconcileBrokers({ nodered: f.nodered, probe: takes, marks: marks() }, binding("127.0.0.1"), MINTED, []); @@ -99,7 +99,7 @@ test("a named node that is not there, or a loopback broker, is refused", async ( }); test("a deploy that raced another is read again once", async () => { - const f = fakeNodeRed(aceFlows()); + const f = fakeNodeRed(nodeAFlows()); let first = true; const racing: NodeRed = { ...f.nodered, diff --git a/modules/telegram/cmd/telegram/channel_test.go b/modules/telegram/cmd/telegram/channel_test.go index 06c96121..0c1be4f0 100644 --- a/modules/telegram/cmd/telegram/channel_test.go +++ b/modules/telegram/cmd/telegram/channel_test.go @@ -217,7 +217,7 @@ func TestAQuestionIsShownWithItsTicketsAndRingsAndAWarningIsSilent(t *testing.T) if f.of("sendMessage")[1].Body["disable_notification"] != true { t.Error("a clearing rang (D4)") } - subject, body = work(asks.Send, asks.Message{Handle: "m3", Title: "Urgent: ace silent", Urgent: true, To: "42"}) + subject, body = work(asks.Send, asks.Message{Handle: "m3", Title: "Urgent: node-a silent", Urgent: true, To: "42"}) _ = c.Take(subject, body) if f.of("sendMessage")[2].Body["disable_notification"] != false { t.Error("an urgent message was silent (D4)") @@ -243,7 +243,7 @@ func TestALongMessageIsCutAndTheCutSaid(t *testing.T) { // nor injects. The tap on it is still compared by the plain words, which is what Telegram gives back. func TestAMessageIsRenderedInHTMLWithItsMarkupEscaped(t *testing.T) { c, f, s, _ := newChannel(t, goodToken) - subject, body := work(asks.Show, asks.Message{Handle: "q1", Title: "Set mounts on & co?", + subject, body := work(asks.Show, asks.Message{Handle: "q1", Title: "Set mounts on & co?", Body: "Changes two settings.\n+ shares: media=/storage/media\n~ sources: a=b (was: c)", Note: "Asked by mesh-controller at 15:11.\nFingerprint 1234 5678 9abc.", To: "42", Buttons: []asks.Button{{Label: "Approve", Ticket: "tkt"}}}) @@ -251,7 +251,7 @@ func TestAMessageIsRenderedInHTMLWithItsMarkupEscaped(t *testing.T) { t.Fatal(err) } sent := f.of("sendMessage") - want := "Set mounts on <shanks> & co?\nChanges two settings.\n+ shares: media=/storage/media\n" + + want := "Set mounts on <node-d> & co?\nChanges two settings.\n+ shares: media=/storage/media\n" + "~ sources: a=b (was: c)\n\n
Asked by mesh-controller at 15:11.\nFingerprint 1234 5678 9abc.
" if len(sent) != 1 || sent[0].Body["text"] != want || sent[0].Body["parse_mode"] != "HTML" { t.Fatalf("sent %v", sent) @@ -262,7 +262,7 @@ func TestAMessageIsRenderedInHTMLWithItsMarkupEscaped(t *testing.T) { // Telegram gives the words back plain, the space around the blockquote as it pleases: the tap on them is taken. c.Handle(Update{UpdateID: 1, Callback: &Callback{ID: "cb1", Data: "tkt", From: User{ID: 42, FirstName: "Jo"}, Message: &Msg{MessageID: shown, Chat: Chat{ID: 42, Type: "private"}, - Text: "Set mounts on & co?\nChanges two settings.\n+ shares: media=/storage/media\n~ sources: a=b (was: c)\n" + + Text: "Set mounts on & co?\nChanges two settings.\n+ shares: media=/storage/media\n~ sources: a=b (was: c)\n" + "Asked by mesh-controller at 15:11.\nFingerprint 1234 5678 9abc."}}}) if got := s.of(asks.IntakeSubject(asks.Chosen, Kind)); len(got) != 1 { t.Fatalf("the tap on the rendered message was not taken: %s", got) @@ -270,20 +270,20 @@ func TestAMessageIsRenderedInHTMLWithItsMarkupEscaped(t *testing.T) { // Words changed by another holder of the token are still told apart. c.Handle(Update{UpdateID: 2, Callback: &Callback{ID: "cb2", Data: "tkt", From: User{ID: 42, FirstName: "Jo"}, Message: &Msg{MessageID: shown, Chat: Chat{ID: 42, Type: "private"}, - Text: "Set mounts on & co?\nChanges three settings.\n+ shares: media=/storage/media\n~ sources: a=b (was: c)\n" + + Text: "Set mounts on & co?\nChanges three settings.\n+ shares: media=/storage/media\n~ sources: a=b (was: c)\n" + "Asked by mesh-controller at 15:11.\nFingerprint 1234 5678 9abc."}}}) if got := s.of(asks.IntakeSubject(asks.Chosen, Kind)); len(got) != 1 { t.Fatalf("a tap on changed words was taken: %s", got) } // The edit says what was chosen, one line with the headline, and is in the same mode. - subject, body = work(asks.Edit, asks.Message{Handle: "q1", Title: "You chose Approve at 15:06 on Telegram · Set mounts on & co?", + subject, body = work(asks.Edit, asks.Message{Handle: "q1", Title: "You chose Approve at 15:06 on Telegram · Set mounts on & co?", Note: "Told to mesh-controller, which acts on it itself.", To: "42"}) if err := c.Take(subject, body); err != nil { t.Fatal(err) } ed := f.of("editMessageText") if len(ed) != 1 || ed[0].Body["parse_mode"] != "HTML" || - ed[0].Body["text"] != "You chose Approve at 15:06 on Telegram · Set mounts on <shanks> & co?\n\n
Told to mesh-controller, which acts on it itself.
" { + ed[0].Body["text"] != "You chose Approve at 15:06 on Telegram · Set mounts on <node-d> & co?\n\n
Told to mesh-controller, which acts on it itself.
" { t.Errorf("edited %v", ed) } // A plain answer in the chat is escaped too. @@ -657,7 +657,7 @@ func TestAToastIsCutAtTelegramsBound(t *testing.T) { // loses its buttons. A new handle is a new message, and nothing is deleted. func TestAMessageSaidAgainUnderItsHandleReplacesTheEarlierOne(t *testing.T) { c, f, _, st := newChannel(t, goodToken) - subject, body := work(asks.Show, asks.Message{Handle: "m1", Title: "Urgent: ace silent", Urgent: true, To: "42", + subject, body := work(asks.Show, asks.Message{Handle: "m1", Title: "Urgent: node-a silent", Urgent: true, To: "42", Buttons: []asks.Button{{Label: "Silence for a week", Ticket: "0123456789abcdef0123456789abcdef"}}}) if err := c.Take(subject, body); err != nil { t.Fatal(err) @@ -668,7 +668,7 @@ func TestAMessageSaidAgainUnderItsHandleReplacesTheEarlierOne(t *testing.T) { if len(f.of("deleteMessage")) != 0 { t.Fatal("a new handle deleted a message") } - subject, body = work(asks.Show, asks.Message{Handle: "m1", Title: "Still open: ace silent", Urgent: true, To: "42", + subject, body = work(asks.Show, asks.Message{Handle: "m1", Title: "Still open: node-a silent", Urgent: true, To: "42", Buttons: []asks.Button{{Label: "Silence for a week", Ticket: "fedcba9876543210fedcba9876543210"}}}) if err := c.Take(subject, body); err != nil { t.Fatal(err) @@ -686,7 +686,7 @@ func TestAMessageSaidAgainUnderItsHandleReplacesTheEarlierOne(t *testing.T) { return 400, `{"ok":false,"error_code":400,"description":"Bad Request: message can't be deleted"}` } second := st.placed["m1"].ID - subject, body = work(asks.Send, asks.Message{Handle: "m1", Title: "Now urgent: ace silent", Urgent: true, To: "42"}) + subject, body = work(asks.Send, asks.Message{Handle: "m1", Title: "Now urgent: node-a silent", Urgent: true, To: "42"}) _ = c.Take(subject, body) ed := f.of("editMessageText") if len(ed) != 1 || ed[0].Body["message_id"] != float64(second) || !strings.Contains(ed[0].Body["text"].(string), "Replaced") { @@ -705,7 +705,7 @@ func TestAReplacementThatCannotBeSentLeavesTheEarlierMessage(t *testing.T) { f.answer["sendMessage"] = func(map[string]any) (int, string) { return 400, `{"ok":false,"error_code":400,"description":"Bad Request: chat not found"}` } - subject, body := work(asks.Send, asks.Message{Handle: "m1", Title: "Still open: ace silent", Urgent: true, To: "42"}) + subject, body := work(asks.Send, asks.Message{Handle: "m1", Title: "Still open: node-a silent", Urgent: true, To: "42"}) _ = c.Take(subject, body) if len(f.of("deleteMessage")) != 0 || st.placed["m1"].ID != 7 { t.Fatalf("the earlier message was taken away though its replacement was not sent: %+v", f.of("deleteMessage")) diff --git a/modules/telegram/cmd/telegram/render_test.go b/modules/telegram/cmd/telegram/render_test.go index 963136d8..a678fb12 100644 --- a/modules/telegram/cmd/telegram/render_test.go +++ b/modules/telegram/cmd/telegram/render_test.go @@ -20,7 +20,7 @@ var adr0343 = asks.Message{Handle: "h-343", To: "42", "• A deleted file is marked, and a newer change elsewhere outlives the deletion", Note: "Asked by mesh-knowledge at 16:05. Unanswered by tomorrow 15:55: the record stays proposed; nothing of it is in force.\n" + "Approve: the record is accepted and its clauses are in force. Decline: the record stays proposed; nothing of it is in force.\n" + - "ADR 0343, proposed by fix-367@g14; the knowledge base's own review approved it. Fingerprint a59f 361b f60e cb5e d237 a837.\n" + + "ADR 0343, proposed by fix-367@node-b; the knowledge base's own review approved it. Fingerprint a59f 361b f60e cb5e d237 a837.\n" + "Read its 13 clauses with the knowledge base's get, number 343.", Buttons: []asks.Button{{Label: "Approve", Ticket: "t-approve"}, {Label: "Decline", Ticket: "t-decline"}}} From 3b89d398fa1a2d152f15cd480f171ffe08729dfc Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 22 Oct 2026 21:28:54 +0200 Subject: [PATCH 2/5] Name no node in messenger's fixtures (issue 1838) --- .../cmd/messenger/adr505_bus_test.go | 20 +- .../messenger/cmd/messenger/adr505_test.go | 116 +-- .../messenger/cmd/messenger/answers_test.go | 16 +- .../messenger/cmd/messenger/condition_test.go | 14 +- .../messenger/cmd/messenger/content_test.go | 12 +- .../messenger/cmd/messenger/details_test.go | 12 +- .../messenger/cmd/messenger/glance_test.go | 4 +- .../messenger/cmd/messenger/history_test.go | 30 +- .../messenger/cmd/messenger/holder_test.go | 36 +- .../messenger/cmd/messenger/manifest_test.go | 2 +- .../cmd/messenger/onemessage_test.go | 46 +- .../messenger/cmd/messenger/preview_test.go | 10 +- .../messenger/cmd/messenger/replaced_test.go | 4 +- .../messenger/cmd/messenger/restart_test.go | 26 +- .../messenger/cmd/messenger/review_test.go | 4 +- .../testdata/backlog-2026-10-06.json | 892 +++++++++--------- .../messenger/cmd/messenger/tracking_test.go | 48 +- modules/messenger/cmd/messenger/walks_test.go | 136 +-- modules/messenger/cmd/messenger/whole_test.go | 8 +- modules/messenger/cmd/messenger/words_test.go | 74 +- 20 files changed, 755 insertions(+), 755 deletions(-) diff --git a/modules/messenger/cmd/messenger/adr505_bus_test.go b/modules/messenger/cmd/messenger/adr505_bus_test.go index 440ca55e..467bb20b 100644 --- a/modules/messenger/cmd/messenger/adr505_bus_test.go +++ b/modules/messenger/cmd/messenger/adr505_bus_test.go @@ -30,8 +30,8 @@ func (b *conditionBed) controllerEvent(t *testing.T, event string, body any) { func walkEvent(phase, outcome string, started, at time.Time) map[string]any { b := map[string]any{"id": "plan-bus", "state": "walking", "walk": "plan-bus", "phase": phase, "budget_class": "leaf", "bound_seconds": 600, "started_at": started.UTC().Format(time.RFC3339Nano), - "touches": []map[string]any{{"machine": "novox", "modules": []string{"gitea"}}, - {"machine": "shanks", "modules": []string{"mesh-build-image"}, "declared": true}}} + "touches": []map[string]any{{"machine": "node-c", "modules": []string{"gitea"}}, + {"machine": "node-d", "modules": []string{"mesh-build-image"}, "declared": true}}} if phase == WalkEnded { b["outcome"], b["ended_at"] = outcome, at.UTC().Format(time.RFC3339Nano) } @@ -64,23 +64,23 @@ func TestAWalksDeclaredMachineIsHeldUntilItSettledOverTheBus(t *testing.T) { b := newConditionBedWith(t, `{"settle-seconds": 2}`) started := time.Now() b.controllerEvent(t, EventPlanMoved, walkEvent(WalkStarted, "", started, started)) - b.controllerEvent(t, EventRaised, conditionEvent("machine.shanks.uncomposable", "machine", "shanks", "shanks", - "Shanks cannot get new instructions")) - b.controllerEvent(t, EventRaised, conditionEvent("machine.ace.silent", "machine", "ace", "ace", "Ace is silent")) + b.controllerEvent(t, EventRaised, conditionEvent("machine.node-d.uncomposable", "machine", "node-d", "node-d", + "Node-d cannot get new instructions")) + b.controllerEvent(t, EventRaised, conditionEvent("machine.node-a.silent", "machine", "node-a", "node-a", "Node-a is silent")) b.r.until("the untouched machine's condition reaches the desk with its delivery line", 15*time.Second, func() bool { - m := b.toldWith("Ace is silent") + m := b.toldWith("Node-a is silent") return m != nil && strings.HasSuffix(*m, "\nNo delivery running.") }) - if b.toldWith("Shanks cannot get new instructions") != nil { + if b.toldWith("Node-d cannot get new instructions") != nil { t.Fatalf("the declared machine's condition was told during the walk") } b.controllerEvent(t, EventPlanMoved, walkEvent(WalkEnded, WalkDelivered, started, time.Now())) time.Sleep(time.Second) - if b.toldWith("Shanks cannot get new instructions") != nil || b.toldWith("Delivered") != nil { + if b.toldWith("Node-d cannot get new instructions") != nil || b.toldWith("Delivered") != nil { t.Fatalf("told before the settle passed: %+v", b.told()) } b.r.until("the walk's end tells what it held once it settled", 30*time.Second, func() bool { - m := b.toldWith("Still open after the delivery of gitea to novox:") - return m != nil && strings.Contains(*m, "Shanks cannot get new instructions") && !strings.Contains(*m, "shanks,") + m := b.toldWith("Still open after the delivery of gitea to node-c:") + return m != nil && strings.Contains(*m, "Node-d cannot get new instructions") && !strings.Contains(*m, "node-d,") }) } diff --git a/modules/messenger/cmd/messenger/adr505_test.go b/modules/messenger/cmd/messenger/adr505_test.go index 541b0f4f..41fa5771 100644 --- a/modules/messenger/cmd/messenger/adr505_test.go +++ b/modules/messenger/cmd/messenger/adr505_test.go @@ -61,7 +61,7 @@ func controllerConditions(c *clock) []Condition { // open, whatever name their keys give the controller and whatever host they name. func TestTheControllersOwnConditionsAreHeldWhileAWalkMovesMeshController(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - walk(t, h, "plan-c", WalkStarted, "", c.now(), 1200, novox("mesh-controller")) + walk(t, h, "plan-c", WalkStarted, "", c.now(), 1200, nodeC("mesh-controller")) for _, k := range controllerConditions(c) { h.Condition(EventRaised, k) } @@ -79,7 +79,7 @@ func TestTheControllersOwnConditionsAreHeldWhileAWalkMovesMeshController(t *test // ADR 0505 §2a: a walk that does not move mesh-controller holds none of them. func TestTheControllersOwnConditionsAreNotHeldByAWalkOfAnotherModule(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - walk(t, h, "plan-g", WalkStarted, "", c.now(), 1200, Touch{Machine: "ace", Modules: []string{"gitea"}}) + walk(t, h, "plan-g", WalkStarted, "", c.now(), 1200, Touch{Machine: "node-a", Modules: []string{"gitea"}}) for _, k := range controllerConditions(c) { h.Condition(EventRaised, k) } @@ -91,32 +91,32 @@ func TestTheControllersOwnConditionsAreNotHeldByAWalkOfAnotherModule(t *testing. } } -// shanksDeclared is a touch as the controller says a machine whose declaration the walk's merges change and to which +// nodeDDeclared is a touch as the controller says a machine whose declaration the walk's merges change and to which // it sends nothing (mesh-controller walk_said.go walkTouch, `declared`, ADR 0505 §2b). -var shanksDeclared = Touch{Machine: "shanks", Modules: []string{"mesh-build-image"}, Declared: true} +var nodeDDeclared = Touch{Machine: "node-d", Modules: []string{"mesh-build-image"}, Declared: true} // ADR 0505 §2b: a machine whose declaration a walk's merges change is held like a machine it sends to, and is not // named among the machines the walk reached. func TestAMachineWhoseDeclarationTheWalkChangesIsHeldAndNotNamedAsReached(t *testing.T) { ev, ok, err := DecodeWalk([]byte(`{"id":"plan-d","walk":"plan-d","phase":"started","budget_class":"leaf",` + - `"bound_seconds":600,"touches":[{"machine":"novox","modules":["gitea"]},` + - `{"machine":"shanks","modules":["mesh-build-image"],"declared":true}]}`)) + `"bound_seconds":600,"touches":[{"machine":"node-c","modules":["gitea"]},` + + `{"machine":"node-d","modules":["mesh-build-image"],"declared":true}]}`)) if err != nil || !ok || len(ev.Touches) != 2 || !ev.Touches[1].Declared || ev.Touches[0].Declared { t.Fatalf("a declared touch was not read: %+v %v %v", ev.Touches, ok, err) } h, tg, dt, c, _ := newHolder(t) - walk(t, h, "plan-d", WalkStarted, "", c.now(), 600, novox("gitea"), shanksDeclared) - k := cond("machine.shanks.uncomposable", Urgent, "shanks cannot get new instructions") - k.Machine, k.Raised = "shanks", c.now() + walk(t, h, "plan-d", WalkStarted, "", c.now(), 600, nodeC("gitea"), nodeDDeclared) + k := cond("machine.node-d.uncomposable", Urgent, "node-d cannot get new instructions") + k.Machine, k.Raised = "node-d", c.now() h.Condition(EventRaised, k) runFor(h, c, time.Minute) if !has(outcomes(h, k.Key), "held") || heard(headlineOf(k.Key), tg, dt) { t.Fatalf("a condition on the declared machine was not held: %v", outcomes(h, k.Key)) } - if got := touchWords(mergeTouches([]Touch{novox("gitea"), shanksDeclared}, nil)); got != "gitea on novox" { - t.Fatalf("what the walk reached reads %q, want only novox", got) + if got := touchWords(mergeTouches([]Touch{nodeC("gitea"), nodeDDeclared}, nil)); got != "gitea on node-c" { + t.Fatalf("what the walk reached reads %q, want only node-c", got) } - if got := mergeTouches([]Touch{shanksDeclared}, []Touch{{Machine: "shanks", Modules: []string{"buildah"}}}); got[0].Declared { + if got := mergeTouches([]Touch{nodeDDeclared}, []Touch{{Machine: "node-d", Modules: []string{"buildah"}}}); got[0].Declared { t.Fatalf("a machine the walk also sends to stayed declared: %+v", got) } } @@ -127,12 +127,12 @@ func TestAMachineWhoseDeclarationTheWalkChangesIsHeldAndNotNamedAsReached(t *tes func TestAConditionRaisedInTheSettleIsHeldAndToldAtItsEnd(t *testing.T) { for _, clears := range []bool{false, true} { h, tg, dt, c, _ := newHolder(t) - walk(t, h, "plan-s", WalkStarted, "", c.now(), 600, novox("gitea")) + walk(t, h, "plan-s", WalkStarted, "", c.now(), 600, nodeC("gitea")) runFor(h, c, 3*time.Minute) - walk(t, h, "plan-s", WalkEnded, WalkDelivered, c.now(), 0, novox("gitea")) + walk(t, h, "plan-s", WalkEnded, WalkDelivered, c.now(), 0, nodeC("gitea")) c.pass(30 * time.Second) - k := cond("machine.novox.uncomposable", Urgent, "novox cannot get new instructions") - k.Machine, k.Raised = "novox", c.now() + k := cond("machine.node-c.uncomposable", Urgent, "node-c cannot get new instructions") + k.Machine, k.Raised = "node-c", c.now() h.Condition(EventRaised, k) runFor(h, c, time.Minute) if heard(headlineOf(k.Key), tg, dt) || !has(outcomes(h, k.Key), "held") { @@ -146,7 +146,7 @@ func TestAConditionRaisedInTheSettleIsHeldAndToldAtItsEnd(t *testing.T) { } runFor(h, c, time.Minute) switch { - case !clears && !heard("Still open after the delivery of gitea to novox:\n- Urgent: "+headlineOf(k.Key), tg, dt): + case !clears && !heard("Still open after the delivery of gitea to node-c:\n- Urgent: "+headlineOf(k.Key), tg, dt): t.Fatalf("still open at the settle's end and not told under the delivery: %+v", dt.sends) case clears && (heard(headlineOf(k.Key), tg, dt) || !heard("1 problem it raised resolved during it.", dt)): t.Fatalf("cleared in the settle: told, or not counted: %+v", dt.sends) @@ -158,7 +158,7 @@ func TestAConditionRaisedInTheSettleIsHeldAndToldAtItsEnd(t *testing.T) { // any other message, and told at the settle's end only when the condition is still open. func TestAReminderDuringAWalkIsHeld(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - k := cond("machine.novox.network", Urgent, "novox lost its default route") + k := cond("machine.node-c.network", Urgent, "node-c lost its default route") k.Raised = c.now() h.Condition(EventRaised, k) runFor(h, c, time.Minute) @@ -167,7 +167,7 @@ func TestAReminderDuringAWalkIsHeld(t *testing.T) { t.Fatalf("the condition was not said before the walk") } runFor(h, c, RemindUrgent-3*time.Minute) - walk(t, h, "plan-r", WalkStarted, "", c.now(), 1200, novox("node-tools")) + walk(t, h, "plan-r", WalkStarted, "", c.now(), 1200, nodeC("node-tools")) runFor(h, c, 5*time.Minute) if saidOn(tg, dt) != first { t.Fatalf("the reminder was said during the walk: %+v", dt.sends) @@ -177,7 +177,7 @@ func TestAReminderDuringAWalkIsHeld(t *testing.T) { } walk(t, h, "plan-r", WalkEnded, WalkDelivered, c.now(), 0) runFor(h, c, DefaultSettle+time.Minute) - if !heard("Still open after the delivery of node-tools to novox:", dt) { + if !heard("Still open after the delivery of node-tools to node-c:", dt) { t.Fatalf("the held reminder was not told at the settle's end: %+v", dt.sends) } } @@ -185,7 +185,7 @@ func TestAReminderDuringAWalkIsHeld(t *testing.T) { // ADR 0505 §3: a router that starts again while a walk settles holds on and tells its end once the settle passed. func TestAWalkThatSettlesSurvivesARouterRestart(t *testing.T) { h, tg, dt, c, st := newHolder(t) - walk(t, h, "plan-x", WalkStarted, "", c.now(), 1200, novox("mesh-tools")) + walk(t, h, "plan-x", WalkStarted, "", c.now(), 1200, nodeC("mesh-tools")) runFor(h, c, time.Minute) walk(t, h, "plan-x", WalkEnded, WalkDelivered, c.now(), 0) c.pass(10 * time.Second) @@ -194,7 +194,7 @@ func TestAWalkThatSettlesSurvivesARouterRestart(t *testing.T) { t.Fatal(err) } again.Start() - k := cond("machine.novox.tools-silent", Urgent, "the tools on novox are silent") + k := cond("machine.node-c.tools-silent", Urgent, "the tools on node-c are silent") k.Raised = c.now() again.Condition(EventRaised, k) runFor(again, c, time.Minute) @@ -202,10 +202,10 @@ func TestAWalkThatSettlesSurvivesARouterRestart(t *testing.T) { t.Fatalf("not held by the settling walk read back: %v", outcomes(again, k.Key)) } runFor(again, c, DefaultSettle) - if !heard("Still open after the delivery of mesh-tools to novox:\n- Urgent: "+headlineOf(k.Key), tg, dt) { + if !heard("Still open after the delivery of mesh-tools to node-c:\n- Urgent: "+headlineOf(k.Key), tg, dt) { t.Fatalf("the settled walk's end was not told after the restart: %+v", dt.sends) } - walk(t, again, "plan-x", WalkStarted, "", c.now().Add(-5*time.Minute), 1200, novox("mesh-tools")) + walk(t, again, "plan-x", WalkStarted, "", c.now().Add(-5*time.Minute), 1200, nodeC("mesh-tools")) if len(again.walks) != 0 { t.Fatalf("its late start opened it again: %+v", again.walks) } @@ -216,13 +216,13 @@ func TestAWalkThatSettlesSurvivesARouterRestart(t *testing.T) { func TestAConditionJustAfterAFailedWalkIsSentAtOnceAndAfterADeliveredOneHeld(t *testing.T) { for _, outcome := range []string{WalkFailed, WalkStopped, WalkDelivered} { h, tg, dt, c, _ := newHolder(t) - walk(t, h, "plan-f", WalkStarted, "", c.now(), 600, novox("gitea")) - walk(t, h, "plan-o", WalkStarted, "", c.now(), 1200, novox("mesh-issues")) + walk(t, h, "plan-f", WalkStarted, "", c.now(), 600, nodeC("gitea")) + walk(t, h, "plan-o", WalkStarted, "", c.now(), 1200, nodeC("mesh-issues")) runFor(h, c, 2*time.Minute) - walk(t, h, "plan-f", WalkEnded, outcome, c.now(), 0, novox("gitea")) + walk(t, h, "plan-f", WalkEnded, outcome, c.now(), 0, nodeC("gitea")) runFor(h, c, 30*time.Second) - k := cond("machine.novox.uncomposable", Urgent, "novox cannot get new instructions") - k.Machine, k.Raised = "novox", c.now() + k := cond("machine.node-c.uncomposable", Urgent, "node-c cannot get new instructions") + k.Machine, k.Raised = "node-c", c.now() h.Condition(EventRaised, k) runFor(h, c, 30*time.Second) sent := heard(headlineOf(k.Key), tg, dt) @@ -238,12 +238,12 @@ func TestAConditionJustAfterAFailedWalkIsSentAtOnceAndAfterADeliveredOneHeld(t * // ADR 0505 §6: an urgent condition on a machine no open or settling walk touches is sent at once during a walk. func TestAnUrgentConditionOnAnUntouchedMachineIsSentAtOnceDuringAWalk(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - walk(t, h, "plan-u", WalkStarted, "", c.now(), 1200, novox("gitea")) - k := cond("machine.ace.silent", Urgent, "ace has not been heard") - k.Machine, k.Raised = "ace", c.now() + walk(t, h, "plan-u", WalkStarted, "", c.now(), 1200, nodeC("gitea")) + k := cond("machine.node-a.silent", Urgent, "node-a has not been heard") + k.Machine, k.Raised = "node-a", c.now() h.Condition(EventRaised, k) if !heard(headlineOf(k.Key), tg, dt) { - t.Fatalf("held, while no walk touches ace: %v", outcomes(h, k.Key)) + t.Fatalf("held, while no walk touches node-a: %v", outcomes(h, k.Key)) } } @@ -263,30 +263,30 @@ func bodyOf(t *testing.T, h *Holder, key, what string) string { // walk's settle, after a failed walk, and with no walk. func TestEveryProblemMessageEndsWithWhetherADeliveryRan(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - k := cond("machine.novox.tools-silent", Urgent, "the tools on novox are silent") + k := cond("machine.node-c.tools-silent", Urgent, "the tools on node-c are silent") k.Raised = c.now() h.Condition(EventRaised, k) if !strings.HasSuffix(tg.sends[0].Body, ".\nNo delivery running.") || !strings.Contains(tg.sends[0].Body, "\nSince ") { t.Fatalf("no walk: %q", tg.sends[0].Body) } - walk(t, h, "plan-l", WalkStarted, "", c.now(), 600, novox("gitea", "mesh-issues"), shanksDeclared) - if b := bodyOf(t, h, k.Key, "reminder"); !strings.HasSuffix(b, ".\nDuring the delivery of gitea, mesh-issues to novox.") { + walk(t, h, "plan-l", WalkStarted, "", c.now(), 600, nodeC("gitea", "mesh-issues"), nodeDDeclared) + if b := bodyOf(t, h, k.Key, "reminder"); !strings.HasSuffix(b, ".\nDuring the delivery of gitea, mesh-issues to node-c.") { t.Fatalf("during a walk: %q", b) } runFor(h, c, time.Minute) walk(t, h, "plan-l", WalkEnded, WalkDelivered, c.now(), 0) c.pass(40 * time.Second) - if b := bodyOf(t, h, k.Key, "raised"); !strings.HasSuffix(b, "\n40 s after the delivery of gitea, mesh-issues to novox, which succeeded.") { + if b := bodyOf(t, h, k.Key, "raised"); !strings.HasSuffix(b, "\n40 s after the delivery of gitea, mesh-issues to node-c, which succeeded.") { t.Fatalf("in the settle of a delivered walk: %q", b) } runFor(h, c, 3*time.Minute) if b := bodyOf(t, h, k.Key, "reminder"); !strings.HasSuffix(b, "\nNo delivery running.") { t.Fatalf("after the settle: %q", b) } - walk(t, h, "plan-m", WalkStarted, "", c.now(), 600, novox("gitea")) + walk(t, h, "plan-m", WalkStarted, "", c.now(), 600, nodeC("gitea")) walk(t, h, "plan-m", WalkEnded, WalkFailed, c.now(), 0) c.pass(30 * time.Second) - if b := bodyOf(t, h, k.Key, "reminder"); !strings.HasSuffix(b, "\n30 s after the delivery of gitea to novox, which failed.") { + if b := bodyOf(t, h, k.Key, "reminder"); !strings.HasSuffix(b, "\n30 s after the delivery of gitea to node-c, which failed.") { t.Fatalf("after a failed walk: %q", b) } keyless(t, dt.sends...) @@ -303,13 +303,13 @@ func TestEveryProblemMessageEndsWithWhetherADeliveryRan(t *testing.T) { // ADR 0505 §1: the line names at most six modules and counts the rest, and says no name the content rule refuses. func TestTheDeliveryLineNamesAtMostSixModulesAndNothingTheRuleRefuses(t *testing.T) { - many := novox("a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8") - if got := deliveryWords([]Touch{many}); got != "a1, a2, a3, a4, a5, a6 and 2 more to novox" { + many := nodeC("a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8") + if got := deliveryWords([]Touch{many}); got != "a1, a2, a3, a4, a5, a6 and 2 more to node-c" { t.Fatalf("eight modules: %q", got) } h, _, _, c, _ := newHolder(t) - walk(t, h, "plan-p", WalkStarted, "", c.now(), 600, novox("/var/lib/mesh-tools")) - k := cond("machine.novox.tools-silent", Urgent, "the tools on novox are silent") + walk(t, h, "plan-p", WalkStarted, "", c.now(), 600, nodeC("/var/lib/mesh-tools")) + k := cond("machine.node-c.tools-silent", Urgent, "the tools on node-c are silent") k.Raised = c.now() h.Condition(EventRaised, k) if b := bodyOf(t, h, k.Key, "raised"); !strings.HasSuffix(b, "\nDuring a delivery.") { @@ -323,18 +323,18 @@ func TestTheDeliveryLineNamesAtMostSixModulesAndNothingTheRuleRefuses(t *testing func TestADeclaredMachinesConditionAcrossThreeWalksIsSaidAtTheFirstWalksLimit(t *testing.T) { h, tg, dt, c, _ := newHolder(t) t0 := c.now() - walk(t, h, "plan-1", WalkStarted, "", c.now(), 600, novox("gitea"), shanksDeclared) // limit: t0 + 10 + 2 min - k := cond("machine.shanks.uncomposable", Urgent, "shanks cannot get new instructions") - k.Machine, k.Raised = "shanks", c.now() + walk(t, h, "plan-1", WalkStarted, "", c.now(), 600, nodeC("gitea"), nodeDDeclared) // limit: t0 + 10 + 2 min + k := cond("machine.node-d.uncomposable", Urgent, "node-d cannot get new instructions") + k.Machine, k.Raised = "node-d", c.now() h.Condition(EventRaised, k) runFor(h, c, 5*time.Minute) - walk(t, h, "plan-1", WalkEnded, WalkDelivered, c.now(), 0, novox("gitea"), shanksDeclared) + walk(t, h, "plan-1", WalkEnded, WalkDelivered, c.now(), 0, nodeC("gitea"), nodeDDeclared) runFor(h, c, time.Minute) - walk(t, h, "plan-2", WalkStarted, "", c.now(), 600, novox("mesh-issues"), shanksDeclared) + walk(t, h, "plan-2", WalkStarted, "", c.now(), 600, nodeC("mesh-issues"), nodeDDeclared) runFor(h, c, 3*time.Minute) - walk(t, h, "plan-2", WalkEnded, WalkDelivered, c.now(), 0, novox("mesh-issues"), shanksDeclared) + walk(t, h, "plan-2", WalkEnded, WalkDelivered, c.now(), 0, nodeC("mesh-issues"), nodeDDeclared) runFor(h, c, time.Minute) - walk(t, h, "plan-3", WalkStarted, "", c.now(), 1200, novox("gitea"), shanksDeclared) + walk(t, h, "plan-3", WalkStarted, "", c.now(), 1200, nodeC("gitea"), nodeDDeclared) for c.now().Before(t0.Add(12*time.Minute - 10*time.Second)) { runFor(h, c, 5*time.Second) } @@ -351,14 +351,14 @@ func TestADeclaredMachinesConditionAcrossThreeWalksIsSaidAtTheFirstWalksLimit(t // once: one walk with both sayings' touches, and one end message. func TestAWalkSaidAgainWithItsDeclaredMachinesActsOnce(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - walk(t, h, "plan-r", WalkStarted, "", c.now(), 600, novox("gitea")) - walk(t, h, "plan-r", WalkStarted, "", c.now(), 600, novox("gitea"), shanksDeclared) + walk(t, h, "plan-r", WalkStarted, "", c.now(), 600, nodeC("gitea")) + walk(t, h, "plan-r", WalkStarted, "", c.now(), 600, nodeC("gitea"), nodeDDeclared) if len(h.walks) != 1 || len(h.walks["plan-r"].Touches) != 2 { t.Fatalf("said again it is not one walk with both touches: %+v", h.walks) } runFor(h, c, time.Minute) - walk(t, h, "plan-r", WalkEnded, WalkFailed, c.now(), 0, novox("gitea")) - walk(t, h, "plan-r", WalkEnded, WalkFailed, c.now(), 0, novox("gitea"), shanksDeclared) + walk(t, h, "plan-r", WalkEnded, WalkFailed, c.now(), 0, nodeC("gitea")) + walk(t, h, "plan-r", WalkEnded, WalkFailed, c.now(), 0, nodeC("gitea"), nodeDDeclared) runFor(h, c, 3*time.Minute) n := 0 for _, m := range append(append([]Message(nil), dt.sends...), tg.sends...) { @@ -376,9 +376,9 @@ func TestAWalkSaidAgainWithItsDeclaredMachinesActsOnce(t *testing.T) { func TestAMessageTwoWalksFirstHeldIsSaidOnceAtTheSoonerLimit(t *testing.T) { for _, sev := range []string{Warning, Urgent} { h, tg, dt, c, _ := newHolder(t) - walk(t, h, "plan-a", WalkStarted, "", c.now(), 360, novox("gitea")) // its limit: 6 min and the settle - walk(t, h, "plan-b", WalkStarted, "", c.now(), 1200, novox("mesh-issues")) // its limit: 22 min - k := cond("machine.novox.network", sev, "novox lost its default route") + walk(t, h, "plan-a", WalkStarted, "", c.now(), 360, nodeC("gitea")) // its limit: 6 min and the settle + walk(t, h, "plan-b", WalkStarted, "", c.now(), 1200, nodeC("mesh-issues")) // its limit: 22 min + k := cond("machine.node-c.network", sev, "node-c lost its default route") k.Raised = c.now() h.Condition(EventRaised, k) runFor(h, c, 7*time.Minute) @@ -402,7 +402,7 @@ func TestAMessageTwoWalksFirstHeldIsSaidOnceAtTheSoonerLimit(t *testing.T) { t.Fatalf("%s: said %d times on %s, want %d: %+v", sev, got, ch.name, n, ch.sends) } } - if !heard("Still open after the delivery of gitea to novox:", dt) { + if !heard("Still open after the delivery of gitea to node-c:", dt) { t.Fatalf("%s: not told in the sooner walk's end message: %+v", sev, dt.sends) } } diff --git a/modules/messenger/cmd/messenger/answers_test.go b/modules/messenger/cmd/messenger/answers_test.go index cdffa473..7799d10a 100644 --- a/modules/messenger/cmd/messenger/answers_test.go +++ b/modules/messenger/cmd/messenger/answers_test.go @@ -426,7 +426,7 @@ func TestEveryAnswerThatIsNotTheOperatorsIsRefusedAndSaid(t *testing.T) { "a sender the service did not say": {"telegram", "42", false, 2 * time.Hour, "Release", 0, "did not authenticate"}, "a link younger than an hour": {"telegram", "42", true, 59 * time.Minute, "Release", 0, "can answer this question from"}, "an ask that expired": {"telegram", "42", true, 2 * time.Hour, "Release", 3 * time.Hour, "expired"}, - "a ticket shown on another kind": {"desktop", "g14", true, 2 * time.Hour, "Release", 0, "not offered here"}, + "a ticket shown on another kind": {"desktop", "node-b", true, 2 * time.Hour, "Release", 0, "not offered here"}, } { t.Run(name, func(t *testing.T) { h, tg, _, c, store, w := newRouter(t) @@ -532,13 +532,13 @@ func TestTheDeskAcknowledgesAndNeverApproves(t *testing.T) { submit(t, h, "mesh-delivery", ackAsk(c, "d-1")) settle(h, c) silence := ticketFor(dt.sends[0], "Silence for a week") - ch := choiceOf(silence, "g14", c.now()) + ch := choiceOf(silence, "node-b", c.now()) ch.Sender.Authenticated = false if out, err := h.Chosen("desktop", ch); err != nil || out != "chosen" { t.Fatalf("%s %v", out, err) } got := w.of("mesh-delivery") - if len(got) != 1 || got[0].By.Verified != "a desk click: whoever was at the operator's session on g14" || len(got[0].Proofs) != 0 { + if len(got) != 1 || got[0].By.Verified != "a desk click: whoever was at the operator's session on node-b" || len(got[0].Proofs) != 0 { t.Errorf("%+v", got) } // An approve ticket forged onto the desk is refused: the kind cannot carry it. @@ -553,7 +553,7 @@ func TestTheDeskAcknowledgesAndNeverApproves(t *testing.T) { rec.Tickets[release] = tk store2.asks["mesh-delivery.d-1"] = rec h2.keepAsk("mesh-delivery.d-1", rec, store2.revs["mesh-delivery.d-1"]) - if out, err := h2.Chosen("desktop", choiceOf(release, "g14", c2.now())); err == nil || out != "refused" || + if out, err := h2.Chosen("desktop", choiceOf(release, "node-b", c2.now())); err == nil || out != "refused" || !strings.Contains(err.Error(), "cannot answer a question that asks for an approval") { t.Errorf("the desk approved: %s %v", out, err) } @@ -564,7 +564,7 @@ func TestTheDeskAcknowledgesAndNeverApproves(t *testing.T) { rec.Tickets[silence] = tk store2.asks["mesh-delivery.d-1"] = rec h2.keepAsk("mesh-delivery.d-1", rec, store2.revs["mesh-delivery.d-1"]) - if out, _ := h2.Chosen("desktop", choiceOf(silence, "g14", c2.now())); out != "refused" || + if out, _ := h2.Chosen("desktop", choiceOf(silence, "node-b", c2.now())); out != "refused" || store2.asks["mesh-delivery.d-1"].State != StateOpen { t.Errorf("a desk click ended an ask that waits for an approval: %s", out) } @@ -681,7 +681,7 @@ func TestAnAskAboutAConditionIsAnsweredOnItsMessage(t *testing.T) { t.Errorf("the ask is shown on %q", store.asks["mesh-controller.d-1"].Record) } silence := ticketFor(shown, "Silence for a week") - if out, err := h.Chosen("desktop", choiceOf(silence, "g14", c.now())); err != nil || out != "chosen" { + if out, err := h.Chosen("desktop", choiceOf(silence, "node-b", c.now())); err != nil || out != "chosen" { t.Fatalf("%s %v", out, err) } if got := w.of("mesh-controller"); len(got) != 1 || got[0].About != "delivery.hq.held" { @@ -781,7 +781,7 @@ func TestALinkCodeExpiresAndFiveWrongTriesEndIt(t *testing.T) { t.Errorf("%+v", a) } // The desk cannot be linked: it proves nothing about who clicked. - h.Link("desktop", asks.LinkAsked{ID: "l3", At: c.now(), Sender: asks.Sender{Identity: "g14"}}) + h.Link("desktop", asks.LinkAsked{ID: "l3", At: c.now(), Sender: asks.Sender{Identity: "node-b"}}) if _, pending := store.links["desktop"]; pending { t.Error("the desk began a link") } @@ -1001,7 +1001,7 @@ func TestAWarningTheDeskCouldNotShowGoesAway(t *testing.T) { if len(dt.sends) != 1 { t.Fatalf("the desk was sent %d", len(dt.sends)) } - h.Failed("desktop", asks.Failed{Handle: "g14=1", Why: "no session answers", At: c.now()}) + h.Failed("desktop", asks.Failed{Handle: "node-b=1", Why: "no session answers", At: c.now()}) c.pass(BurstWindow) h.Flush() if len(tg.sends) == 0 { diff --git a/modules/messenger/cmd/messenger/condition_test.go b/modules/messenger/cmd/messenger/condition_test.go index f5a9e485..f6131e77 100644 --- a/modules/messenger/cmd/messenger/condition_test.go +++ b/modules/messenger/cmd/messenger/condition_test.go @@ -27,8 +27,8 @@ func TestTheEventsAreTheControllersSeat(t *testing.T) { func TestAConditionAsTheStoreHoldsIt(t *testing.T) { body := `{ - "key": "machine.ace.silent", "kind": "silent", - "subject": {"scope": "machine", "id": "ace", "machine": "ace"}, + "key": "machine.node-a.silent", "kind": "silent", + "subject": {"scope": "machine", "id": "node-a", "machine": "node-a"}, "severity": "urgent", "summary": "the home server has not been heard for 15 min", "evidence": [{"at": "2026-10-06T12:00:00Z", "what": "last heartbeat"}], "source": "S1", "raised": "2026-10-06T12:15:00Z", "last-observed": "2026-10-06T12:16:00Z", @@ -40,7 +40,7 @@ func TestAConditionAsTheStoreHoldsIt(t *testing.T) { if err != nil { t.Fatal(err) } - if c.Key != "machine.ace.silent" || c.Kind != "silent" || c.Scope != "machine" || c.ID != "ace" || + if c.Key != "machine.node-a.silent" || c.Kind != "silent" || c.Scope != "machine" || c.ID != "node-a" || c.Severity != Urgent || c.Source != "S1" || c.Observations != 3 || c.Resolver != "self" { t.Fatalf("%+v", c) } @@ -50,7 +50,7 @@ func TestAConditionAsTheStoreHoldsIt(t *testing.T) { if !c.SilencedAt(time.Date(2026, 10, 6, 13, 0, 0, 0, time.UTC)) || c.SilencedAt(time.Date(2026, 10, 6, 15, 0, 0, 0, time.UTC)) { t.Fatalf("silenced: %v", c.SilencedTill) } - if c.SubjectWords() != "machine ace" { + if c.SubjectWords() != "machine node-a" { t.Fatalf("subject words: %q", c.SubjectWords()) } } @@ -65,7 +65,7 @@ func TestOtherSpellingsAndAKeyMadeFromItsParts(t *testing.T) { if c.Key != "plan.41.stalled" || c.Source != "S3" || c.LastObserved.IsZero() || !c.SilencedTill.IsZero() { t.Fatalf("%+v", c) } - c, err = DecodeCondition(EventRaised, []byte(`{"key":"provider.keycloak.ace.gitea.failing","subject":"keycloak", + c, err = DecodeCondition(EventRaised, []byte(`{"key":"provider.keycloak.node-a.gitea.failing","subject":"keycloak", "severity":"warning","summary":"the identity provider fails gitea"}`)) if err != nil || c.Scope != "provider" || c.Kind != "failing" || c.ID != "keycloak" { t.Fatalf("%+v %v", c, err) @@ -73,8 +73,8 @@ func TestOtherSpellingsAndAKeyMadeFromItsParts(t *testing.T) { } func TestAClearedEventNeedsOnlyItsKey(t *testing.T) { - c, err := DecodeCondition(EventCleared, []byte(`{"key":"machine.ace.silent","cleared":"2026-10-06T12:30:00Z"}`)) - if err != nil || c.Key != "machine.ace.silent" || c.Cleared.IsZero() { + c, err := DecodeCondition(EventCleared, []byte(`{"key":"machine.node-a.silent","cleared":"2026-10-06T12:30:00Z"}`)) + if err != nil || c.Key != "machine.node-a.silent" || c.Cleared.IsZero() { t.Fatalf("%+v %v", c, err) } } diff --git a/modules/messenger/cmd/messenger/content_test.go b/modules/messenger/cmd/messenger/content_test.go index 9fc23039..038b6f6d 100644 --- a/modules/messenger/cmd/messenger/content_test.go +++ b/modules/messenger/cmd/messenger/content_test.go @@ -5,14 +5,14 @@ import "testing" func TestRolesAndWordsMayLeave(t *testing.T) { for _, s := range []string{ "URGENT: the home server has not been heard for 15 min", - "key: provider.keycloak.ace.gitea.failing", - "more: conditions show machine.ace.silent", + "key: provider.keycloak.node-a.gitea.failing", + "more: conditions show machine.node-a.silent", "since: 2026-10-06 12:30 UTC", "call call-1759752000123456789-12 has run past its bound of 10 min", - "ace/postgres.query answers no more", + "node-a/postgres.query answers no more", "3/4 machines answered; plan 41 waits on build 7f3a9c1e", - "the bus advisory slow-consumer for ace_records", - "core.controller.novox.rolled-back", + "the bus advisory slow-consumer for node-a_records", + "core.controller.node-c.rolled-back", "seat node-notifier has no live holder", "HELD BACK: 5 message(s) over the cap of 20 an hour", "STILL OPEN after 1.5 h: the controller's event loop takes no message", @@ -32,7 +32,7 @@ func TestAnAddressAPathOrASecretMayNot(t *testing.T) { "fe80::1 answered": "address", "2001:db8:0:0:0:0:2:1 answered": "address", "see https://git.example.org/x": "address", - "git.novox.internal does not answer": "address", + "git.node-c.internal does not answer": "address", "the mail for admin@example.org bounced": "address", "zurag.be is down": "address", "localhost refused": "address", diff --git a/modules/messenger/cmd/messenger/details_test.go b/modules/messenger/cmd/messenger/details_test.go index 46d9f79e..da02f5c2 100644 --- a/modules/messenger/cmd/messenger/details_test.go +++ b/modules/messenger/cmd/messenger/details_test.go @@ -38,7 +38,7 @@ func TestDetailsWorksOnEachOfThreeWarningsOnceEach(t *testing.T) { var toks []string if same { // One problem said three times: raised, escalated, and reminded. - k := cond("machine.novox.silent", Warning, "the anchor is silent") + k := cond("machine.node-c.silent", Warning, "the anchor is silent") k.Raised = c.now() h.Condition(EventRaised, k) settle(h, c) @@ -49,7 +49,7 @@ func TestDetailsWorksOnEachOfThreeWarningsOnceEach(t *testing.T) { h.Tick() settle(h, c) } else { - for _, key := range []string{"machine.ace.silent", "machine.shanks.units", "plan.41.stalled"} { + for _, key := range []string{"machine.node-a.silent", "machine.node-d.units", "plan.41.stalled"} { k := cond(key, Warning, key+" needs a look") k.Raised = c.now() h.Condition(EventRaised, k) @@ -97,7 +97,7 @@ func TestDetailsWorksOnEachOfThreeWarningsOnceEach(t *testing.T) { func TestDetailsTicketsAreBoundedInNumberAndTime(t *testing.T) { h, tg, _, c, _ := newHolder(t) h.Desk = nil - k := cond("machine.ace.silent", Warning, "the home server is silent") + k := cond("machine.node-a.silent", Warning, "the home server is silent") k.Raised = c.now() h.Condition(EventRaised, k) settle(h, c) @@ -134,7 +134,7 @@ func TestDetailsTicketsAreBoundedInNumberAndTime(t *testing.T) { func TestDetailsOutlivesAChangeOfTheActions(t *testing.T) { h, tg, _, c, _ := newHolder(t) h.Desk = nil - k := cond("machine.ace.silent", Warning, "the home server is silent") + k := cond("machine.node-a.silent", Warning, "the home server is silent") k.Raised = c.now() h.Condition(EventRaised, k) settle(h, c) @@ -165,7 +165,7 @@ func TestDetailsOnAMessageWithAnOpenAskNeverAnswersIt(t *testing.T) { shown = m } for _, tok := range []string{older, detailsOf(t, shown)} { - if out, err := h.Chosen("desktop", choiceOf(tok, "g14", c.now())); err != nil || out != "shown" { + if out, err := h.Chosen("desktop", choiceOf(tok, "node-b", c.now())); err != nil || out != "shown" { t.Fatalf("Details: %q %v", out, err) } } @@ -182,7 +182,7 @@ func TestDetailsOnAMessageWithAnOpenAskNeverAnswersIt(t *testing.T) { func TestAnUnreadyChannelPushesOutNoShownDetails(t *testing.T) { h, tg, _, c, _ := newHolder(t) h.Desk = nil - k := cond("machine.ace.silent", Warning, "the home server is silent") + k := cond("machine.node-a.silent", Warning, "the home server is silent") k.Raised = c.now() h.Condition(EventRaised, k) settle(h, c) diff --git a/modules/messenger/cmd/messenger/glance_test.go b/modules/messenger/cmd/messenger/glance_test.go index 223caeb9..4a6f4f85 100644 --- a/modules/messenger/cmd/messenger/glance_test.go +++ b/modules/messenger/cmd/messenger/glance_test.go @@ -23,7 +23,7 @@ func decisionAsk(c *clock) asks.Ask { "• A deleted file is marked, and a newer change elsewhere outlives the deletion", Who: asks.Operator, Expires: c.now().Add(23*time.Hour + 50*time.Minute), OnExpiry: "the record stays proposed; nothing of it is in force", About: "knowledge.decision.343", - Details: "ADR 0343, proposed by fix-367@g14; the knowledge base's own review approved it. Fingerprint a59f 361b f60e cb5e d237 a837.\n" + + Details: "ADR 0343, proposed by fix-367@node-b; the knowledge base's own review approved it. Fingerprint a59f 361b f60e cb5e d237 a837.\n" + "Read its 13 clauses with the knowledge base's get, number 343.", Options: []asks.Option{ {ID: "approve", Label: "Approve", Does: "the record is accepted and its clauses are in force", Level: asks.Approve, Binds: bound("approve")}, @@ -50,7 +50,7 @@ func TestAnAsksMessageIsItsSummaryWithTheRestInItsNote(t *testing.T) { "Asked by mesh-knowledge at " + asked + ". Unanswered by tomorrow " + a.Expires.In(time.UTC).Format("15:04") + ": the record stays proposed; nothing of it is in force.", "Approve: the record is accepted and its clauses are in force. Decline: the record stays proposed; nothing of it is in force.", - "ADR 0343, proposed by fix-367@g14; the knowledge base's own review approved it. Fingerprint a59f 361b f60e cb5e d237 a837.", + "ADR 0343, proposed by fix-367@node-b; the knowledge base's own review approved it. Fingerprint a59f 361b f60e cb5e d237 a837.", "Read its 13 clauses with the knowledge base's get, number 343.", } if strings.Join(note, "\n") != strings.Join(want, "\n") { diff --git a/modules/messenger/cmd/messenger/history_test.go b/modules/messenger/cmd/messenger/history_test.go index a8285d77..d3b304e9 100644 --- a/modules/messenger/cmd/messenger/history_test.go +++ b/modules/messenger/cmd/messenger/history_test.go @@ -184,7 +184,7 @@ func TestTodaysBacklogWithAnUrgentStillOpenIsOneMessage(t *testing.T) { h, tg, dt, c := incidentHolder(t) // Suppose the merge never got acted on, and three machines stayed behind: still open at 09:49. stillOpen := map[string]bool{"merge.mesh-catalog.f2b51686.not-acted": true, - "machine.ace.core-behind": true, "machine.g14.core-behind": true, "machine.shanks.core-behind": true} + "machine.node-a.core-behind": true, "machine.node-b.core-behind": true, "machine.node-d.core-behind": true} var kept []backlogEvent for _, e := range backlog { c, _ := DecodeCondition(e.event, e.body) @@ -216,7 +216,7 @@ func TestTodaysBacklogWithAnUrgentStillOpenIsOneMessage(t *testing.T) { func TestAnEventOlderThanTheReadingIsNotActedOn(t *testing.T) { h, tg, dt, c, _ := newHolder(t) h.Sync(nil, c.now()) - k := cond("machine.ace.silent", Urgent, "the home server is silent") + k := cond("machine.node-a.silent", Urgent, "the home server is silent") k.At = c.now().Add(-time.Minute) k.Raised = k.At h.Condition(EventRaised, k) // already cleared in the state read after it @@ -228,7 +228,7 @@ func TestAnEventOlderThanTheReadingIsNotActedOn(t *testing.T) { func TestAnOldEventIsStateNeverAMessage(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - k := cond("machine.ace.silent", Urgent, "the home server is silent") + k := cond("machine.node-a.silent", Urgent, "the home server is silent") k.At = c.now().Add(-FreshFor - time.Second) h.Condition(EventRaised, k) runFor(h, c, 2*time.Minute) @@ -247,10 +247,10 @@ func TestAnOldEventIsStateNeverAMessage(t *testing.T) { t.Fatalf("a clearing of what was never said was said") } // The state, read now, says an urgent one is open that was never said: that is said, once. - h.Condition(EventRaised, Condition{Key: "machine.shanks.silent", Scope: "machine", ID: "shanks", Kind: "silent", + h.Condition(EventRaised, Condition{Key: "machine.node-d.silent", Scope: "machine", ID: "node-d", Kind: "silent", Severity: Urgent, Summary: "the desktop is silent", At: c.now().Add(-time.Hour)}) - h.Sync([]Condition{cond("machine.shanks.silent", Urgent, "the desktop is silent")}, c.now()) - h.Sync([]Condition{cond("machine.shanks.silent", Urgent, "the desktop is silent")}, c.now().Add(time.Second)) + h.Sync([]Condition{cond("machine.node-d.silent", Urgent, "the desktop is silent")}, c.now()) + h.Sync([]Condition{cond("machine.node-d.silent", Urgent, "the desktop is silent")}, c.now().Add(time.Second)) if len(tg.sends) != 1 || len(dt.sends) != 1 { t.Fatalf("telegram %d desktop %d", len(tg.sends), len(dt.sends)) } @@ -320,7 +320,7 @@ func TestTheDesktopIsGentle(t *testing.T) { runFor(h, c, 5*time.Minute) h.Condition(EventRaised, cond("plan.4.stalled", Warning, "plan 4 waits")) // Urgent is not held to the desktop's rhythm. - h.Condition(EventRaised, cond("machine.ace.silent", Urgent, "the home server is silent")) + h.Condition(EventRaised, cond("machine.node-a.silent", Urgent, "the home server is silent")) h.Flush() if len(dt.sends) != 2 || !strings.HasPrefix(dt.sends[1].Title, "Urgent: ") || len(tg.sends) != 1 { t.Fatalf("urgent: desktop %d telegram %d", len(dt.sends), len(tg.sends)) @@ -346,7 +346,7 @@ func TestTheDesktopIsGentle(t *testing.T) { func TestNothingIsSentInTheFirstMinuteButTheUrgentOpenAsOne(t *testing.T) { h, tg, dt, c, _ := newHolder(t) h.Start() - u1 := cond("machine.ace.silent", Urgent, "the home server is silent") + u1 := cond("machine.node-a.silent", Urgent, "the home server is silent") u1.Raised = c.now().Add(-3 * time.Hour) u2 := cond("bus.controller.refused", Urgent, "the bus refuses the controller") u2.Raised = c.now().Add(-20 * time.Minute) @@ -365,7 +365,7 @@ func TestNothingIsSentInTheFirstMinuteButTheUrgentOpenAsOne(t *testing.T) { k := cond("plan.43.stalled", Warning, "plan 43 waits") k.At = c.now() h.Condition(EventRaised, k) - u3 := cond("machine.shanks.silent", Urgent, "the desktop is silent") + u3 := cond("machine.node-d.silent", Urgent, "the desktop is silent") u3.At = c.now() h.Condition(EventRaised, u3) runFor(h, c, 45*time.Second) @@ -378,14 +378,14 @@ func TestNothingIsSentInTheFirstMinuteButTheUrgentOpenAsOne(t *testing.T) { t.Fatalf("after the grace: telegram %d desktop %d", len(tg.sends), len(dt.sends)) } if d := dt.sends[1]; !strings.Contains(d.Body, "plan 42 stalled") || !strings.Contains(d.Body, "plan 43 stalled") || - !strings.Contains(d.Body, "machine shanks silent") || strings.Contains(d.Body, "plan 41 stalled") { + !strings.Contains(d.Body, "machine node-d silent") || strings.Contains(d.Body, "plan 41 stalled") { t.Fatalf("desktop digest: %q", d.Text()) } } func TestWhatEndedWhileAwayIsEndedQuietly(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - k := cond("machine.ace.silent", Urgent, "the home server is silent") + k := cond("machine.node-a.silent", Urgent, "the home server is silent") k.At = c.now() h.Condition(EventRaised, k) if len(tg.sends) != 1 || len(dt.sends) != 1 { @@ -406,7 +406,7 @@ func TestWhatEndedWhileAwayIsEndedQuietly(t *testing.T) { func TestARestartSaysNothingAgain(t *testing.T) { h, tg, dt, c, st := newHolder(t) - k := cond("machine.ace.silent", Urgent, "the home server is silent") + k := cond("machine.node-a.silent", Urgent, "the home server is silent") k.At = c.now() h.Condition(EventRaised, k) w := cond("plan.41.stalled", Warning, "plan 41 waits") @@ -426,7 +426,7 @@ func TestARestartSaysNothingAgain(t *testing.T) { } func TestTheOpenSetIsReadInEveryShape(t *testing.T) { - one := `{"key":"machine.ace.silent","kind":"silent","subject":{"scope":"machine","id":"ace"},"severity":"urgent","summary":"s","raised":"2026-10-06T09:00:00Z"}` + one := `{"key":"machine.node-a.silent","kind":"silent","subject":{"scope":"machine","id":"node-a"},"severity":"urgent","summary":"s","raised":"2026-10-06T09:00:00Z"}` for _, raw := range []string{ `{"conditions":[` + one + `],"open":1}`, `{"answer":{"conditions":[` + one + `]},"ok":true}`, @@ -434,7 +434,7 @@ func TestTheOpenSetIsReadInEveryShape(t *testing.T) { `{"content":[{"type":"text","text":"{\"conditions\":[` + strings.ReplaceAll(one, `"`, `\"`) + `]}"}]}`, } { got, err := DecodeOpen(json.RawMessage(raw)) - if err != nil || len(got) != 1 || got[0].Key != "machine.ace.silent" || got[0].Severity != Urgent { + if err != nil || len(got) != 1 || got[0].Key != "machine.node-a.silent" || got[0].Severity != Urgent { t.Fatalf("%s: %+v %v", raw, got, err) } } @@ -449,7 +449,7 @@ func TestTheOpenSetIsReadInEveryShape(t *testing.T) { } func TestAnEventSaysItsOwnTime(t *testing.T) { - c, err := DecodeCondition(EventCleared, []byte(`{"key":"machine.ace.silent","at":"2026-10-06T08:36:50Z","raised":"2026-10-06T08:32:30Z"}`)) + c, err := DecodeCondition(EventCleared, []byte(`{"key":"machine.node-a.silent","at":"2026-10-06T08:36:50Z","raised":"2026-10-06T08:32:30Z"}`)) if err != nil || !c.When(EventCleared).Equal(time.Date(2026, 10, 6, 8, 36, 50, 0, time.UTC)) { t.Fatalf("%v %v", c.When(EventCleared), err) } diff --git a/modules/messenger/cmd/messenger/holder_test.go b/modules/messenger/cmd/messenger/holder_test.go index 980721c3..cfd3e727 100644 --- a/modules/messenger/cmd/messenger/holder_test.go +++ b/modules/messenger/cmd/messenger/holder_test.go @@ -48,7 +48,7 @@ func (f *fakeChannel) Send(m Message) (string, error) { f.sends = append(f.sends, m) f.to = append(f.to, m.To) if f.name == "desktop" { - return fmt.Sprintf("g14=%d", f.n), nil // as the desktop answers: the machine and the notification + return fmt.Sprintf("node-b=%d", f.n), nil // as the desktop answers: the machine and the notification } return fmt.Sprint(f.n), nil } @@ -157,7 +157,7 @@ func newHolder(t *testing.T) (*Holder, *fakeChannel, *fakeChannel, *clock, *memS func TestARaisedConditionIsSentOnceByItsKey(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - k := cond("machine.ace.silent", Urgent, "the home server has not been heard for 15 min") + k := cond("machine.node-a.silent", Urgent, "the home server has not been heard for 15 min") k.Raised = c.now() h.Condition(EventRaised, k) h.Condition(EventRaised, k) // a redelivery @@ -167,7 +167,7 @@ func TestARaisedConditionIsSentOnceByItsKey(t *testing.T) { t.Fatalf("urgent: telegram %d, desktop %d; want one each", len(tg.sends), len(dt.sends)) } keyless(t, tg.sends...) - if tg.sends[0].Title != "Urgent: machine ace silent" || !strings.HasPrefix(tg.sends[0].Body, "Needs you: look at it. What it means: ") || + if tg.sends[0].Title != "Urgent: machine node-a silent" || !strings.HasPrefix(tg.sends[0].Body, "Needs you: look at it. What it means: ") || !strings.Contains(tg.sends[0].Body, "\nSince ") { t.Fatalf("message: %q", tg.sends[0].Text()) } @@ -252,7 +252,7 @@ func TestAMessageCarryingAnAddressIsRefusedAndSaidWithItsWordsWithheld(t *testin h, tg, _, c, _ := newHolder(t) var emitted []string h.Emit = func(e string, _ any) error { emitted = append(emitted, e); return nil } - h.Condition(EventRaised, cond("provider.keycloak.ace.failing", Urgent, "cannot reach 192.168.1.20:8443 with token=abc")) + h.Condition(EventRaised, cond("provider.keycloak.node-a.failing", Urgent, "cannot reach 192.168.1.20:8443 with token=abc")) if len(tg.sends) != 1 { t.Fatalf("sends: %d", len(tg.sends)) } @@ -260,7 +260,7 @@ func TestAMessageCarryingAnAddressIsRefusedAndSaidWithItsWordsWithheld(t *testin if strings.Contains(text, "192.168") || strings.Contains(text, "token=") { t.Fatalf("the address left: %q", text) } - if !strings.Contains(text, "withheld, because it carried an IPv4 address") || !strings.Contains(text, "provider keycloak ace failing") { + if !strings.Contains(text, "withheld, because it carried an IPv4 address") || !strings.Contains(text, "provider keycloak node-a failing") { t.Fatalf("not said as refused, by key: %q", text) } hist := h.History(10)["refusals"].([]RefusalNote) @@ -271,7 +271,7 @@ func TestAMessageCarryingAnAddressIsRefusedAndSaidWithItsWordsWithheld(t *testin t.Fatalf("emitted: %v", emitted) } // Its clearing keeps the words withheld. - h.Condition(EventCleared, Condition{Key: "provider.keycloak.ace.failing"}) + h.Condition(EventCleared, Condition{Key: "provider.keycloak.node-a.failing"}) c.pass(ClearSettle) h.Tick() for _, m := range tg.edits { @@ -330,7 +330,7 @@ func TestStillOpenPastItsBoundItIsSaidOnceMore(t *testing.T) { func TestClearedEditsTheFirstMessageAndReopenedWithinTenMinutesIsNotNew(t *testing.T) { h, tg, dt, c, st := newHolder(t) - k := cond("machine.ace.silent", Urgent, "the home server is silent") + k := cond("machine.node-a.silent", Urgent, "the home server is silent") k.Raised = c.now() h.Condition(EventRaised, k) c.pass(14 * time.Minute) @@ -340,7 +340,7 @@ func TestClearedEditsTheFirstMessageAndReopenedWithinTenMinutesIsNotNew(t *testi if len(tg.sends) != 1 || len(tg.edits) != 1 || len(dt.edits) != 1 { t.Fatalf("telegram sends %d edits %d, desktop edits %d", len(tg.sends), len(tg.edits), len(dt.edits)) } - if m := tg.edits["1"]; m.Title != "Resolved: machine ace silent, after 14 min" || m.Body != "" { + if m := tg.edits["1"]; m.Title != "Resolved: machine node-a silent, after 14 min" || m.Body != "" { t.Fatalf("edit: %q", m.Title) } if len(h.Open()) != 0 { @@ -369,7 +369,7 @@ func TestClearedEditsTheFirstMessageAndReopenedWithinTenMinutesIsNotNew(t *testi func TestASilencedConditionSendsNothing(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - k := cond("machine.ace.silent", Urgent, "silent") + k := cond("machine.node-a.silent", Urgent, "silent") k.SilencedTill = c.now().Add(2 * time.Hour) h.Condition(EventRaised, k) c.pass(90 * time.Minute) @@ -379,7 +379,7 @@ func TestASilencedConditionSendsNothing(t *testing.T) { t.Fatalf("a silenced condition said something") } // Silenced after it was sent: no reminder. - k2 := cond("machine.shanks.silent", Urgent, "silent") + k2 := cond("machine.node-d.silent", Urgent, "silent") k2.Raised = c.now() h.Condition(EventRaised, k2) k2.SilencedTill = c.now().Add(3 * time.Hour) @@ -393,7 +393,7 @@ func TestASilencedConditionSendsNothing(t *testing.T) { func TestEscalationIsSaidOnce(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - k := cond("machine.novox.silent", Warning, "the anchor is silent") + k := cond("machine.node-c.silent", Warning, "the anchor is silent") h.Condition(EventRaised, k) settle(h, c) k.Severity = Urgent @@ -401,12 +401,12 @@ func TestEscalationIsSaidOnce(t *testing.T) { h.Condition(EventChanged, k) settle(h, c) // The desktop's warning is replaced by the urgent message (issue 373); Telegram, which had none, is sent one. - if len(dt.sends) != 1 || len(dt.replaced) != 1 || dt.replaced[0].id != "g14=1" || + if len(dt.sends) != 1 || len(dt.replaced) != 1 || dt.replaced[0].id != "node-b=1" || !strings.HasPrefix(dt.replaced[0].m.Title, "Now urgent: ") || len(tg.sends) != 1 || !strings.HasPrefix(tg.sends[0].Title, "Now urgent: ") { t.Fatalf("desktop %d sends %d replaced, telegram %d", len(dt.sends), len(dt.replaced), len(tg.sends)) } // Escalated while the warning still waited its window: one message, the urgent one. - k2 := cond("machine.ace.silent", Warning, "the home server is silent") + k2 := cond("machine.node-a.silent", Warning, "the home server is silent") h.Condition(EventRaised, k2) k2.Severity = Urgent h.Condition(EventChanged, k2) @@ -434,7 +434,7 @@ func TestAChannelThatCannotSendSaysSoAndIsTriedAgain(t *testing.T) { h, tg, _, c, _ := newHolder(t) h.Desk = nil tg.fail = errors.New("telegram sendMessage: cannot connect (dial)") - h.Condition(EventRaised, cond("machine.ace.silent", Urgent, "silent")) + h.Condition(EventRaised, cond("machine.node-a.silent", Urgent, "silent")) st := h.Status("listening") if !strings.HasPrefix(st.Verdict, "CANNOT SEND") || len(st.Unsent) != 1 || st.Channels[0].LastError == "" { t.Fatalf("status: %+v", st) @@ -464,7 +464,7 @@ func TestNothingConfiguredIsSaidInTheStatus(t *testing.T) { func TestARestartForgetsNothing(t *testing.T) { h, tg, _, c, st := newHolder(t) h.Desk = nil - k := cond("machine.ace.silent", Urgent, "silent") + k := cond("machine.node-a.silent", Urgent, "silent") k.Raised = c.now() h.Condition(EventRaised, k) again := &Holder{Away: tg, Store: st, Now: c.now, Logf: t.Logf} @@ -507,12 +507,12 @@ func TestAnUnreadableEventIsToldOnceAnHour(t *testing.T) { func TestNotifyIsKeptApartFromConditions(t *testing.T) { h, tg, _, c, _ := newHolder(t) h.Desk = nil - out, err := h.Notify("backup.ace.failed", Warning, "last night's backup of the home server failed", "backup", false) + out, err := h.Notify("backup.node-a.failed", Warning, "last night's backup of the home server failed", "backup", false) if err != nil || out["held"] != true { t.Fatalf("%v %v", out, err) } settle(h, c) - if err != nil || out["key"] != "notify.backup.ace.failed" || len(tg.sends) != 1 { + if err != nil || out["key"] != "notify.backup.node-a.failed" || len(tg.sends) != 1 { t.Fatalf("%v %v %d", out, err, len(tg.sends)) } if _, err := h.Notify("x", "", "s", "", false); err == nil { @@ -529,7 +529,7 @@ func TestNotifyIsKeptApartFromConditions(t *testing.T) { func TestATellReachesEveryChannelOnceAndOffersOnlyDetails(t *testing.T) { h, tg, dt, c, _ := newHolder(t) c.pass(14 * time.Hour) // well past midnight: it is not held for being "night" — there is no such hold - out, err := h.Tell("new mail arrived for ace", []string{"One message from the inbox you watch."}, "mail") + out, err := h.Tell("new mail arrived for node-a", []string{"One message from the inbox you watch."}, "mail") if err != nil { t.Fatal(err) } diff --git a/modules/messenger/cmd/messenger/manifest_test.go b/modules/messenger/cmd/messenger/manifest_test.go index 8fc2f9e5..796eecfd 100644 --- a/modules/messenger/cmd/messenger/manifest_test.go +++ b/modules/messenger/cmd/messenger/manifest_test.go @@ -134,7 +134,7 @@ func TestTheToolsAgreeWithTheManifest(t *testing.T) { if !reflect.DeepEqual(verbs, m.Claims[0].Serves) { t.Fatalf("verbs %v, claim %v", verbs, m.Claims[0].Serves) } - for _, never := range []string{"/home/", "jochen", "g14", "shanks", "novox", "zurag", "telegram"} { + for _, never := range []string{"/home/", "jochen", "node-b", "node-d", "node-c", "zurag", "telegram"} { if strings.Contains(strings.ToLower(raw), never) { t.Errorf("module.json names %q", never) } diff --git a/modules/messenger/cmd/messenger/onemessage_test.go b/modules/messenger/cmd/messenger/onemessage_test.go index 56d16d1c..bd556c23 100644 --- a/modules/messenger/cmd/messenger/onemessage_test.go +++ b/modules/messenger/cmd/messenger/onemessage_test.go @@ -22,7 +22,7 @@ func saidOn(chs ...*fakeChannel) int { // "again, 22nd time", no "Resolved" — and once it stays cleared, its clearing is said once. func TestAFlappingConditionIsSaidOnceAndItsClearingOnceWhenItStops(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - k := cond("machine.shanks.units", Warning, "2 failed services on shanks") + k := cond("machine.node-d.units", Warning, "2 failed services on node-d") k.Raised = c.now() h.Condition(EventRaised, k) settle(h, c) @@ -58,7 +58,7 @@ func TestAFlappingConditionIsSaidOnceAndItsClearingOnceWhenItStops(t *testing.T) t.Fatalf("open: %+v", open) } // A genuinely new problem meanwhile is said. - n := cond("machine.ace.disk-full", Urgent, "the home server's disk is full") + n := cond("machine.node-a.disk-full", Urgent, "the home server's disk is full") n.Raised = c.now() h.Condition(EventRaised, n) if len(tg.sends) != 1 || len(dt.sends) != 2 { @@ -67,7 +67,7 @@ func TestAFlappingConditionIsSaidOnceAndItsClearingOnceWhenItStops(t *testing.T) // The unit stays mended: its clearing is said once, in place of its message. h.Condition(EventCleared, Condition{Key: k.Key, At: c.now()}) runFor(h, c, 30*time.Minute) - if len(dt.edits) != 1 || !strings.HasPrefix(dt.edits["g14=1"].Title, "Resolved: ") || len(dt.sends) != 2 { + if len(dt.edits) != 1 || !strings.HasPrefix(dt.edits["node-b=1"].Title, "Resolved: ") || len(dt.sends) != 2 { t.Fatalf("its clearing: edits %+v, sends %d", dt.edits, len(dt.sends)) } } @@ -75,7 +75,7 @@ func TestAFlappingConditionIsSaidOnceAndItsClearingOnceWhenItStops(t *testing.T) // A clearing a few seconds long is never said, and the message continues; an urgent problem rang once. func TestAnUrgentBlipRingsOnceAndItsBlipsSayNothing(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - k := cond("machine.ace.silent", Urgent, "the home server is silent") + k := cond("machine.node-a.silent", Urgent, "the home server is silent") k.Raised = c.now() h.Condition(EventRaised, k) for i := 0; i < 5; i++ { @@ -97,7 +97,7 @@ func TestAnUrgentBlipRingsOnceAndItsBlipsSayNothing(t *testing.T) { // said, not swallowed as the same message. func TestAConditionClearedBeforeItWasSaidAndBackIsSaid(t *testing.T) { h, _, dt, c, _ := newHolder(t) - k := cond("machine.shanks.units", Warning, "2 failed services on shanks") + k := cond("machine.node-d.units", Warning, "2 failed services on node-d") k.Raised = c.now() h.Condition(EventRaised, k) c.pass(10 * time.Second) @@ -106,7 +106,7 @@ func TestAConditionClearedBeforeItWasSaidAndBackIsSaid(t *testing.T) { k.At = c.now() h.Condition(EventRaised, k) runFor(h, c, 2*time.Minute) - if len(dt.sends) != 1 || !strings.Contains(dt.sends[0].Title, "machine shanks units") { + if len(dt.sends) != 1 || !strings.Contains(dt.sends[0].Title, "machine node-d units") { t.Fatalf("desktop %+v", dt.sends) } } @@ -169,7 +169,7 @@ func TestAnAsksExpiryIsSaidWithItsDay(t *testing.T) { func TestAnEndedQuestionLeavesNoMessageOfferingItsAnswers(t *testing.T) { h, tg, dt, c, store, _ := newRouter(t) link(h, store, c, "42", c.now().Add(-2*time.Hour)) - k := cond("machine.novox.secret-given", Urgent, "a secret was given at the terminal") + k := cond("machine.node-c.secret-given", Urgent, "a secret was given at the terminal") k.Raised = c.now() h.Condition(EventRaised, k) settle(h, c) @@ -191,7 +191,7 @@ func TestAnEndedQuestionLeavesNoMessageOfferingItsAnswers(t *testing.T) { if len(ch.sends) != 1 { t.Fatalf("%s: %d messages for one problem", ch.name, len(ch.sends)) } - last := ch.edits[map[string]string{"telegram": "1", "desktop": "g14=1"}[ch.name]] + last := ch.edits[map[string]string{"telegram": "1", "desktop": "node-b=1"}[ch.name]] if len(ch.replaced) == 0 || len(last.Actions) > 1 || !strings.Contains(last.Body, "No longer answerable") { t.Fatalf("%s: replaced %d, the message now: %q %v", ch.name, len(ch.replaced), last.Text(), labelsOf(last)) } @@ -202,7 +202,7 @@ func TestAnEndedQuestionLeavesNoMessageOfferingItsAnswers(t *testing.T) { // warning back as urgent rings, and a reminder waiting to go out when it cleared still goes out. func TestABlipSwallowsNeitherAnEscalationNorAWaitingReminder(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - k := cond("machine.shanks.units", Warning, "2 failed services on shanks") + k := cond("machine.node-d.units", Warning, "2 failed services on node-d") k.Raised = c.now() h.Condition(EventRaised, k) settle(h, c) @@ -274,7 +274,7 @@ func TestAReminderInABurstReplacesItsMessageAndIsNoDigestLine(t *testing.T) { func TestAClearingTheChannelCouldNotTakeIsSaidLater(t *testing.T) { h, tg, _, c, _ := newHolder(t) h.Desk = nil - k := cond("machine.ace.silent", Urgent, "the home server is silent") + k := cond("machine.node-a.silent", Urgent, "the home server is silent") k.Raised = c.now() h.Condition(EventRaised, k) tg.fail = errorf("telegram is away") @@ -297,7 +297,7 @@ func TestAClearingTheChannelCouldNotTakeIsSaidLater(t *testing.T) { func TestASilenceIsSaidOnTheShownMessageAndTheMessageIsOpenAgainWhenItEnds(t *testing.T) { h, tg, dt, c, _ := newHolder(t) h.Zone = func() *time.Location { return time.UTC } - k := cond("machine.shanks.units", Warning, "2 failed services on shanks") + k := cond("machine.node-d.units", Warning, "2 failed services on node-d") k.Raised = c.now() h.Condition(EventRaised, k) settle(h, c) @@ -307,8 +307,8 @@ func TestASilenceIsSaidOnTheShownMessageAndTheMessageIsOpenAgainWhenItEnds(t *te c.pass(time.Hour) k.SilencedTill, k.SilencedWhy = c.now().Add(7*24*time.Hour), "the mounts are gone for good" h.Condition(EventChanged, k) - m, edited := dt.edits["g14=1"] - if !edited || m.Title != "Silenced until Tue 13 Oct 13:00: machine shanks units" || !m.Quiet || m.Urgent || + m, edited := dt.edits["node-b=1"] + if !edited || m.Title != "Silenced until Tue 13 Oct 13:00: machine node-d units" || !m.Quiet || m.Urgent || len(m.Actions) != 0 || !strings.Contains(m.Body, "Because: the mounts are gone for good.") { t.Fatalf("silenced, and the desk's message says %q %q quiet=%v urgent=%v actions=%v", m.Title, m.Body, m.Quiet, m.Urgent, m.Actions) } @@ -324,7 +324,7 @@ func TestASilenceIsSaidOnTheShownMessageAndTheMessageIsOpenAgainWhenItEnds(t *te // The silence runs out and the condition is still open: its message is open again, on the same notification. c.pass(7 * 24 * time.Hour) h.Tick() - if m := dt.edits["g14=1"]; m.Title != "machine shanks units" || m.Quiet || len(m.Actions) == 0 { + if m := dt.edits["node-b=1"]; m.Title != "machine node-d units" || m.Quiet || len(m.Actions) == 0 { t.Fatalf("the silence ended, and the message says %q quiet=%v actions=%v", m.Title, m.Quiet, m.Actions) } if len(dt.sends) != 1 { @@ -336,18 +336,18 @@ func TestASilenceIsSaidOnTheShownMessageAndTheMessageIsOpenAgainWhenItEnds(t *te // desk's popup, which timed out, is not brought back. func TestAConditionResolvedWhileSilencedSaysSoOnlyWhereAnEditNotifiesNobody(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - k := cond("machine.ace.silent", Urgent, "the home server is silent") + k := cond("machine.node-a.silent", Urgent, "the home server is silent") k.Raised = c.now() h.Condition(EventRaised, k) - k.SilencedTill, k.SilencedWhy = c.now().Add(24*time.Hour), "ace is moving house" + k.SilencedTill, k.SilencedWhy = c.now().Add(24*time.Hour), "node-a is moving house" h.Condition(EventChanged, k) - if !strings.HasPrefix(tg.edits["1"].Title, "Silenced until ") || !strings.HasPrefix(dt.edits["g14=1"].Title, "Silenced until ") { - t.Fatalf("telegram %q desk %q", tg.edits["1"].Title, dt.edits["g14=1"].Title) + if !strings.HasPrefix(tg.edits["1"].Title, "Silenced until ") || !strings.HasPrefix(dt.edits["node-b=1"].Title, "Silenced until ") { + t.Fatalf("telegram %q desk %q", tg.edits["1"].Title, dt.edits["node-b=1"].Title) } h.Condition(EventCleared, Condition{Key: k.Key, At: c.now()}) runFor(h, c, ClearSettle+time.Minute) - if !strings.HasPrefix(tg.edits["1"].Title, "Resolved: ") || !strings.HasPrefix(dt.edits["g14=1"].Title, "Silenced until ") { - t.Fatalf("resolved while silenced: telegram %q desk %q", tg.edits["1"].Title, dt.edits["g14=1"].Title) + if !strings.HasPrefix(tg.edits["1"].Title, "Resolved: ") || !strings.HasPrefix(dt.edits["node-b=1"].Title, "Silenced until ") { + t.Fatalf("resolved while silenced: telegram %q desk %q", tg.edits["1"].Title, dt.edits["node-b=1"].Title) } if len(tg.sends)+len(dt.sends) != 2 || len(tg.replaced)+len(dt.replaced) != 0 { t.Fatalf("a new message was made: sends %d %d", len(tg.sends), len(dt.sends)) @@ -358,7 +358,7 @@ func TestAConditionResolvedWhileSilencedSaysSoOnlyWhereAnEditNotifiesNobody(t *t // same way, and the reading that says it ended makes the message open again. func TestASilenceReadFromTheOpenSetIsSaidOnTheShownMessage(t *testing.T) { h, _, dt, c, _ := newHolder(t) - k := cond("machine.shanks.units", Warning, "2 failed services on shanks") + k := cond("machine.node-d.units", Warning, "2 failed services on node-d") k.Raised = c.now() h.Condition(EventRaised, k) settle(h, c) @@ -366,12 +366,12 @@ func TestASilenceReadFromTheOpenSetIsSaidOnTheShownMessage(t *testing.T) { s := k s.SilencedTill, s.SilencedWhy = c.now().Add(7*24*time.Hour), "the mounts are gone for good" h.Sync([]Condition{s}, c.now()) - if m := dt.edits["g14=1"]; !strings.HasPrefix(m.Title, "Silenced until ") || !m.Quiet || len(m.Actions) != 0 { + if m := dt.edits["node-b=1"]; !strings.HasPrefix(m.Title, "Silenced until ") || !m.Quiet || len(m.Actions) != 0 { t.Fatalf("read silenced, and the desk's message says %q quiet=%v actions=%v", m.Title, m.Quiet, m.Actions) } c.pass(10 * time.Minute) h.Sync([]Condition{k}, c.now()) // the silence was lifted: the reading carries none - if m := dt.edits["g14=1"]; m.Title != "machine shanks units" || len(dt.sends) != 1 { + if m := dt.edits["node-b=1"]; m.Title != "machine node-d units" || len(dt.sends) != 1 { t.Fatalf("read unsilenced, and the desk's message says %q (sends %d)", m.Title, len(dt.sends)) } } diff --git a/modules/messenger/cmd/messenger/preview_test.go b/modules/messenger/cmd/messenger/preview_test.go index ec23f9f7..33b820a9 100644 --- a/modules/messenger/cmd/messenger/preview_test.go +++ b/modules/messenger/cmd/messenger/preview_test.go @@ -114,7 +114,7 @@ func TestAConditionsMessageIsReadWithoutBeingSent(t *testing.T) { } func TestAPreviewSaysTheWordsTheChannelWasGiven(t *testing.T) { - issues := []TrackedIssue{{Number: 386, Status: "fixing", Worker: "fix-386@g14", Since: at(21, 10)}} + issues := []TrackedIssue{{Number: 386, Status: "fixing", Worker: "fix-386@node-b", Since: at(21, 10)}} h, tg, dt, c, st, k := previewHolder(t, issues) sent := dt.sends[len(dt.sends)-1] // the message the desk was actually handed was := mark(t, h, tg, dt, st, k.Key) @@ -126,7 +126,7 @@ func TestAPreviewSaysTheWordsTheChannelWasGiven(t *testing.T) { if out["title"] != sent.Title || out["body"] != sent.Body { t.Fatalf("preview %q / %q; the channel was given %q / %q", out["title"], out["body"], sent.Title, sent.Body) } - if !strings.Contains(sent.Body, "Tracked as issue 386: fix-386 on g14 is fixing it since ") { + if !strings.Contains(sent.Body, "Tracked as issue 386: fix-386 on node-b is fixing it since ") { t.Fatalf("the message this is compared against carries no tracking line: %q", sent.Body) } was.check(t, h, tg, dt, st, c, k.Key) @@ -187,11 +187,11 @@ func TestASilenceIsPreviewedOnlyWhileThereIsOne(t *testing.T) { func TestAPreviewOfWhatThisRouterDoesNotHoldIsRefusedByName(t *testing.T) { h, _, _, _, _, k := previewHolder(t, nil) - _, err := h.Preview("machine.ace.silent", "") + _, err := h.Preview("machine.node-a.silent", "") if err == nil { t.Fatal("a condition this router does not hold was previewed") } - if !strings.Contains(err.Error(), "machine.ace.silent") || !strings.Contains(err.Error(), k.Key) { + if !strings.Contains(err.Error(), "machine.node-a.silent") || !strings.Contains(err.Error(), k.Key) { t.Errorf("the refusal says neither what was asked nor what is held: %v", err) } @@ -248,7 +248,7 @@ func TestAPreviewSaysTheReducedWordsAndWhyWhenItsOwnMayNotLeave(t *testing.T) { stated := 0 h.Emit = func(string, any) error { stated++; return nil } // A warning that needs nothing is held, not sent, so this refusal is one no send has met yet. - k := cond("machine.ace.unreadable", Warning, "a file on it could not be read") + k := cond("machine.node-a.unreadable", Warning, "a file on it could not be read") k.Explanation = "Nothing for you to do. A file at /home/someone/secrets.txt could not be read." k.Needs = "" k.Raised = c.now() diff --git a/modules/messenger/cmd/messenger/replaced_test.go b/modules/messenger/cmd/messenger/replaced_test.go index 467a9c0c..e536ce1c 100644 --- a/modules/messenger/cmd/messenger/replaced_test.go +++ b/modules/messenger/cmd/messenger/replaced_test.go @@ -43,7 +43,7 @@ func TestAReplacedAsksMessageEndsWithIt(t *testing.T) { t.Fatalf("open ask records: %v; want only the newer ask's", got) } for _, ch := range []*fakeChannel{tg, dt} { - id := map[string]string{"telegram": "1", "desktop": "g14=1"}[ch.name] + id := map[string]string{"telegram": "1", "desktop": "node-b=1"}[ch.name] m, edited := ch.edits[id] for _, r := range ch.replaced { if r.id == id { @@ -95,7 +95,7 @@ func TestAnAsksMessageLeftOpenAfterItsAskEndedIsEndedOnTheNextTick(t *testing.T) // restarts never says a held message of something that already ended. func TestAClearedRecordOwesNothing(t *testing.T) { h, _, _, c, st := newHolder(t) - k := cond("machine.shanks.units", Warning, "2 failed services on shanks") + k := cond("machine.node-d.units", Warning, "2 failed services on node-d") k.Raised = c.now() h.Condition(EventRaised, k) h.mu.Lock() diff --git a/modules/messenger/cmd/messenger/restart_test.go b/modules/messenger/cmd/messenger/restart_test.go index cb885556..35bc4841 100644 --- a/modules/messenger/cmd/messenger/restart_test.go +++ b/modules/messenger/cmd/messenger/restart_test.go @@ -20,7 +20,7 @@ func TestLostAnswersGetOnlyWhatIsOpenAndUnansweredSaidAgain(t *testing.T) { h.Start() c.pass(2 * time.Minute) // Open, with a question the desk carries. - open := cond("machine.shanks.units", Warning, "2 failed services on shanks") + open := cond("machine.node-d.units", Warning, "2 failed services on node-d") open.Raised = c.now() h.Condition(EventRaised, open) settle(h, c) @@ -30,12 +30,12 @@ func TestLostAnswersGetOnlyWhatIsOpenAndUnansweredSaidAgain(t *testing.T) { ask := ackAsk(c, "silence-units") ask.About = open.Key submit(t, h, ConditionOwner, ask) - if e := dt.edits["g14=1"]; ticketFor(e, "Silence for a week") == "" { + if e := dt.edits["node-b=1"]; ticketFor(e, "Silence for a week") == "" { t.Fatalf("the question was not put on the open message: %+v", e) } // Silenced, with a question of its own, and its message says it is silenced. runFor(h, c, 20*time.Minute) - sil := cond("machine.ace.agent-home", Warning, "Agent-home shrank") + sil := cond("machine.node-a.agent-home", Warning, "Agent-home shrank") sil.Raised = c.now() h.Condition(EventRaised, sil) settle(h, c) @@ -46,12 +46,12 @@ func TestLostAnswersGetOnlyWhatIsOpenAndUnansweredSaidAgain(t *testing.T) { silAsk := ackAsk(c, "silence-home") silAsk.About = sil.Key submit(t, h, ConditionOwner, silAsk) - if e := dt.edits["g14=2"]; ticketFor(e, "Silence for a week") == "" { + if e := dt.edits["node-b=2"]; ticketFor(e, "Silence for a week") == "" { t.Fatalf("the question was not put on the message to be silenced: %+v", e) } sil.SilencedTill, sil.SilencedWhy, sil.At = c.now().Add(7*24*time.Hour), "known", c.now() h.Condition(EventChanged, sil) - if e := dt.edits["g14=2"]; !strings.HasPrefix(e.Title, "Silenced until") { + if e := dt.edits["node-b=2"]; !strings.HasPrefix(e.Title, "Silenced until") { t.Fatalf("the silence was not said: %+v", e) } // Open, told, and asking nothing: not unanswered, so not said again. @@ -74,10 +74,10 @@ func TestLostAnswersGetOnlyWhatIsOpenAndUnansweredSaidAgain(t *testing.T) { } h.Condition(EventCleared, Condition{Key: res.Key, At: c.now()}) runFor(h, c, 3*time.Minute) - if e := dt.edits["g14=4"]; !strings.HasPrefix(e.Title, "Resolved: ") { + if e := dt.edits["node-b=4"]; !strings.HasPrefix(e.Title, "Resolved: ") { t.Fatalf("the clearing was not said: %+v", e) } - delete(dt.edits, "g14=2") // so an edit said again would be seen as such + delete(dt.edits, "node-b=2") // so an edit said again would be seen as such sends, edits, replaced, tgSaid := len(dt.sends), len(dt.edits), len(dt.replaced), saidOn(tg) // The desk's notifier started again: its standing says when the answers were lost. c.pass(time.Minute) @@ -87,20 +87,20 @@ func TestLostAnswersGetOnlyWhatIsOpenAndUnansweredSaidAgain(t *testing.T) { if len(dt.sends) != sends { t.Fatalf("a new message was sent instead of one under its handle: %+v", dt.sends[sends:]) } - if len(dt.replaced) != replaced+1 || dt.replaced[replaced].id != "g14=1" { + if len(dt.replaced) != replaced+1 || dt.replaced[replaced].id != "node-b=1" { t.Fatalf("the open question was not said again under its handle, once and alone: %+v", dt.replaced[replaced:]) } again := dt.replaced[replaced].m if ticketFor(again, "Silence for a week") == "" || !strings.Contains(again.Title, headlineOf(open.Key)) { t.Fatalf("said again without its answer or its words: %+v", again) } - if e, said := dt.edits["g14=2"]; said { + if e, said := dt.edits["node-b=2"]; said { t.Fatalf("the silenced one was said again for the restart: %+v", e) } if len(dt.edits) != edits { t.Fatalf("an edit reached the desk for the restart: %+v", dt.edits) } - if e := dt.edits["g14=4"]; !strings.HasPrefix(e.Title, "Resolved: ") { + if e := dt.edits["node-b=4"]; !strings.HasPrefix(e.Title, "Resolved: ") { t.Fatalf("the resolved one was changed: %+v", e) } if saidOn(tg) != tgSaid { @@ -115,14 +115,14 @@ func TestLostAnswersGetOnlyWhatIsOpenAndUnansweredSaidAgain(t *testing.T) { } // Its ticket is one-time still: one warrant, however often it is tapped, and refused from another machine. tk := ticketFor(again, "Silence for a week") - ch := choiceOf(tk, "g14", c.now()) + ch := choiceOf(tk, "node-b", c.now()) ch.Sender.Authenticated = false if got, err := h.Chosen("desktop", ch); got != "chosen" || err != nil { t.Fatalf("the answer on the message said again: %s, %v", got, err) } ch.ID = "c-second" _, _ = h.Chosen("desktop", ch) // the same tap again: said as recorded (issue 372), nothing more done - other := choiceOf(tk, "shanks", c.now()) + other := choiceOf(tk, "node-d", c.now()) other.Sender.Authenticated = false if got, _ := h.Chosen("desktop", other); got != "refused" { t.Fatalf("the ticket taken from another machine after it was used: %s", got) @@ -146,7 +146,7 @@ func TestLostAnswersAreJudgedPerMessageAndWaitForTheDesk(t *testing.T) { h, tg, dt, c, _, _ := newRouter(t) h.Start() c.pass(2 * time.Minute) - open := cond("machine.shanks.units", Warning, "2 failed services on shanks") + open := cond("machine.node-d.units", Warning, "2 failed services on node-d") open.Raised = c.now() h.Condition(EventRaised, open) settle(h, c) diff --git a/modules/messenger/cmd/messenger/review_test.go b/modules/messenger/cmd/messenger/review_test.go index 3409c3a6..b1f4c837 100644 --- a/modules/messenger/cmd/messenger/review_test.go +++ b/modules/messenger/cmd/messenger/review_test.go @@ -297,7 +297,7 @@ func TestAnAccountInItsFirstHourIsUnlinkedFromTheDesk(t *testing.T) { if labelsOf(asked) != "Unlink it" || !strings.Contains(asked.Body, "number 666") { t.Fatalf("the desk was not asked: %+v", asked) } - ch := choiceOf(ticketFor(asked, "Unlink it"), "g14", c.now()) + ch := choiceOf(ticketFor(asked, "Unlink it"), "node-b", c.now()) ch.Sender.Authenticated = false if out, err := h.Chosen("desktop", ch); err != nil || out != "chosen" { t.Fatalf("%s %v", out, err) @@ -409,7 +409,7 @@ func TestAnUnlinkFromTheDeskInTheFirstHourBarsNothing(t *testing.T) { link(h, store, c, "42", c.now().Add(-10*time.Minute)) // the operator's own, linked just now h.Link("telegram", asks.LinkAsked{ID: "l1", At: c.now(), Sender: asks.Sender{Identity: "666", Display: "X", Authenticated: true}}) asked := dt.sends[len(dt.sends)-1] - ch := choiceOf(ticketFor(asked, "Unlink it"), "g14", c.now()) // a click nobody can prove was the operator's + ch := choiceOf(ticketFor(asked, "Unlink it"), "node-b", c.now()) // a click nobody can prove was the operator's ch.Sender.Authenticated = false if out, err := h.Chosen("desktop", ch); err != nil || out != "chosen" { t.Fatalf("%s %v", out, err) diff --git a/modules/messenger/cmd/messenger/testdata/backlog-2026-10-06.json b/modules/messenger/cmd/messenger/testdata/backlog-2026-10-06.json index b5bb8c19..f474c086 100644 --- a/modules/messenger/cmd/messenger/testdata/backlog-2026-10-06.json +++ b/modules/messenger/cmd/messenger/testdata/backlog-2026-10-06.json @@ -5,22 +5,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-clipboard.shanks.silent", + "key": "seat.node-clipboard.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.057516362Z", "observations": 1, "raised": "2026-10-06T08:32:30.057516362Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-clipboard.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-clipboard.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-clipboard.shanks", - "machine": "shanks", + "id": "node-clipboard.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-clipboard's holder on shanks does not answer the bus: its verbs reach nothing there" + "summary": "node-clipboard's holder on node-d does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.057871793Z", @@ -28,22 +28,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-display-server.g14.silent", + "key": "seat.node-display-server.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.057871793Z", "observations": 1, "raised": "2026-10-06T08:32:30.057871793Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-display-server.g14.silent", + "show": "mesh-controller.conditions key=seat.node-display-server.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-display-server.g14", - "machine": "g14", + "id": "node-display-server.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-display-server's holder on g14 does not answer the bus: its verbs reach nothing there" + "summary": "node-display-server's holder on node-b does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.058097193Z", @@ -51,22 +51,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-display-server.shanks.silent", + "key": "seat.node-display-server.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.058097193Z", "observations": 1, "raised": "2026-10-06T08:32:30.058097193Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-display-server.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-display-server.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-display-server.shanks", - "machine": "shanks", + "id": "node-display-server.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-display-server's holder on shanks does not answer the bus: its verbs reach nothing there" + "summary": "node-display-server's holder on node-d does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.058426864Z", @@ -74,22 +74,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-display-session.g14.silent", + "key": "seat.node-display-session.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.058426864Z", "observations": 1, "raised": "2026-10-06T08:32:30.058426864Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-display-session.g14.silent", + "show": "mesh-controller.conditions key=seat.node-display-session.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-display-session.g14", - "machine": "g14", + "id": "node-display-session.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-display-session's holder on g14 does not answer the bus: its verbs reach nothing there" + "summary": "node-display-session's holder on node-b does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.058721885Z", @@ -97,22 +97,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-display-session.shanks.silent", + "key": "seat.node-display-session.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.058721885Z", "observations": 1, "raised": "2026-10-06T08:32:30.058721885Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-display-session.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-display-session.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-display-session.shanks", - "machine": "shanks", + "id": "node-display-session.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-display-session's holder on shanks does not answer the bus: its verbs reach nothing there" + "summary": "node-display-session's holder on node-d does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.058968226Z", @@ -120,22 +120,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-hostname.ace.silent", + "key": "seat.node-hostname.node-a.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.058968226Z", "observations": 1, "raised": "2026-10-06T08:32:30.058968226Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-hostname.ace.silent", + "show": "mesh-controller.conditions key=seat.node-hostname.node-a.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-hostname.ace", - "machine": "ace", + "id": "node-hostname.node-a", + "machine": "node-a", "scope": "seat" }, - "summary": "node-hostname's holder on ace does not answer the bus: its verbs reach nothing there" + "summary": "node-hostname's holder on node-a does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.059256706Z", @@ -143,22 +143,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-hostname.g14.silent", + "key": "seat.node-hostname.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.059256706Z", "observations": 1, "raised": "2026-10-06T08:32:30.059256706Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-hostname.g14.silent", + "show": "mesh-controller.conditions key=seat.node-hostname.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-hostname.g14", - "machine": "g14", + "id": "node-hostname.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-hostname's holder on g14 does not answer the bus: its verbs reach nothing there" + "summary": "node-hostname's holder on node-b does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.059499037Z", @@ -166,22 +166,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-hostname.novox.silent", + "key": "seat.node-hostname.node-c.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.059499037Z", "observations": 1, "raised": "2026-10-06T08:32:30.059499037Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-hostname.novox.silent", + "show": "mesh-controller.conditions key=seat.node-hostname.node-c.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-hostname.novox", - "machine": "novox", + "id": "node-hostname.node-c", + "machine": "node-c", "scope": "seat" }, - "summary": "node-hostname's holder on novox does not answer the bus: its verbs reach nothing there" + "summary": "node-hostname's holder on node-c does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.059770797Z", @@ -189,22 +189,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-hostname.shanks.silent", + "key": "seat.node-hostname.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.059770797Z", "observations": 1, "raised": "2026-10-06T08:32:30.059770797Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-hostname.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-hostname.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-hostname.shanks", - "machine": "shanks", + "id": "node-hostname.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-hostname's holder on shanks does not answer the bus: its verbs reach nothing there" + "summary": "node-hostname's holder on node-d does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.060058548Z", @@ -212,22 +212,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-intrusion-prevention.ace.silent", + "key": "seat.node-intrusion-prevention.node-a.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.060058548Z", "observations": 1, "raised": "2026-10-06T08:32:30.060058548Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-intrusion-prevention.ace.silent", + "show": "mesh-controller.conditions key=seat.node-intrusion-prevention.node-a.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-intrusion-prevention.ace", - "machine": "ace", + "id": "node-intrusion-prevention.node-a", + "machine": "node-a", "scope": "seat" }, - "summary": "node-intrusion-prevention's holder on ace does not answer the bus: its verbs reach nothing there" + "summary": "node-intrusion-prevention's holder on node-a does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.060295159Z", @@ -235,22 +235,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-intrusion-prevention.g14.silent", + "key": "seat.node-intrusion-prevention.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.060295159Z", "observations": 1, "raised": "2026-10-06T08:32:30.060295159Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-intrusion-prevention.g14.silent", + "show": "mesh-controller.conditions key=seat.node-intrusion-prevention.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-intrusion-prevention.g14", - "machine": "g14", + "id": "node-intrusion-prevention.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-intrusion-prevention's holder on g14 does not answer the bus: its verbs reach nothing there" + "summary": "node-intrusion-prevention's holder on node-b does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.060518809Z", @@ -258,22 +258,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-intrusion-prevention.novox.silent", + "key": "seat.node-intrusion-prevention.node-c.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.060518809Z", "observations": 1, "raised": "2026-10-06T08:32:30.060518809Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-intrusion-prevention.novox.silent", + "show": "mesh-controller.conditions key=seat.node-intrusion-prevention.node-c.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-intrusion-prevention.novox", - "machine": "novox", + "id": "node-intrusion-prevention.node-c", + "machine": "node-c", "scope": "seat" }, - "summary": "node-intrusion-prevention's holder on novox does not answer the bus: its verbs reach nothing there" + "summary": "node-intrusion-prevention's holder on node-c does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.06074635Z", @@ -281,22 +281,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-intrusion-prevention.shanks.silent", + "key": "seat.node-intrusion-prevention.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.06074635Z", "observations": 1, "raised": "2026-10-06T08:32:30.06074635Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-intrusion-prevention.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-intrusion-prevention.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-intrusion-prevention.shanks", - "machine": "shanks", + "id": "node-intrusion-prevention.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-intrusion-prevention's holder on shanks does not answer the bus: its verbs reach nothing there" + "summary": "node-intrusion-prevention's holder on node-d does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.060996311Z", @@ -304,22 +304,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-launcher.g14.silent", + "key": "seat.node-launcher.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.060996311Z", "observations": 1, "raised": "2026-10-06T08:32:30.060996311Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-launcher.g14.silent", + "show": "mesh-controller.conditions key=seat.node-launcher.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-launcher.g14", - "machine": "g14", + "id": "node-launcher.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-launcher's holder on g14 does not answer the bus: its verbs reach nothing there" + "summary": "node-launcher's holder on node-b does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.061271341Z", @@ -327,22 +327,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-launcher.shanks.silent", + "key": "seat.node-launcher.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.061271341Z", "observations": 1, "raised": "2026-10-06T08:32:30.061271341Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-launcher.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-launcher.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-launcher.shanks", - "machine": "shanks", + "id": "node-launcher.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-launcher's holder on shanks does not answer the bus: its verbs reach nothing there" + "summary": "node-launcher's holder on node-d does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.061636702Z", @@ -350,22 +350,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-lock-screen.g14.silent", + "key": "seat.node-lock-screen.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.061636702Z", "observations": 1, "raised": "2026-10-06T08:32:30.061636702Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-lock-screen.g14.silent", + "show": "mesh-controller.conditions key=seat.node-lock-screen.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-lock-screen.g14", - "machine": "g14", + "id": "node-lock-screen.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-lock-screen's holder on g14 does not answer the bus: its verbs reach nothing there" + "summary": "node-lock-screen's holder on node-b does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.061982123Z", @@ -373,22 +373,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-lock-screen.shanks.silent", + "key": "seat.node-lock-screen.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.061982123Z", "observations": 1, "raised": "2026-10-06T08:32:30.061982123Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-lock-screen.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-lock-screen.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-lock-screen.shanks", - "machine": "shanks", + "id": "node-lock-screen.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-lock-screen's holder on shanks does not answer the bus: its verbs reach nothing there" + "summary": "node-lock-screen's holder on node-d does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.062283474Z", @@ -396,22 +396,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-login-manager.g14.silent", + "key": "seat.node-login-manager.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.062283474Z", "observations": 1, "raised": "2026-10-06T08:32:30.062283474Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-login-manager.g14.silent", + "show": "mesh-controller.conditions key=seat.node-login-manager.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-login-manager.g14", - "machine": "g14", + "id": "node-login-manager.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-login-manager's holder on g14 does not answer the bus: its verbs reach nothing there" + "summary": "node-login-manager's holder on node-b does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.062517265Z", @@ -419,22 +419,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-login-manager.shanks.silent", + "key": "seat.node-login-manager.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.062517265Z", "observations": 1, "raised": "2026-10-06T08:32:30.062517265Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-login-manager.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-login-manager.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-login-manager.shanks", - "machine": "shanks", + "id": "node-login-manager.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-login-manager's holder on shanks does not answer the bus: its verbs reach nothing there" + "summary": "node-login-manager's holder on node-d does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.063012266Z", @@ -442,22 +442,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-login-shell.ace.silent", + "key": "seat.node-login-shell.node-a.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.063012266Z", "observations": 1, "raised": "2026-10-06T08:32:30.063012266Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-login-shell.ace.silent", + "show": "mesh-controller.conditions key=seat.node-login-shell.node-a.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-login-shell.ace", - "machine": "ace", + "id": "node-login-shell.node-a", + "machine": "node-a", "scope": "seat" }, - "summary": "node-login-shell's holder on ace does not answer the bus: its verbs reach nothing there" + "summary": "node-login-shell's holder on node-a does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.063292207Z", @@ -465,22 +465,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-login-shell.g14.silent", + "key": "seat.node-login-shell.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.063292207Z", "observations": 1, "raised": "2026-10-06T08:32:30.063292207Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-login-shell.g14.silent", + "show": "mesh-controller.conditions key=seat.node-login-shell.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-login-shell.g14", - "machine": "g14", + "id": "node-login-shell.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-login-shell's holder on g14 does not answer the bus: its verbs reach nothing there" + "summary": "node-login-shell's holder on node-b does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.063697368Z", @@ -488,22 +488,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-login-shell.novox.silent", + "key": "seat.node-login-shell.node-c.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.063697368Z", "observations": 1, "raised": "2026-10-06T08:32:30.063697368Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-login-shell.novox.silent", + "show": "mesh-controller.conditions key=seat.node-login-shell.node-c.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-login-shell.novox", - "machine": "novox", + "id": "node-login-shell.node-c", + "machine": "node-c", "scope": "seat" }, - "summary": "node-login-shell's holder on novox does not answer the bus: its verbs reach nothing there" + "summary": "node-login-shell's holder on node-c does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.063953058Z", @@ -511,22 +511,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-login-shell.shanks.silent", + "key": "seat.node-login-shell.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.063953058Z", "observations": 1, "raised": "2026-10-06T08:32:30.063953058Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-login-shell.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-login-shell.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-login-shell.shanks", - "machine": "shanks", + "id": "node-login-shell.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-login-shell's holder on shanks does not answer the bus: its verbs reach nothing there" + "summary": "node-login-shell's holder on node-d does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.06437673Z", @@ -534,22 +534,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-notifier.g14.silent", + "key": "seat.node-notifier.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.06437673Z", "observations": 1, "raised": "2026-10-06T08:32:30.06437673Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-notifier.g14.silent", + "show": "mesh-controller.conditions key=seat.node-notifier.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-notifier.g14", - "machine": "g14", + "id": "node-notifier.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-notifier's holder on g14 does not answer the bus: its verbs reach nothing there" + "summary": "node-notifier's holder on node-b does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.06463614Z", @@ -557,22 +557,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-notifier.shanks.silent", + "key": "seat.node-notifier.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.06463614Z", "observations": 1, "raised": "2026-10-06T08:32:30.06463614Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-notifier.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-notifier.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-notifier.shanks", - "machine": "shanks", + "id": "node-notifier.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-notifier's holder on shanks does not answer the bus: its verbs reach nothing there" + "summary": "node-notifier's holder on node-d does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.065726493Z", @@ -580,22 +580,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-packet-filter.ace.silent", + "key": "seat.node-packet-filter.node-a.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.065726493Z", "observations": 1, "raised": "2026-10-06T08:32:30.065726493Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-packet-filter.ace.silent", + "show": "mesh-controller.conditions key=seat.node-packet-filter.node-a.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-packet-filter.ace", - "machine": "ace", + "id": "node-packet-filter.node-a", + "machine": "node-a", "scope": "seat" }, - "summary": "node-packet-filter's holder on ace does not answer the bus: its verbs reach nothing there" + "summary": "node-packet-filter's holder on node-a does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.065999204Z", @@ -603,22 +603,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-packet-filter.g14.silent", + "key": "seat.node-packet-filter.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.065999204Z", "observations": 1, "raised": "2026-10-06T08:32:30.065999204Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-packet-filter.g14.silent", + "show": "mesh-controller.conditions key=seat.node-packet-filter.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-packet-filter.g14", - "machine": "g14", + "id": "node-packet-filter.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-packet-filter's holder on g14 does not answer the bus: its verbs reach nothing there" + "summary": "node-packet-filter's holder on node-b does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.066261855Z", @@ -626,22 +626,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-packet-filter.novox.silent", + "key": "seat.node-packet-filter.node-c.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.066261855Z", "observations": 1, "raised": "2026-10-06T08:32:30.066261855Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-packet-filter.novox.silent", + "show": "mesh-controller.conditions key=seat.node-packet-filter.node-c.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-packet-filter.novox", - "machine": "novox", + "id": "node-packet-filter.node-c", + "machine": "node-c", "scope": "seat" }, - "summary": "node-packet-filter's holder on novox does not answer the bus: its verbs reach nothing there" + "summary": "node-packet-filter's holder on node-c does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.066546895Z", @@ -649,22 +649,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-packet-filter.shanks.silent", + "key": "seat.node-packet-filter.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.066546895Z", "observations": 1, "raised": "2026-10-06T08:32:30.066546895Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-packet-filter.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-packet-filter.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-packet-filter.shanks", - "machine": "shanks", + "id": "node-packet-filter.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-packet-filter's holder on shanks does not answer the bus: its verbs reach nothing there" + "summary": "node-packet-filter's holder on node-d does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.066791976Z", @@ -672,22 +672,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-service-manager.ace.silent", + "key": "seat.node-service-manager.node-a.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.066791976Z", "observations": 1, "raised": "2026-10-06T08:32:30.066791976Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-service-manager.ace.silent", + "show": "mesh-controller.conditions key=seat.node-service-manager.node-a.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-service-manager.ace", - "machine": "ace", + "id": "node-service-manager.node-a", + "machine": "node-a", "scope": "seat" }, - "summary": "node-service-manager's holder on ace does not answer the bus: its verbs reach nothing there" + "summary": "node-service-manager's holder on node-a does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.067159597Z", @@ -695,22 +695,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-service-manager.g14.silent", + "key": "seat.node-service-manager.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.067159597Z", "observations": 1, "raised": "2026-10-06T08:32:30.067159597Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-service-manager.g14.silent", + "show": "mesh-controller.conditions key=seat.node-service-manager.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-service-manager.g14", - "machine": "g14", + "id": "node-service-manager.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-service-manager's holder on g14 does not answer the bus: its verbs reach nothing there" + "summary": "node-service-manager's holder on node-b does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.067959759Z", @@ -718,22 +718,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-service-manager.novox.silent", + "key": "seat.node-service-manager.node-c.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.067959759Z", "observations": 1, "raised": "2026-10-06T08:32:30.067959759Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-service-manager.novox.silent", + "show": "mesh-controller.conditions key=seat.node-service-manager.node-c.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-service-manager.novox", - "machine": "novox", + "id": "node-service-manager.node-c", + "machine": "node-c", "scope": "seat" }, - "summary": "node-service-manager's holder on novox does not answer the bus: its verbs reach nothing there" + "summary": "node-service-manager's holder on node-c does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.068622421Z", @@ -741,22 +741,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-service-manager.shanks.silent", + "key": "seat.node-service-manager.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.068622421Z", "observations": 1, "raised": "2026-10-06T08:32:30.068622421Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-service-manager.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-service-manager.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-service-manager.shanks", - "machine": "shanks", + "id": "node-service-manager.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-service-manager's holder on shanks does not answer the bus: its verbs reach nothing there" + "summary": "node-service-manager's holder on node-d does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.069113732Z", @@ -764,22 +764,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-terminal-emulator.g14.silent", + "key": "seat.node-terminal-emulator.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.069113732Z", "observations": 1, "raised": "2026-10-06T08:32:30.069113732Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-terminal-emulator.g14.silent", + "show": "mesh-controller.conditions key=seat.node-terminal-emulator.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-terminal-emulator.g14", - "machine": "g14", + "id": "node-terminal-emulator.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-terminal-emulator's holder on g14 does not answer the bus: its verbs reach nothing there" + "summary": "node-terminal-emulator's holder on node-b does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:30.070533516Z", @@ -787,22 +787,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "seat.node-terminal-emulator.shanks.silent", + "key": "seat.node-terminal-emulator.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.070533516Z", "observations": 1, "raised": "2026-10-06T08:32:30.070533516Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-terminal-emulator.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-terminal-emulator.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-terminal-emulator.shanks", - "machine": "shanks", + "id": "node-terminal-emulator.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-terminal-emulator's holder on shanks does not answer the bus: its verbs reach nothing there" + "summary": "node-terminal-emulator's holder on node-d does not answer the bus: its verbs reach nothing there" }, { "at": "2026-10-06T08:32:50.075279606Z", @@ -822,10 +822,10 @@ "source": "S9", "subject": { "id": "controller", - "machine": "novox", + "machine": "node-c", "scope": "bus" }, - "summary": "the bus refused the controller: nats: permissions violation: Permissions Violation for Publish to \"$KV.mesh-controller_conditions.seat.node-clipboard.g14.silent\" (18 times since 08:30 UTC)" + "summary": "the bus refused the controller: nats: permissions violation: Permissions Violation for Publish to \"$KV.mesh-controller_conditions.seat.node-clipboard.node-b.silent\" (18 times since 08:30 UTC)" }, { "at": "2026-10-06T08:33:20.099570197Z", @@ -833,22 +833,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "machine.novox.tools-silent", + "key": "machine.node-c.tools-silent", "kind": "tools-silent", "last-observed": "2026-10-06T08:33:20.099570197Z", "observations": 1, "raised": "2026-10-06T08:33:20.099570197Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=machine.novox.tools-silent", + "show": "mesh-controller.conditions key=machine.node-c.tools-silent", "silenced": null, "source": "S11", "subject": { - "id": "novox", - "machine": "novox", + "id": "node-c", + "machine": "node-c", "scope": "machine" }, - "summary": "the node tools on novox have not said they are there not since this controller started at 2026-10-06 08:30 UTC (bound 3m0s): nothing can ask that machine anything" + "summary": "the node tools on node-c have not said they are there not since this controller started at 2026-10-06 08:30 UTC (bound 3m0s): nothing can ask that machine anything" }, { "at": "2026-10-06T08:33:20.099854198Z", @@ -856,22 +856,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "machine.ace.tools-silent", + "key": "machine.node-a.tools-silent", "kind": "tools-silent", "last-observed": "2026-10-06T08:33:20.099854198Z", "observations": 1, "raised": "2026-10-06T08:33:20.099854198Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=machine.ace.tools-silent", + "show": "mesh-controller.conditions key=machine.node-a.tools-silent", "silenced": null, "source": "S11", "subject": { - "id": "ace", - "machine": "ace", + "id": "node-a", + "machine": "node-a", "scope": "machine" }, - "summary": "the node tools on ace have not said they are there not since this controller started at 2026-10-06 08:30 UTC (bound 3m0s): nothing can ask that machine anything" + "summary": "the node tools on node-a have not said they are there not since this controller started at 2026-10-06 08:30 UTC (bound 3m0s): nothing can ask that machine anything" }, { "at": "2026-10-06T08:33:20.100089578Z", @@ -879,22 +879,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "machine.shanks.tools-silent", + "key": "machine.node-d.tools-silent", "kind": "tools-silent", "last-observed": "2026-10-06T08:33:20.100089578Z", "observations": 1, "raised": "2026-10-06T08:33:20.100089578Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=machine.shanks.tools-silent", + "show": "mesh-controller.conditions key=machine.node-d.tools-silent", "silenced": null, "source": "S11", "subject": { - "id": "shanks", - "machine": "shanks", + "id": "node-d", + "machine": "node-d", "scope": "machine" }, - "summary": "the node tools on shanks have not said they are there not since this controller started at 2026-10-06 08:30 UTC (bound 3m0s): nothing can ask that machine anything" + "summary": "the node tools on node-d have not said they are there not since this controller started at 2026-10-06 08:30 UTC (bound 3m0s): nothing can ask that machine anything" }, { "at": "2026-10-06T08:33:20.100337919Z", @@ -902,22 +902,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "machine.g14.tools-silent", + "key": "machine.node-b.tools-silent", "kind": "tools-silent", "last-observed": "2026-10-06T08:33:20.100337919Z", "observations": 1, "raised": "2026-10-06T08:33:20.100337919Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=machine.g14.tools-silent", + "show": "mesh-controller.conditions key=machine.node-b.tools-silent", "silenced": null, "source": "S11", "subject": { - "id": "g14", - "machine": "g14", + "id": "node-b", + "machine": "node-b", "scope": "machine" }, - "summary": "the node tools on g14 have not said they are there not since this controller started at 2026-10-06 08:30 UTC (bound 3m0s): nothing can ask that machine anything" + "summary": "the node tools on node-b have not said they are there not since this controller started at 2026-10-06 08:30 UTC (bound 3m0s): nothing can ask that machine anything" }, { "at": "2026-10-06T08:36:50.042087261Z", @@ -926,22 +926,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-clipboard.shanks.silent", + "key": "seat.node-clipboard.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.057516362Z", "observations": 1, "raised": "2026-10-06T08:32:30.057516362Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-clipboard.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-clipboard.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-clipboard.shanks", - "machine": "shanks", + "id": "node-clipboard.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-clipboard's holder on shanks does not answer the bus: its verbs reach nothing there", + "summary": "node-clipboard's holder on node-d does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -951,22 +951,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-display-server.g14.silent", + "key": "seat.node-display-server.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.057871793Z", "observations": 1, "raised": "2026-10-06T08:32:30.057871793Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-display-server.g14.silent", + "show": "mesh-controller.conditions key=seat.node-display-server.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-display-server.g14", - "machine": "g14", + "id": "node-display-server.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-display-server's holder on g14 does not answer the bus: its verbs reach nothing there", + "summary": "node-display-server's holder on node-b does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -976,22 +976,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-display-server.shanks.silent", + "key": "seat.node-display-server.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.058097193Z", "observations": 1, "raised": "2026-10-06T08:32:30.058097193Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-display-server.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-display-server.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-display-server.shanks", - "machine": "shanks", + "id": "node-display-server.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-display-server's holder on shanks does not answer the bus: its verbs reach nothing there", + "summary": "node-display-server's holder on node-d does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1001,22 +1001,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-display-session.g14.silent", + "key": "seat.node-display-session.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.058426864Z", "observations": 1, "raised": "2026-10-06T08:32:30.058426864Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-display-session.g14.silent", + "show": "mesh-controller.conditions key=seat.node-display-session.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-display-session.g14", - "machine": "g14", + "id": "node-display-session.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-display-session's holder on g14 does not answer the bus: its verbs reach nothing there", + "summary": "node-display-session's holder on node-b does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1026,22 +1026,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-display-session.shanks.silent", + "key": "seat.node-display-session.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.058721885Z", "observations": 1, "raised": "2026-10-06T08:32:30.058721885Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-display-session.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-display-session.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-display-session.shanks", - "machine": "shanks", + "id": "node-display-session.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-display-session's holder on shanks does not answer the bus: its verbs reach nothing there", + "summary": "node-display-session's holder on node-d does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1051,22 +1051,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-hostname.ace.silent", + "key": "seat.node-hostname.node-a.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.058968226Z", "observations": 1, "raised": "2026-10-06T08:32:30.058968226Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-hostname.ace.silent", + "show": "mesh-controller.conditions key=seat.node-hostname.node-a.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-hostname.ace", - "machine": "ace", + "id": "node-hostname.node-a", + "machine": "node-a", "scope": "seat" }, - "summary": "node-hostname's holder on ace does not answer the bus: its verbs reach nothing there", + "summary": "node-hostname's holder on node-a does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1076,22 +1076,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-hostname.g14.silent", + "key": "seat.node-hostname.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.059256706Z", "observations": 1, "raised": "2026-10-06T08:32:30.059256706Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-hostname.g14.silent", + "show": "mesh-controller.conditions key=seat.node-hostname.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-hostname.g14", - "machine": "g14", + "id": "node-hostname.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-hostname's holder on g14 does not answer the bus: its verbs reach nothing there", + "summary": "node-hostname's holder on node-b does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1101,22 +1101,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-hostname.novox.silent", + "key": "seat.node-hostname.node-c.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.059499037Z", "observations": 1, "raised": "2026-10-06T08:32:30.059499037Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-hostname.novox.silent", + "show": "mesh-controller.conditions key=seat.node-hostname.node-c.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-hostname.novox", - "machine": "novox", + "id": "node-hostname.node-c", + "machine": "node-c", "scope": "seat" }, - "summary": "node-hostname's holder on novox does not answer the bus: its verbs reach nothing there", + "summary": "node-hostname's holder on node-c does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1126,22 +1126,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-hostname.shanks.silent", + "key": "seat.node-hostname.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.059770797Z", "observations": 1, "raised": "2026-10-06T08:32:30.059770797Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-hostname.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-hostname.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-hostname.shanks", - "machine": "shanks", + "id": "node-hostname.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-hostname's holder on shanks does not answer the bus: its verbs reach nothing there", + "summary": "node-hostname's holder on node-d does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1151,22 +1151,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-intrusion-prevention.ace.silent", + "key": "seat.node-intrusion-prevention.node-a.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.060058548Z", "observations": 1, "raised": "2026-10-06T08:32:30.060058548Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-intrusion-prevention.ace.silent", + "show": "mesh-controller.conditions key=seat.node-intrusion-prevention.node-a.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-intrusion-prevention.ace", - "machine": "ace", + "id": "node-intrusion-prevention.node-a", + "machine": "node-a", "scope": "seat" }, - "summary": "node-intrusion-prevention's holder on ace does not answer the bus: its verbs reach nothing there", + "summary": "node-intrusion-prevention's holder on node-a does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1176,22 +1176,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-intrusion-prevention.g14.silent", + "key": "seat.node-intrusion-prevention.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.060295159Z", "observations": 1, "raised": "2026-10-06T08:32:30.060295159Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-intrusion-prevention.g14.silent", + "show": "mesh-controller.conditions key=seat.node-intrusion-prevention.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-intrusion-prevention.g14", - "machine": "g14", + "id": "node-intrusion-prevention.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-intrusion-prevention's holder on g14 does not answer the bus: its verbs reach nothing there", + "summary": "node-intrusion-prevention's holder on node-b does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1201,22 +1201,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-intrusion-prevention.novox.silent", + "key": "seat.node-intrusion-prevention.node-c.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.060518809Z", "observations": 1, "raised": "2026-10-06T08:32:30.060518809Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-intrusion-prevention.novox.silent", + "show": "mesh-controller.conditions key=seat.node-intrusion-prevention.node-c.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-intrusion-prevention.novox", - "machine": "novox", + "id": "node-intrusion-prevention.node-c", + "machine": "node-c", "scope": "seat" }, - "summary": "node-intrusion-prevention's holder on novox does not answer the bus: its verbs reach nothing there", + "summary": "node-intrusion-prevention's holder on node-c does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1226,22 +1226,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-intrusion-prevention.shanks.silent", + "key": "seat.node-intrusion-prevention.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.06074635Z", "observations": 1, "raised": "2026-10-06T08:32:30.06074635Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-intrusion-prevention.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-intrusion-prevention.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-intrusion-prevention.shanks", - "machine": "shanks", + "id": "node-intrusion-prevention.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-intrusion-prevention's holder on shanks does not answer the bus: its verbs reach nothing there", + "summary": "node-intrusion-prevention's holder on node-d does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1251,22 +1251,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-launcher.g14.silent", + "key": "seat.node-launcher.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.060996311Z", "observations": 1, "raised": "2026-10-06T08:32:30.060996311Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-launcher.g14.silent", + "show": "mesh-controller.conditions key=seat.node-launcher.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-launcher.g14", - "machine": "g14", + "id": "node-launcher.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-launcher's holder on g14 does not answer the bus: its verbs reach nothing there", + "summary": "node-launcher's holder on node-b does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1276,22 +1276,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-launcher.shanks.silent", + "key": "seat.node-launcher.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.061271341Z", "observations": 1, "raised": "2026-10-06T08:32:30.061271341Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-launcher.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-launcher.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-launcher.shanks", - "machine": "shanks", + "id": "node-launcher.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-launcher's holder on shanks does not answer the bus: its verbs reach nothing there", + "summary": "node-launcher's holder on node-d does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1301,22 +1301,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-lock-screen.g14.silent", + "key": "seat.node-lock-screen.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.061636702Z", "observations": 1, "raised": "2026-10-06T08:32:30.061636702Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-lock-screen.g14.silent", + "show": "mesh-controller.conditions key=seat.node-lock-screen.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-lock-screen.g14", - "machine": "g14", + "id": "node-lock-screen.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-lock-screen's holder on g14 does not answer the bus: its verbs reach nothing there", + "summary": "node-lock-screen's holder on node-b does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1326,22 +1326,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-lock-screen.shanks.silent", + "key": "seat.node-lock-screen.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.061982123Z", "observations": 1, "raised": "2026-10-06T08:32:30.061982123Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-lock-screen.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-lock-screen.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-lock-screen.shanks", - "machine": "shanks", + "id": "node-lock-screen.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-lock-screen's holder on shanks does not answer the bus: its verbs reach nothing there", + "summary": "node-lock-screen's holder on node-d does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1351,22 +1351,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-login-manager.g14.silent", + "key": "seat.node-login-manager.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.062283474Z", "observations": 1, "raised": "2026-10-06T08:32:30.062283474Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-login-manager.g14.silent", + "show": "mesh-controller.conditions key=seat.node-login-manager.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-login-manager.g14", - "machine": "g14", + "id": "node-login-manager.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-login-manager's holder on g14 does not answer the bus: its verbs reach nothing there", + "summary": "node-login-manager's holder on node-b does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1376,22 +1376,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-login-manager.shanks.silent", + "key": "seat.node-login-manager.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.062517265Z", "observations": 1, "raised": "2026-10-06T08:32:30.062517265Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-login-manager.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-login-manager.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-login-manager.shanks", - "machine": "shanks", + "id": "node-login-manager.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-login-manager's holder on shanks does not answer the bus: its verbs reach nothing there", + "summary": "node-login-manager's holder on node-d does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1401,22 +1401,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-login-shell.ace.silent", + "key": "seat.node-login-shell.node-a.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.063012266Z", "observations": 1, "raised": "2026-10-06T08:32:30.063012266Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-login-shell.ace.silent", + "show": "mesh-controller.conditions key=seat.node-login-shell.node-a.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-login-shell.ace", - "machine": "ace", + "id": "node-login-shell.node-a", + "machine": "node-a", "scope": "seat" }, - "summary": "node-login-shell's holder on ace does not answer the bus: its verbs reach nothing there", + "summary": "node-login-shell's holder on node-a does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1426,22 +1426,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-login-shell.g14.silent", + "key": "seat.node-login-shell.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.063292207Z", "observations": 1, "raised": "2026-10-06T08:32:30.063292207Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-login-shell.g14.silent", + "show": "mesh-controller.conditions key=seat.node-login-shell.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-login-shell.g14", - "machine": "g14", + "id": "node-login-shell.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-login-shell's holder on g14 does not answer the bus: its verbs reach nothing there", + "summary": "node-login-shell's holder on node-b does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1451,22 +1451,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-login-shell.novox.silent", + "key": "seat.node-login-shell.node-c.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.063697368Z", "observations": 1, "raised": "2026-10-06T08:32:30.063697368Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-login-shell.novox.silent", + "show": "mesh-controller.conditions key=seat.node-login-shell.node-c.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-login-shell.novox", - "machine": "novox", + "id": "node-login-shell.node-c", + "machine": "node-c", "scope": "seat" }, - "summary": "node-login-shell's holder on novox does not answer the bus: its verbs reach nothing there", + "summary": "node-login-shell's holder on node-c does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1476,22 +1476,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-login-shell.shanks.silent", + "key": "seat.node-login-shell.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.063953058Z", "observations": 1, "raised": "2026-10-06T08:32:30.063953058Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-login-shell.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-login-shell.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-login-shell.shanks", - "machine": "shanks", + "id": "node-login-shell.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-login-shell's holder on shanks does not answer the bus: its verbs reach nothing there", + "summary": "node-login-shell's holder on node-d does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1501,22 +1501,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-notifier.g14.silent", + "key": "seat.node-notifier.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.06437673Z", "observations": 1, "raised": "2026-10-06T08:32:30.06437673Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-notifier.g14.silent", + "show": "mesh-controller.conditions key=seat.node-notifier.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-notifier.g14", - "machine": "g14", + "id": "node-notifier.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-notifier's holder on g14 does not answer the bus: its verbs reach nothing there", + "summary": "node-notifier's holder on node-b does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1526,22 +1526,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-notifier.shanks.silent", + "key": "seat.node-notifier.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.06463614Z", "observations": 1, "raised": "2026-10-06T08:32:30.06463614Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-notifier.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-notifier.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-notifier.shanks", - "machine": "shanks", + "id": "node-notifier.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-notifier's holder on shanks does not answer the bus: its verbs reach nothing there", + "summary": "node-notifier's holder on node-d does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1551,22 +1551,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-packet-filter.ace.silent", + "key": "seat.node-packet-filter.node-a.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.065726493Z", "observations": 1, "raised": "2026-10-06T08:32:30.065726493Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-packet-filter.ace.silent", + "show": "mesh-controller.conditions key=seat.node-packet-filter.node-a.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-packet-filter.ace", - "machine": "ace", + "id": "node-packet-filter.node-a", + "machine": "node-a", "scope": "seat" }, - "summary": "node-packet-filter's holder on ace does not answer the bus: its verbs reach nothing there", + "summary": "node-packet-filter's holder on node-a does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1576,22 +1576,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-packet-filter.g14.silent", + "key": "seat.node-packet-filter.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.065999204Z", "observations": 1, "raised": "2026-10-06T08:32:30.065999204Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-packet-filter.g14.silent", + "show": "mesh-controller.conditions key=seat.node-packet-filter.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-packet-filter.g14", - "machine": "g14", + "id": "node-packet-filter.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-packet-filter's holder on g14 does not answer the bus: its verbs reach nothing there", + "summary": "node-packet-filter's holder on node-b does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1601,22 +1601,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-packet-filter.novox.silent", + "key": "seat.node-packet-filter.node-c.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.066261855Z", "observations": 1, "raised": "2026-10-06T08:32:30.066261855Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-packet-filter.novox.silent", + "show": "mesh-controller.conditions key=seat.node-packet-filter.node-c.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-packet-filter.novox", - "machine": "novox", + "id": "node-packet-filter.node-c", + "machine": "node-c", "scope": "seat" }, - "summary": "node-packet-filter's holder on novox does not answer the bus: its verbs reach nothing there", + "summary": "node-packet-filter's holder on node-c does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1626,22 +1626,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-packet-filter.shanks.silent", + "key": "seat.node-packet-filter.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.066546895Z", "observations": 1, "raised": "2026-10-06T08:32:30.066546895Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-packet-filter.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-packet-filter.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-packet-filter.shanks", - "machine": "shanks", + "id": "node-packet-filter.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-packet-filter's holder on shanks does not answer the bus: its verbs reach nothing there", + "summary": "node-packet-filter's holder on node-d does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1651,22 +1651,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-service-manager.ace.silent", + "key": "seat.node-service-manager.node-a.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.066791976Z", "observations": 1, "raised": "2026-10-06T08:32:30.066791976Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-service-manager.ace.silent", + "show": "mesh-controller.conditions key=seat.node-service-manager.node-a.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-service-manager.ace", - "machine": "ace", + "id": "node-service-manager.node-a", + "machine": "node-a", "scope": "seat" }, - "summary": "node-service-manager's holder on ace does not answer the bus: its verbs reach nothing there", + "summary": "node-service-manager's holder on node-a does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1676,22 +1676,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-service-manager.g14.silent", + "key": "seat.node-service-manager.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.067159597Z", "observations": 1, "raised": "2026-10-06T08:32:30.067159597Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-service-manager.g14.silent", + "show": "mesh-controller.conditions key=seat.node-service-manager.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-service-manager.g14", - "machine": "g14", + "id": "node-service-manager.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-service-manager's holder on g14 does not answer the bus: its verbs reach nothing there", + "summary": "node-service-manager's holder on node-b does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1701,22 +1701,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-service-manager.novox.silent", + "key": "seat.node-service-manager.node-c.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.067959759Z", "observations": 1, "raised": "2026-10-06T08:32:30.067959759Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-service-manager.novox.silent", + "show": "mesh-controller.conditions key=seat.node-service-manager.node-c.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-service-manager.novox", - "machine": "novox", + "id": "node-service-manager.node-c", + "machine": "node-c", "scope": "seat" }, - "summary": "node-service-manager's holder on novox does not answer the bus: its verbs reach nothing there", + "summary": "node-service-manager's holder on node-c does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1726,22 +1726,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-service-manager.shanks.silent", + "key": "seat.node-service-manager.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.068622421Z", "observations": 1, "raised": "2026-10-06T08:32:30.068622421Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-service-manager.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-service-manager.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-service-manager.shanks", - "machine": "shanks", + "id": "node-service-manager.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-service-manager's holder on shanks does not answer the bus: its verbs reach nothing there", + "summary": "node-service-manager's holder on node-d does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1751,22 +1751,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-terminal-emulator.g14.silent", + "key": "seat.node-terminal-emulator.node-b.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.069113732Z", "observations": 1, "raised": "2026-10-06T08:32:30.069113732Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-terminal-emulator.g14.silent", + "show": "mesh-controller.conditions key=seat.node-terminal-emulator.node-b.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-terminal-emulator.g14", - "machine": "g14", + "id": "node-terminal-emulator.node-b", + "machine": "node-b", "scope": "seat" }, - "summary": "node-terminal-emulator's holder on g14 does not answer the bus: its verbs reach nothing there", + "summary": "node-terminal-emulator's holder on node-b does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1776,22 +1776,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "seat.node-terminal-emulator.shanks.silent", + "key": "seat.node-terminal-emulator.node-d.silent", "kind": "holder-silent", "last-observed": "2026-10-06T08:32:30.070533516Z", "observations": 1, "raised": "2026-10-06T08:32:30.070533516Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=seat.node-terminal-emulator.shanks.silent", + "show": "mesh-controller.conditions key=seat.node-terminal-emulator.node-d.silent", "silenced": null, "source": "D3", "subject": { - "id": "node-terminal-emulator.shanks", - "machine": "shanks", + "id": "node-terminal-emulator.node-d", + "machine": "node-d", "scope": "seat" }, - "summary": "node-terminal-emulator's holder on shanks does not answer the bus: its verbs reach nothing there", + "summary": "node-terminal-emulator's holder on node-d does not answer the bus: its verbs reach nothing there", "why": "D3 no longer observes it" }, { @@ -1800,22 +1800,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "machine.novox.core-behind", + "key": "machine.node-c.core-behind", "kind": "core-behind", "last-observed": "2026-10-06T08:36:50.063776538Z", "observations": 1, "raised": "2026-10-06T08:36:50.063776538Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=machine.novox.core-behind", + "show": "mesh-controller.conditions key=machine.node-c.core-behind", "silenced": null, "source": "D10", "subject": { - "id": "novox", - "machine": "novox", + "id": "node-c", + "machine": "node-c", "scope": "machine" }, - "summary": "novox runs the node-engine 31045596, the mesh holds 1545b00a; the node tools it was last sent, not yet reported applied, and no plan is rolling them out" + "summary": "node-c runs the node-engine 31045596, the mesh holds 1545b00a; the node tools it was last sent, not yet reported applied, and no plan is rolling them out" }, { "at": "2026-10-06T08:36:50.064278109Z", @@ -1823,22 +1823,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "machine.ace.core-behind", + "key": "machine.node-a.core-behind", "kind": "core-behind", "last-observed": "2026-10-06T08:36:50.064278109Z", "observations": 1, "raised": "2026-10-06T08:36:50.064278109Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=machine.ace.core-behind", + "show": "mesh-controller.conditions key=machine.node-a.core-behind", "silenced": null, "source": "D10", "subject": { - "id": "ace", - "machine": "ace", + "id": "node-a", + "machine": "node-a", "scope": "machine" }, - "summary": "ace runs the node-engine d49d9a95, the mesh holds 1545b00a; the node tools it was last sent, not yet reported applied, and no plan is rolling them out" + "summary": "node-a runs the node-engine d49d9a95, the mesh holds 1545b00a; the node tools it was last sent, not yet reported applied, and no plan is rolling them out" }, { "at": "2026-10-06T08:36:50.06486367Z", @@ -1846,22 +1846,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "machine.shanks.core-behind", + "key": "machine.node-d.core-behind", "kind": "core-behind", "last-observed": "2026-10-06T08:36:50.06486367Z", "observations": 1, "raised": "2026-10-06T08:36:50.06486367Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=machine.shanks.core-behind", + "show": "mesh-controller.conditions key=machine.node-d.core-behind", "silenced": null, "source": "D10", "subject": { - "id": "shanks", - "machine": "shanks", + "id": "node-d", + "machine": "node-d", "scope": "machine" }, - "summary": "shanks runs the node-engine d49d9a95, the mesh holds 1545b00a; the node tools it was last sent, not yet reported applied, and no plan is rolling them out" + "summary": "node-d runs the node-engine d49d9a95, the mesh holds 1545b00a; the node tools it was last sent, not yet reported applied, and no plan is rolling them out" }, { "at": "2026-10-06T08:36:50.065185711Z", @@ -1869,22 +1869,22 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "machine.g14.core-behind", + "key": "machine.node-b.core-behind", "kind": "core-behind", "last-observed": "2026-10-06T08:36:50.065185711Z", "observations": 1, "raised": "2026-10-06T08:36:50.065185711Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=machine.g14.core-behind", + "show": "mesh-controller.conditions key=machine.node-b.core-behind", "silenced": null, "source": "D10", "subject": { - "id": "g14", - "machine": "g14", + "id": "node-b", + "machine": "node-b", "scope": "machine" }, - "summary": "g14 runs the node-engine d49d9a95, the mesh holds 1545b00a; the node tools it was last sent, not yet reported applied, and no plan is rolling them out" + "summary": "node-b runs the node-engine d49d9a95, the mesh holds 1545b00a; the node tools it was last sent, not yet reported applied, and no plan is rolling them out" }, { "at": "2026-10-06T08:36:50.067828596Z", @@ -1915,22 +1915,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "machine.novox.tools-silent", + "key": "machine.node-c.tools-silent", "kind": "tools-silent", "last-observed": "2026-10-06T08:36:20.129780419Z", "observations": 7, "raised": "2026-10-06T08:33:20.099570197Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=machine.novox.tools-silent", + "show": "mesh-controller.conditions key=machine.node-c.tools-silent", "silenced": null, "source": "S11", "subject": { - "id": "novox", - "machine": "novox", + "id": "node-c", + "machine": "node-c", "scope": "machine" }, - "summary": "the node tools on novox have not said they are there not since this controller started at 2026-10-06 08:30 UTC (bound 3m0s): nothing can ask that machine anything", + "summary": "the node tools on node-c have not said they are there not since this controller started at 2026-10-06 08:30 UTC (bound 3m0s): nothing can ask that machine anything", "why": "S11 no longer observes it" }, { @@ -1940,22 +1940,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "machine.ace.tools-silent", + "key": "machine.node-a.tools-silent", "kind": "tools-silent", "last-observed": "2026-10-06T08:36:20.13023719Z", "observations": 7, "raised": "2026-10-06T08:33:20.099854198Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=machine.ace.tools-silent", + "show": "mesh-controller.conditions key=machine.node-a.tools-silent", "silenced": null, "source": "S11", "subject": { - "id": "ace", - "machine": "ace", + "id": "node-a", + "machine": "node-a", "scope": "machine" }, - "summary": "the node tools on ace have not said they are there not since this controller started at 2026-10-06 08:30 UTC (bound 3m0s): nothing can ask that machine anything", + "summary": "the node tools on node-a have not said they are there not since this controller started at 2026-10-06 08:30 UTC (bound 3m0s): nothing can ask that machine anything", "why": "S11 no longer observes it" }, { @@ -1965,22 +1965,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "machine.shanks.tools-silent", + "key": "machine.node-d.tools-silent", "kind": "tools-silent", "last-observed": "2026-10-06T08:36:20.131261612Z", "observations": 7, "raised": "2026-10-06T08:33:20.100089578Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=machine.shanks.tools-silent", + "show": "mesh-controller.conditions key=machine.node-d.tools-silent", "silenced": null, "source": "S11", "subject": { - "id": "shanks", - "machine": "shanks", + "id": "node-d", + "machine": "node-d", "scope": "machine" }, - "summary": "the node tools on shanks have not said they are there not since this controller started at 2026-10-06 08:30 UTC (bound 3m0s): nothing can ask that machine anything", + "summary": "the node tools on node-d have not said they are there not since this controller started at 2026-10-06 08:30 UTC (bound 3m0s): nothing can ask that machine anything", "why": "S11 no longer observes it" }, { @@ -1990,22 +1990,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "machine.g14.tools-silent", + "key": "machine.node-b.tools-silent", "kind": "tools-silent", "last-observed": "2026-10-06T08:36:20.131706843Z", "observations": 7, "raised": "2026-10-06T08:33:20.100337919Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=machine.g14.tools-silent", + "show": "mesh-controller.conditions key=machine.node-b.tools-silent", "silenced": null, "source": "S11", "subject": { - "id": "g14", - "machine": "g14", + "id": "node-b", + "machine": "node-b", "scope": "machine" }, - "summary": "the node tools on g14 have not said they are there not since this controller started at 2026-10-06 08:30 UTC (bound 3m0s): nothing can ask that machine anything", + "summary": "the node tools on node-b have not said they are there not since this controller started at 2026-10-06 08:30 UTC (bound 3m0s): nothing can ask that machine anything", "why": "S11 no longer observes it" }, { @@ -2073,10 +2073,10 @@ "source": "S9", "subject": { "id": "controller", - "machine": "novox", + "machine": "node-c", "scope": "bus" }, - "summary": "the bus refused the controller: nats: permissions violation: Permissions Violation for Publish to \"mesh.seat.node-intrusion-prevention.tool.banned.novox\" (30 times since 08:30 UTC)", + "summary": "the bus refused the controller: nats: permissions violation: Permissions Violation for Publish to \"mesh.seat.node-intrusion-prevention.tool.banned.node-c\" (30 times since 08:30 UTC)", "why": "S9 no longer observes it" }, { @@ -2097,10 +2097,10 @@ "source": "S9", "subject": { "id": "controller", - "machine": "novox", + "machine": "node-c", "scope": "bus" }, - "summary": "the bus refused the controller: nats: permissions violation: Permissions Violation for Publish to \"mesh.seat.node-intrusion-prevention.tool.banned.g14\" (4 times since 08:51 UTC)" + "summary": "the bus refused the controller: nats: permissions violation: Permissions Violation for Publish to \"mesh.seat.node-intrusion-prevention.tool.banned.node-b\" (4 times since 08:51 UTC)" }, { "at": "2026-10-06T08:51:54.485229269Z", @@ -2109,22 +2109,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "machine.novox.core-behind", + "key": "machine.node-c.core-behind", "kind": "core-behind", "last-observed": "2026-10-06T08:46:50.051748101Z", "observations": 4, "raised": "2026-10-06T08:36:50.063776538Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=machine.novox.core-behind", + "show": "mesh-controller.conditions key=machine.node-c.core-behind", "silenced": null, "source": "D10", "subject": { - "id": "novox", - "machine": "novox", + "id": "node-c", + "machine": "node-c", "scope": "machine" }, - "summary": "novox runs the node-engine 31045596, the mesh holds 1545b00a, and no plan is rolling them out", + "summary": "node-c runs the node-engine 31045596, the mesh holds 1545b00a, and no plan is rolling them out", "why": "D10 no longer observes it" }, { @@ -2134,22 +2134,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "machine.shanks.core-behind", + "key": "machine.node-d.core-behind", "kind": "core-behind", "last-observed": "2026-10-06T08:51:54.476786016Z", "observations": 5, "raised": "2026-10-06T08:36:50.06486367Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=machine.shanks.core-behind", + "show": "mesh-controller.conditions key=machine.node-d.core-behind", "silenced": null, "source": "D10", "subject": { - "id": "shanks", - "machine": "shanks", + "id": "node-d", + "machine": "node-d", "scope": "machine" }, - "summary": "shanks runs the node-engine 31045596c83a, the mesh holds a914848b8990 (built from d7d93f57), and no plan is rolling them out", + "summary": "node-d runs the node-engine 31045596c83a, the mesh holds a914848b8990 (built from d7d93f57), and no plan is rolling them out", "why": "D10 no longer observes it" }, { @@ -2159,22 +2159,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "machine.g14.core-behind", + "key": "machine.node-b.core-behind", "kind": "core-behind", "last-observed": "2026-10-06T08:51:54.477343986Z", "observations": 5, "raised": "2026-10-06T08:36:50.065185711Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=machine.g14.core-behind", + "show": "mesh-controller.conditions key=machine.node-b.core-behind", "silenced": null, "source": "D10", "subject": { - "id": "g14", - "machine": "g14", + "id": "node-b", + "machine": "node-b", "scope": "machine" }, - "summary": "g14 runs the node-engine 31045596c83a, the mesh holds a914848b8990 (built from d7d93f57), and no plan is rolling them out", + "summary": "node-b runs the node-engine 31045596c83a, the mesh holds a914848b8990 (built from d7d93f57), and no plan is rolling them out", "why": "D10 no longer observes it" }, { @@ -2208,22 +2208,22 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "machine.ace.core-behind", + "key": "machine.node-a.core-behind", "kind": "core-behind", "last-observed": "2026-10-06T08:54:52.412005339Z", "observations": 6, "raised": "2026-10-06T08:36:50.064278109Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=machine.ace.core-behind", + "show": "mesh-controller.conditions key=machine.node-a.core-behind", "silenced": null, "source": "D10", "subject": { - "id": "ace", - "machine": "ace", + "id": "node-a", + "machine": "node-a", "scope": "machine" }, - "summary": "ace runs the node-engine 31045596c83a, the mesh holds a914848b8990 (built from d7d93f57), and no plan is rolling them out", + "summary": "node-a runs the node-engine 31045596c83a, the mesh holds a914848b8990 (built from d7d93f57), and no plan is rolling them out", "why": "D10 no longer observes it" }, { @@ -2232,21 +2232,21 @@ "count": 1, "epoch": 0, "event": "condition-raised", - "key": "bus.EVENTS.novox_messenger.missing", + "key": "bus.EVENTS.node-c_messenger.missing", "kind": "consumer-lost", "last-observed": "2026-10-06T09:36:52.655368241Z", "observations": 1, "raised": "2026-10-06T09:36:52.655368241Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=bus.EVENTS.novox_messenger.missing", + "show": "mesh-controller.conditions key=bus.EVENTS.node-c_messenger.missing", "silenced": null, "source": "D6", "subject": { - "id": "EVENTS.novox_messenger", + "id": "EVENTS.node-c_messenger", "scope": "bus" }, - "summary": "how messenger on novox hears what it consumes (novox_messenger on EVENTS) is not on the bus: what it delivers reaches nobody" + "summary": "how messenger on node-c hears what it consumes (node-c_messenger on EVENTS) is not on the bus: what it delivers reaches nobody" }, { "at": "2026-10-06T09:48:20.402344535Z", @@ -2267,10 +2267,10 @@ "source": "S9", "subject": { "id": "controller", - "machine": "novox", + "machine": "node-c", "scope": "bus" }, - "summary": "the bus refused the controller: nats: permissions violation: Permissions Violation for Publish to \"mesh.seat.node-intrusion-prevention.tool.banned.g14\" (4 times since 08:51 UTC)", + "summary": "the bus refused the controller: nats: permissions violation: Permissions Violation for Publish to \"mesh.seat.node-intrusion-prevention.tool.banned.node-b\" (4 times since 08:51 UTC)", "why": "S9 no longer observes it" }, { @@ -2280,21 +2280,21 @@ "count": 1, "epoch": 0, "event": "condition-cleared", - "key": "bus.EVENTS.novox_messenger.missing", + "key": "bus.EVENTS.node-c_messenger.missing", "kind": "consumer-lost", "last-observed": "2026-10-06T09:46:48.513702228Z", "observations": 4, "raised": "2026-10-06T09:36:52.655368241Z", "resolver": "self", "severity": "warning", - "show": "mesh-controller.conditions key=bus.EVENTS.novox_messenger.missing", + "show": "mesh-controller.conditions key=bus.EVENTS.node-c_messenger.missing", "silenced": null, "source": "D6", "subject": { - "id": "EVENTS.novox_messenger", + "id": "EVENTS.node-c_messenger", "scope": "bus" }, - "summary": "how messenger on novox hears what it consumes (novox_messenger on EVENTS) is not on the bus: what it delivers reaches nobody", + "summary": "how messenger on node-c hears what it consumes (node-c_messenger on EVENTS) is not on the bus: what it delivers reaches nobody", "why": "D6 no longer observes it" } ] diff --git a/modules/messenger/cmd/messenger/tracking_test.go b/modules/messenger/cmd/messenger/tracking_test.go index fbf719c3..0a546f69 100644 --- a/modules/messenger/cmd/messenger/tracking_test.go +++ b/modules/messenger/cmd/messenger/tracking_test.go @@ -44,15 +44,15 @@ func TestAConditionsMessageSaysWhereTheIssueThatTracksItStands(t *testing.T) { "Whether an issue tracks this could not be checked.", "Nothing for you to do."}, {"nobody works on it", []TrackedIssue{{Number: 352, Status: "located"}}, true, "Tracked as issue 352: nobody is working on it.", "A person repaired"}, - {"an agent is fixing it", []TrackedIssue{{Number: 386, Status: "fixing", Worker: "fix-386@g14", Since: at(21, 10)}}, true, - "Tracked as issue 386: fix-386 on g14 is fixing it since 21:10.", "Nothing for you to do."}, - {"an agent looks for its cause", []TrackedIssue{{Number: 386, Status: "diagnosing", Worker: "jochen@shanks", Since: at(18, 5)}}, true, - "Tracked as issue 386: jochen on shanks is looking for its cause since 18:05.", "Nothing for you to do."}, - {"its worker went quiet", []TrackedIssue{{Number: 386, Status: "fixing", Worker: "fix-386@g14", Since: at(9, 0), Active: at(9, 30), Stale: true}}, true, + {"an agent is fixing it", []TrackedIssue{{Number: 386, Status: "fixing", Worker: "fix-386@node-b", Since: at(21, 10)}}, true, + "Tracked as issue 386: fix-386 on node-b is fixing it since 21:10.", "Nothing for you to do."}, + {"an agent looks for its cause", []TrackedIssue{{Number: 386, Status: "diagnosing", Worker: "jochen@node-d", Since: at(18, 5)}}, true, + "Tracked as issue 386: jochen on node-d is looking for its cause since 18:05.", "Nothing for you to do."}, + {"its worker went quiet", []TrackedIssue{{Number: 386, Status: "fixing", Worker: "fix-386@node-b", Since: at(9, 0), Active: at(9, 30), Stale: true}}, true, "Tracked as issue 386: nobody has worked on it since 09:30.", "A person repaired"}, {"a fix waits to be merged", []TrackedIssue{{Number: 386, Status: "located", Fix: "not-merged"}}, true, "Tracked as issue 386: a fix is written and waits to be merged.", "Nothing for you to do."}, - {"its fix is on its way", []TrackedIssue{{Number: 386, Status: "fixing", Worker: "fix-386@g14", Since: at(9, 0), Fix: "merged"}}, true, + {"its fix is on its way", []TrackedIssue{{Number: 386, Status: "fixing", Worker: "fix-386@node-b", Since: at(9, 0), Fix: "merged"}}, true, "Tracked as issue 386: its fix is merged and on its way.", "Nothing for you to do."}, {"the delivery was not heard yet", []TrackedIssue{{Number: 386, Status: "fixing", Fix: "unheard"}}, true, "Tracked as issue 386: a fix is named, and nothing is heard yet of its delivery.", "Nothing for you to do."}, @@ -69,23 +69,23 @@ func TestAConditionsMessageSaysWhereTheIssueThatTracksItStands(t *testing.T) { {"one not fixed after one open", []TrackedIssue{{Number: 100, Status: "wontfix"}, {Number: 200, Status: "open"}}, true, "Tracked as issue 200: nobody is working on it. Also as issue 100: it will not be fixed.", "A person repaired"}, {"its worker went quiet on one that waits for a decision", []TrackedIssue{{Number: 400, Status: "fixing", Needs: "decision", - Worker: "fix-400@g14", Since: at(9, 0), Active: at(9, 30), Stale: true}}, true, + Worker: "fix-400@node-b", Since: at(9, 0), Active: at(9, 30), Stale: true}}, true, "Tracked as issue 400: nobody has worked on it since 09:30.", "A person repaired"}, {"it waits for the operator", []TrackedIssue{{Number: 336, Status: "open", Needs: "operator"}}, true, "Tracked as issue 336: it waits for your answer.", "Needs you: answer issue 336. A person repaired"}, {"it waits for a decision", []TrackedIssue{{Number: 400, Status: "open", Needs: "decision"}}, true, "Tracked as issue 400: nobody is working on it; it waits for a decision first.", "A person repaired"}, {"two issues, one worked on", []TrackedIssue{ - {Number: 386, Status: "fixing", Worker: "fix-386@g14", Since: at(21, 10)}, + {Number: 386, Status: "fixing", Worker: "fix-386@node-b", Since: at(21, 10)}, {Number: 379, Status: "located"}}, true, - "Tracked as issue 379: nobody is working on it. Also as issue 386: fix-386 on g14 is fixing it since 21:10.", + "Tracked as issue 379: nobody is working on it. Also as issue 386: fix-386 on node-b is fixing it since 21:10.", "Nothing for you to do."}, {"two issues, nobody on either", []TrackedIssue{{Number: 386, Status: "open"}, {Number: 379, Status: "located"}}, true, "Tracked as issue 379: nobody is working on it. Also as issue 386: nobody is working on it.", "A person repaired"}, {"one of two waits for the operator", []TrackedIssue{ - {Number: 386, Status: "fixing", Worker: "fix-386@g14", Since: at(21, 10)}, + {Number: 386, Status: "fixing", Worker: "fix-386@node-b", Since: at(21, 10)}, {Number: 379, Status: "open", Needs: "operator"}}, true, - "Tracked as issue 379: it waits for your answer. Also as issue 386: fix-386 on g14 is fixing it since 21:10.", + "Tracked as issue 379: it waits for your answer. Also as issue 386: fix-386 on node-b is fixing it since 21:10.", "Needs you: answer issue 379."}, {"more than three", []TrackedIssue{{Number: 1, Status: "open"}, {Number: 2, Status: "open"}, {Number: 3, Status: "open"}, {Number: 4, Status: "open"}, {Number: 5, Status: "resolved"}}, true, @@ -116,9 +116,9 @@ func TestAConditionsMessageSaysWhereTheIssueThatTracksItStands(t *testing.T) { func TestNothingForYouToDoIsNeverSaidWhileTheIssueWaitsOnTheOperatorOrNobodyWorksOnIt(t *testing.T) { for _, issues := range [][]TrackedIssue{ {{Number: 336, Status: "open", Needs: "operator"}}, - {{Number: 336, Status: "fixing", Worker: "fix-336@g14", Since: at(9, 0), Needs: "operator"}}, + {{Number: 336, Status: "fixing", Worker: "fix-336@node-b", Since: at(9, 0), Needs: "operator"}}, {{Number: 352, Status: "located"}}, - {{Number: 352, Status: "fixing", Worker: "fix-352@g14", Since: at(9, 0), Stale: true}}, + {{Number: 352, Status: "fixing", Worker: "fix-352@node-b", Since: at(9, 0), Stale: true}}, } { if m := trackedMessage(issues, true); strings.Contains(m.Body, "Nothing for you to do") { t.Errorf("%+v: %q", issues, m.Body) @@ -128,11 +128,11 @@ func TestNothingForYouToDoIsNeverSaidWhileTheIssueWaitsOnTheOperatorOrNobodyWork // A verdict that already needs the operator is left as it is; the line is added below it. func TestAVerdictThatNeedsTheOperatorStands(t *testing.T) { - r := &Record{Key: "module.mounts.shanks.unhealthy", Origin: "condition", Severity: Urgent, Headline: "mounts not working on shanks", - Explanation: "Needs you: give the share's login. mounts on shanks is not healthy.", Raised: trackNow.Add(-time.Hour)} + r := &Record{Key: "module.mounts.node-d.unhealthy", Origin: "condition", Severity: Urgent, Headline: "mounts not working on node-d", + Explanation: "Needs you: give the share's login. mounts on node-d is not healthy.", Raised: trackNow.Add(-time.Hour)} m, _ := withTracking(compose(r, "raised", trackNow, time.UTC, 0), r, "raised", []TrackedIssue{{Number: 386, Status: "open", Needs: "operator"}}, true, trackNow, time.UTC) - want := "Needs you: give the share's login. mounts on shanks is not healthy.\nTracked as issue 386: it waits for your answer.\nSince 18:30." + want := "Needs you: give the share's login. mounts on node-d is not healthy.\nTracked as issue 386: it waits for your answer.\nSince 18:30." if m.Body != want { t.Fatalf("got %q\nwant %q", m.Body, want) } @@ -173,12 +173,12 @@ func TestTheRouterAsksTheTrackerAndSaysItsWordInTheMessage(t *testing.T) { if fail { return nil, errors.New("no responders") } - return json.RawMessage(`{"conditions":{"module.mounts.shanks.unhealthy":[` + + return json.RawMessage(`{"conditions":{"module.mounts.node-d.unhealthy":[` + `{"number":379,"status":"located"},` + - `{"number":386,"status":"fixing","worker":"fix-386@g14","since":"2026-10-06T11:10:00Z"}]}}`), nil + `{"number":386,"status":"fixing","worker":"fix-386@node-b","since":"2026-10-06T11:10:00Z"}]}}`), nil } - k := cond("module.mounts.shanks.unhealthy", Urgent, "mounts on shanks is not healthy") - k.Explanation, k.Needs = "Nothing for you to do. mounts on shanks is not healthy.", "" + k := cond("module.mounts.node-d.unhealthy", Urgent, "mounts on node-d is not healthy") + k.Explanation, k.Needs = "Nothing for you to do. mounts on node-d is not healthy.", "" k.Raised = c.now() h.Condition(EventRaised, k) settle(h, c) @@ -186,7 +186,7 @@ func TestTheRouterAsksTheTrackerAndSaysItsWordInTheMessage(t *testing.T) { t.Fatalf("urgent: telegram %d, desktop %d", len(tg.sends), len(dt.sends)) } body := tg.sends[0].Body - if !strings.Contains(body, "\nTracked as issue 379: nobody is working on it. Also as issue 386: fix-386 on g14 is fixing it since 11:10.\n") { + if !strings.Contains(body, "\nTracked as issue 379: nobody is working on it. Also as issue 386: fix-386 on node-b is fixing it since 11:10.\n") { t.Fatalf("body: %q", body) } if asked != 1 { @@ -199,7 +199,7 @@ func TestTheRouterAsksTheTrackerAndSaysItsWordInTheMessage(t *testing.T) { c.pass(TrackingKept + time.Minute) h.Tick() h.mu.Lock() - r := h.open["module.mounts.shanks.unhealthy"] + r := h.open["module.mounts.node-d.unhealthy"] h.mu.Unlock() if m := h.say(r, "reminder"); !strings.Contains(m.Body, "\nWhether an issue tracks this could not be checked.\n") { t.Fatalf("an old word was used: %q", m.Body) @@ -213,11 +213,11 @@ func TestTheRouterAsksTheTrackerAndSaysItsWordInTheMessage(t *testing.T) { // built without it. func TestARouterThatCannotAskAddsNothing(t *testing.T) { h, _, _, c, _ := newHolder(t) - k := cond("machine.ace.silent", Urgent, "ace is silent") + k := cond("machine.node-a.silent", Urgent, "node-a is silent") k.Raised = c.now() h.Condition(EventRaised, k) h.mu.Lock() - r := h.open["machine.ace.silent"] + r := h.open["machine.node-a.silent"] h.mu.Unlock() if m := h.say(r, "raised"); strings.Contains(m.Body, "issue") { t.Fatalf("%q", m.Body) diff --git a/modules/messenger/cmd/messenger/walks_test.go b/modules/messenger/cmd/messenger/walks_test.go index 84fd2e33..3957b3d4 100644 --- a/modules/messenger/cmd/messenger/walks_test.go +++ b/modules/messenger/cmd/messenger/walks_test.go @@ -44,7 +44,7 @@ func walk(t *testing.T, h *Holder, id, phase, outcome string, at time.Time, boun h.Walked(ev) } -func novox(modules ...string) Touch { return Touch{Machine: "novox", Modules: modules} } +func nodeC(modules ...string) Touch { return Touch{Machine: "node-c", Modules: modules} } // heard says whether any message on the channels carries the words: sent, edited or said again in place. func heard(words string, chs ...*fakeChannel) bool { @@ -94,11 +94,11 @@ func has(list []string, want string) bool { // history says it was held — a module's condition, a machine's, and a module's notice alike. func TestDuringAWalkWhatItTouchesIsHeldAndTheHistorySaysSo(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - walk(t, h, "plan-1", WalkStarted, "", c.now(), 600, novox("mesh-tools", "node-tools")) - mod := cond("module.node-tools.novox.unhealthy", Urgent, "the tool runner on novox does not answer") - mod.Machine, mod.Raised = "novox", c.now() + walk(t, h, "plan-1", WalkStarted, "", c.now(), 600, nodeC("mesh-tools", "node-tools")) + mod := cond("module.node-tools.node-c.unhealthy", Urgent, "the tool runner on node-c does not answer") + mod.Machine, mod.Raised = "node-c", c.now() h.Condition(EventRaised, mod) - machine := cond("machine.novox.claude-code.agent-home.data-shrank", Urgent, "the agent's home shrank") + machine := cond("machine.node-c.claude-code.agent-home.data-shrank", Urgent, "the agent's home shrank") machine.Raised = c.now() h.Condition(EventRaised, machine) if _, err := h.Notify("tools.slow", Urgent, "tools answer slowly", "node-tools", false, "tools slow", @@ -123,24 +123,24 @@ func TestDuringAWalkWhatItTouchesIsHeldAndTheHistorySaysSo(t *testing.T) { // nothing of it. func TestAMessageTouchedByTwoOverlappingWalksIsHeldUntilTheSecondEnds(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - walk(t, h, "plan-a", WalkStarted, "", c.now(), 1200, novox("mesh-tools")) + walk(t, h, "plan-a", WalkStarted, "", c.now(), 1200, nodeC("mesh-tools")) c.pass(time.Minute) - walk(t, h, "plan-b", WalkStarted, "", c.now(), 1200, novox("node-tools"), Touch{Machine: "ace", Modules: []string{"node-tools"}}) - k := cond("machine.novox.network", Urgent, "novox lost its default route") + walk(t, h, "plan-b", WalkStarted, "", c.now(), 1200, nodeC("node-tools"), Touch{Machine: "node-a", Modules: []string{"node-tools"}}) + k := cond("machine.node-c.network", Urgent, "node-c lost its default route") k.Raised = c.now() h.Condition(EventRaised, k) runFor(h, c, time.Minute) - walk(t, h, "plan-a", WalkEnded, WalkDelivered, c.now(), 0, novox("mesh-tools")) + walk(t, h, "plan-a", WalkEnded, WalkDelivered, c.now(), 0, nodeC("mesh-tools")) runFor(h, c, DefaultSettle+time.Minute) // its end is told once it settled (ADR 0505 §3) if heard(headlineOf(k.Key), tg, dt) { t.Fatalf("said at the first walk's end, while the second still holds it: %+v %+v", tg.sends, dt.sends) } - if !heard("Delivered: mesh-tools on novox", tg, dt) { + if !heard("Delivered: mesh-tools on node-c", tg, dt) { t.Fatalf("the first walk's end was not told: %+v", dt.sends) } walk(t, h, "plan-b", WalkEnded, WalkDelivered, c.now(), 0) runFor(h, c, DefaultSettle+time.Minute) - if !heard("Still open after the delivery of node-tools to ace, novox:\n- Urgent: "+headlineOf(k.Key), tg, dt) { + if !heard("Still open after the delivery of node-tools to node-a, node-c:\n- Urgent: "+headlineOf(k.Key), tg, dt) { t.Fatalf("the second walk's end did not tell it: telegram %+v, desk %+v", tg.sends, dt.sends) } } @@ -149,18 +149,18 @@ func TestAMessageTouchedByTwoOverlappingWalksIsHeldUntilTheSecondEnds(t *testing // sent at once, while a walk touches the machine they are on. func TestWhatAWalkNeverHoldsIsSentAtOnce(t *testing.T) { h, tg, dt, c, _, _ := newRouter(t) - walk(t, h, "plan-9", WalkStarted, "", c.now(), 1200, novox("telegram", "mesh-tools")) + walk(t, h, "plan-9", WalkStarted, "", c.now(), 1200, nodeC("telegram", "mesh-tools")) for _, key := range []string{ - "machine.novox.telegram.telegram-token.secret-given", // a secret given, on a touched machine - "machine.novox.mounts.smb.secret-replaced", // a secret replaced - "machine.ace.silent", // a machine no walk touches - "delivery.leaf.over-budget", // the walk's own delivery - "plan.plan-9.failed", // the walk itself + "machine.node-c.telegram.telegram-token.secret-given", // a secret given, on a touched machine + "machine.node-c.mounts.smb.secret-replaced", // a secret replaced + "machine.node-a.silent", // a machine no walk touches + "delivery.leaf.over-budget", // the walk's own delivery + "plan.plan-9.failed", // the walk itself } { k := cond(key, Urgent, "it happened") k.Raised = c.now() if !strings.HasPrefix(key, "machine.") { - k.Machine = "novox" // a walk's own failure, on a machine it touches + k.Machine = "node-c" // a walk's own failure, on a machine it touches } h.Condition(EventRaised, k) runFor(h, c, time.Minute) @@ -175,7 +175,7 @@ func TestWhatAWalkNeverHoldsIsSentAtOnce(t *testing.T) { if !has(outcomes(h, "ask."+ConditionOwner+".own"), "sent") { t.Errorf("an ask waiting for the operator was held: %v", outcomes(h, "ask."+ConditionOwner+".own")) } - held := cond("machine.novox.units", Urgent, "2 failed services on novox") + held := cond("machine.node-c.units", Urgent, "2 failed services on node-c") held.Raised = c.now() h.Condition(EventRaised, held) runFor(h, c, time.Minute) @@ -195,15 +195,15 @@ func TestWhatAWalkNeverHoldsIsSentAtOnce(t *testing.T) { // still open, one line each; the one that cleared is only counted, and nothing more is said of them after. func TestAWalksEndIsToldOnceWithWhatIsStillOpen(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - walk(t, h, "plan-3", WalkStarted, "", c.now(), 600, novox("mesh-tools")) - still := cond("machine.novox.tools-silent", Warning, "the tools on novox are silent") + walk(t, h, "plan-3", WalkStarted, "", c.now(), 600, nodeC("mesh-tools")) + still := cond("machine.node-c.tools-silent", Warning, "the tools on node-c are silent") still.Raised = c.now() h.Condition(EventRaised, still) - gone := cond("module.mesh-tools.novox.unhealthy", Warning, "mesh-tools is unhealthy on novox") + gone := cond("module.mesh-tools.node-c.unhealthy", Warning, "mesh-tools is unhealthy on node-c") gone.Raised = c.now() h.Condition(EventRaised, gone) c.pass(time.Second) - other := cond("machine.novox.core-behind", Urgent, "novox runs an older core") + other := cond("machine.node-c.core-behind", Urgent, "node-c runs an older core") other.Raised = c.now() h.Condition(EventRaised, other) runFor(h, c, 2*time.Minute) @@ -219,10 +219,10 @@ func TestAWalksEndIsToldOnceWithWhatIsStillOpen(t *testing.T) { t.Fatalf("the end was not one message per kind: desk %+v, telegram %+v", dt.sends, tg.sends) } m := dt.sends[0] - if m.Title != "Delivery failed: mesh-tools on novox" || !strings.Contains(m.Body, "It took 7 min.") { + if m.Title != "Delivery failed: mesh-tools on node-c" || !strings.Contains(m.Body, "It took 7 min.") { t.Fatalf("the end does not say its outcome, what it reached and how long: %q", m.Text()) } - want := "Still open after the delivery of mesh-tools to novox:\n- " + headlineOf(still.Key) + "\n- Urgent: " + headlineOf(other.Key) + + want := "Still open after the delivery of mesh-tools to node-c:\n- " + headlineOf(still.Key) + "\n- Urgent: " + headlineOf(other.Key) + "\n1 problem it raised resolved during it." if !strings.Contains(m.Body, want) || strings.Contains(m.Text(), headlineOf(gone.Key)) { t.Fatalf("the end message %q does not say %q", m.Body, want) @@ -238,18 +238,18 @@ func TestAWalksEndIsToldOnceWithWhatIsStillOpen(t *testing.T) { // to say only what needs the operator. func TestADeliveredWalkWithNothingHeldIsOneLineOrNothing(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - walk(t, h, "plan-4", WalkStarted, "", c.now(), 600, novox("mesh-tools"), Touch{Machine: "ace", Modules: []string{"mesh-tools"}}) + walk(t, h, "plan-4", WalkStarted, "", c.now(), 600, nodeC("mesh-tools"), Touch{Machine: "node-a", Modules: []string{"mesh-tools"}}) runFor(h, c, 3*time.Minute) walk(t, h, "plan-4", WalkEnded, WalkDelivered, c.now(), 0) runFor(h, c, DefaultSettle+time.Minute) if len(dt.sends) != 1 || len(tg.sends) != 0 { t.Fatalf("desk %+v, telegram %+v", dt.sends, tg.sends) } - if m := dt.sends[0]; m.Title != "Delivered: mesh-tools on ace, novox, in 3 min" || m.Body != "" { + if m := dt.sends[0]; m.Title != "Delivered: mesh-tools on node-a, node-c, in 3 min" || m.Body != "" { t.Fatalf("not one line: %q", m.Text()) } h.NeedsOnly = func(kind string) bool { return kind == "desktop" } - walk(t, h, "plan-5", WalkStarted, "", c.now(), 600, novox("mesh-tools")) + walk(t, h, "plan-5", WalkStarted, "", c.now(), 600, nodeC("mesh-tools")) runFor(h, c, 3*time.Minute) walk(t, h, "plan-5", WalkEnded, WalkDelivered, c.now(), 0) runFor(h, c, DefaultSettle+time.Minute) @@ -279,11 +279,11 @@ func TestAHoldEndsAtTheWalksBound(t *testing.T) { t.Run(tc.name, func(t *testing.T) { h, tg, dt, c, _ := newHolder(t) started := c.now() - walk(t, h, "plan-7", WalkStarted, "", started, tc.given, novox("node-tools")) - open := cond("machine.novox.tools-silent", Urgent, "the tools on novox are silent") + walk(t, h, "plan-7", WalkStarted, "", started, tc.given, nodeC("node-tools")) + open := cond("machine.node-c.tools-silent", Urgent, "the tools on node-c are silent") open.Raised = c.now() h.Condition(EventRaised, open) - gone := cond("module.node-tools.novox.unhealthy", Urgent, "node-tools is unhealthy") + gone := cond("module.node-tools.node-c.unhealthy", Urgent, "node-tools is unhealthy") gone.Raised = c.now() h.Condition(EventRaised, gone) c.pass(30 * time.Second) @@ -305,7 +305,7 @@ func TestAHoldEndsAtTheWalksBound(t *testing.T) { } } // Past its bound the walk holds nothing: a new message about what it touches goes at once. - late := cond("machine.novox.disk", Urgent, "a disk fails on novox") + late := cond("machine.node-c.disk", Urgent, "a disk fails on node-c") late.Raised = c.now() h.Condition(EventRaised, late) runFor(h, c, time.Minute) @@ -319,8 +319,8 @@ func TestAHoldEndsAtTheWalksBound(t *testing.T) { // §2, kept: what a walk holds survives the router's restart, and is told at the walk's end. func TestHeldMessagesSurviveARouterRestart(t *testing.T) { h, tg, dt, c, st := newHolder(t) - walk(t, h, "plan-8", WalkStarted, "", c.now(), 1200, novox("mesh-tools")) - k := cond("machine.novox.tools-silent", Urgent, "the tools on novox are silent") + walk(t, h, "plan-8", WalkStarted, "", c.now(), 1200, nodeC("mesh-tools")) + k := cond("machine.node-c.tools-silent", Urgent, "the tools on node-c are silent") k.Raised = c.now() h.Condition(EventRaised, k) runFor(h, c, time.Minute) @@ -345,8 +345,8 @@ func TestARestartSaysNothingItHasSaid(t *testing.T) { h, tg, dt, c, _, _ := newRouter(t) h.Start() c.pass(2 * time.Minute) - keys := []string{"machine.novox.telegram.telegram-token.secret-given", "machine.novox.claude-code.agent-home.data-shrank", - "machine.shanks.mounts.smb-password-recalbox.secret-given", "machine.ace.nzbgeek.api-key.secret-given"} + keys := []string{"machine.node-c.telegram.telegram-token.secret-given", "machine.node-c.claude-code.agent-home.data-shrank", + "machine.node-d.mounts.smb-password-recalbox.secret-given", "machine.node-a.nzbgeek.api-key.secret-given"} var silenced []Condition for i, key := range keys { k := cond(key, Urgent, "it happened") @@ -359,7 +359,7 @@ func TestARestartSaysNothingItHasSaid(t *testing.T) { stand(h, c) silenced = append(silenced, k) } - withheldOpen := cond("machine.novox.units", Urgent, "2 failed services") + withheldOpen := cond("machine.node-c.units", Urgent, "2 failed services") withheldOpen.Explanation = "Needs you: read /etc/systemd/system/x.service." withheldOpen.Raised = c.now() h.Condition(EventRaised, withheldOpen) @@ -415,14 +415,14 @@ func TestARestartSaysNothingItHasSaid(t *testing.T) { // The controller's walk events are read as ADR 0308 §1 says them; any other plan-moved is not a walk's. func TestTheWalkEventsAreReadAsTheControllerSaysThem(t *testing.T) { at := time.Date(2026, 10, 12, 11, 12, 0, 0, time.UTC) - ev, ok, err := DecodeWalk(walkBody(t, "plan-1", WalkStarted, "", at, 1200, novox("mesh-tools", "node-tools"))) + ev, ok, err := DecodeWalk(walkBody(t, "plan-1", WalkStarted, "", at, 1200, nodeC("mesh-tools", "node-tools"))) if err != nil || !ok || ev.Walk != "plan-1" || ev.BoundSeconds != 1200 || ev.Class != "leaf" || !ev.At.Equal(at) || - len(ev.Touches) != 1 || ev.Touches[0].Machine != "novox" || len(ev.Touches[0].Modules) != 2 { + len(ev.Touches) != 1 || ev.Touches[0].Machine != "node-c" || len(ev.Touches[0].Modules) != 2 { t.Fatalf("%+v %v %v", ev, ok, err) } // As mesh-controller's walk events (its pull request 247) say an end: ended_at, and carried beside modules. end, ok, err := DecodeWalk([]byte(`{"id":"plan-1","walk":"plan-1","phase":"ended","outcome":"stopped",` + - `"touches":[{"machine":"novox","modules":["node-tools","messenger"],"carried":["messenger"]}],` + + `"touches":[{"machine":"node-c","modules":["node-tools","messenger"],"carried":["messenger"]}],` + `"started_at":"2026-10-12T11:12:00Z","ended_at":"2026-10-12T11:19:00Z","updated":"2026-10-12T11:19:01Z"}`)) if err != nil || !ok || end.Outcome != WalkStopped || !end.At.Equal(at.Add(7*time.Minute)) || len(end.Touches[0].Modules) != 2 { t.Fatalf("%+v %v %v", end, ok, err) @@ -439,7 +439,7 @@ func TestTheWalkEventsAreReadAsTheControllerSaysThem(t *testing.T) { } // A start older than its bound is history: nothing is held. h, _, _, c, _ := newHolder(t) - walk(t, h, "plan-old", WalkStarted, "", c.now().Add(-time.Hour), 1200, novox("mesh-tools")) + walk(t, h, "plan-old", WalkStarted, "", c.now().Add(-time.Hour), 1200, nodeC("mesh-tools")) if len(h.walks) != 0 { t.Fatalf("an old start opened a walk: %+v", h.walks) } @@ -452,8 +452,8 @@ func TestWhatAWalkHeldIsSaidOnceAChannelCanSendAgain(t *testing.T) { for _, at := range []string{"end", "bound"} { t.Run(at, func(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - walk(t, h, "plan-c", WalkStarted, "", c.now(), 600, novox("mesh-tools")) - k := cond("machine.novox.tools-silent", Urgent, "the tools on novox are silent") + walk(t, h, "plan-c", WalkStarted, "", c.now(), 600, nodeC("mesh-tools")) + k := cond("machine.node-c.tools-silent", Urgent, "the tools on node-c are silent") k.Raised = c.now() h.Condition(EventRaised, k) runFor(h, c, 2*time.Minute) @@ -485,12 +485,12 @@ func TestWhatAWalkHeldIsSaidOnceAChannelCanSendAgain(t *testing.T) { // limit (its start, bound and settle) has passed, while B still runs, with B's delivery line. func TestAMessageIsHeldOnByALaterWalkThatTouchesIt(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - walk(t, h, "plan-a", WalkStarted, "", c.now(), 360, novox("mesh-tools")) // its limit: 6 min and the settle - k := cond("machine.novox.network", Urgent, "novox lost its default route") + walk(t, h, "plan-a", WalkStarted, "", c.now(), 360, nodeC("mesh-tools")) // its limit: 6 min and the settle + k := cond("machine.node-c.network", Urgent, "node-c lost its default route") k.Raised = c.now() h.Condition(EventRaised, k) runFor(h, c, time.Minute) - walk(t, h, "plan-b", WalkStarted, "", c.now(), 1200, novox("node-tools")) + walk(t, h, "plan-b", WalkStarted, "", c.now(), 1200, nodeC("node-tools")) runFor(h, c, time.Minute) walk(t, h, "plan-a", WalkEnded, WalkDelivered, c.now(), 0) runFor(h, c, DefaultSettle+time.Minute) @@ -501,7 +501,7 @@ func TestAMessageIsHeldOnByALaterWalkThatTouchesIt(t *testing.T) { t.Fatalf("the second walk does not hold it on: %v", got) } runFor(h, c, 4*time.Minute) // past the first walk's limit, 8 minutes after it was held - if !heard("During the delivery of node-tools to novox.", tg, dt) || !heard(headlineOf(k.Key), tg, dt) { + if !heard("During the delivery of node-tools to node-c.", tg, dt) || !heard(headlineOf(k.Key), tg, dt) { t.Fatalf("held past its first hold's limit: %+v %+v", tg.sends, dt.sends) } } @@ -510,8 +510,8 @@ func TestAMessageIsHeldOnByALaterWalkThatTouchesIt(t *testing.T) { // what it held is said, with the still-running line, before the walk is forgotten. func TestAWalkReadBackADayLateSaysWhatItHeldBeforeItIsForgotten(t *testing.T) { h, tg, dt, c, st := newHolder(t) - walk(t, h, "plan-d", WalkStarted, "", c.now(), 600, novox("mesh-tools")) - k := cond("machine.novox.tools-silent", Urgent, "the tools on novox are silent") + walk(t, h, "plan-d", WalkStarted, "", c.now(), 600, nodeC("mesh-tools")) + k := cond("machine.node-c.tools-silent", Urgent, "the tools on node-c are silent") k.Raised = c.now() h.Condition(EventRaised, k) runFor(h, c, time.Minute) @@ -540,14 +540,14 @@ func TestAStartHeardAfterItsEndOpensNothing(t *testing.T) { h, tg, dt, c, st := newHolder(t) started := c.now() c.pass(20 * time.Second) - end, _, err := DecodeWalk([]byte(`{"walk":"plan-e","phase":"ended","outcome":"delivered","touches":[{"machine":"novox","modules":["mesh-tools"]}],` + + end, _, err := DecodeWalk([]byte(`{"walk":"plan-e","phase":"ended","outcome":"delivered","touches":[{"machine":"node-c","modules":["mesh-tools"]}],` + `"started_at":"` + started.Format(time.RFC3339Nano) + `","ended_at":"` + c.now().Format(time.RFC3339Nano) + `"}`)) if err != nil { t.Fatal(err) } h.Walked(end) c.pass(time.Second) - walk(t, h, "plan-e", WalkStarted, "", started, 600, novox("mesh-tools")) + walk(t, h, "plan-e", WalkStarted, "", started, 600, nodeC("mesh-tools")) if len(h.walks) != 0 { t.Fatalf("a start heard after its end opened a walk: %+v", h.walks) } @@ -556,11 +556,11 @@ func TestAStartHeardAfterItsEndOpensNothing(t *testing.T) { t.Fatal(err) } again.Start() - walk(t, again, "plan-e", WalkStarted, "", started, 600, novox("mesh-tools")) + walk(t, again, "plan-e", WalkStarted, "", started, 600, nodeC("mesh-tools")) if len(again.walks) != 0 { t.Fatalf("after a restart, a start heard after its end opened a walk: %+v", again.walks) } - k := cond("machine.novox.tools-silent", Urgent, "the tools on novox are silent") + k := cond("machine.node-c.tools-silent", Urgent, "the tools on node-c are silent") k.Raised = c.now() again.Condition(EventRaised, k) runFor(again, c, time.Minute) @@ -568,7 +568,7 @@ func TestAStartHeardAfterItsEndOpensNothing(t *testing.T) { t.Fatalf("held by a walk that had ended: %v", outcomes(again, k.Key)) } // Retried: the same id walks again, started after the end. - walk(t, again, "plan-e", WalkStarted, "", c.now(), 600, novox("mesh-tools")) + walk(t, again, "plan-e", WalkStarted, "", c.now(), 600, nodeC("mesh-tools")) if len(again.walks) != 1 { t.Fatalf("a walk started after the last end did not open: %+v", again.walks) } @@ -581,8 +581,8 @@ func TestARestartSaysAgainAnAskedMessageAWalkTookBeforeItsAsk(t *testing.T) { h, _, dt, c, _, _ := newRouter(t) h.Start() stand(h, c) - walk(t, h, "plan-f", WalkStarted, "", c.now(), 1200, novox("mesh-tools")) - k := cond("machine.novox.units", Urgent, "2 failed services on novox") + walk(t, h, "plan-f", WalkStarted, "", c.now(), 1200, nodeC("mesh-tools")) + k := cond("machine.node-c.units", Urgent, "2 failed services on node-c") k.Raised = c.now() h.Condition(EventRaised, k) runFor(h, c, time.Minute) @@ -607,8 +607,8 @@ func TestARestartSaysAgainAnAskedMessageAWalkTookBeforeItsAsk(t *testing.T) { // file path) is said in its plain form, and what it held, still open, is said on its own, not marked told. func TestWhatAWalksPlainEndCannotCarryIsSaidOnItsOwn(t *testing.T) { h, tg, dt, c, _ := newHolder(t) - walk(t, h, "plan-g", WalkStarted, "", c.now(), 600, novox("/var/lib/mesh-tools")) - k := cond("machine.novox.tools-silent", Urgent, "the tools on novox are silent") + walk(t, h, "plan-g", WalkStarted, "", c.now(), 600, nodeC("/var/lib/mesh-tools")) + k := cond("machine.node-c.tools-silent", Urgent, "the tools on node-c are silent") k.Raised = c.now() h.Condition(EventRaised, k) runFor(h, c, time.Minute) @@ -634,8 +634,8 @@ func TestAHeldMessageIsToldOnlyOnceTheWalksMessageWasSent(t *testing.T) { if then == "restart warning" { sev = Warning } - walk(t, h, "plan-h", WalkStarted, "", c.now(), 1200, novox("mesh-tools")) - k := cond("machine.novox.tools-silent", sev, "the tools on novox are silent") + walk(t, h, "plan-h", WalkStarted, "", c.now(), 1200, nodeC("mesh-tools")) + k := cond("machine.node-c.tools-silent", sev, "the tools on node-c are silent") k.Raised = c.now() h.Condition(EventRaised, k) runFor(h, c, time.Minute) @@ -652,7 +652,7 @@ func TestAHeldMessageIsToldOnlyOnceTheWalksMessageWasSent(t *testing.T) { tg.fail, dt.fail = nil, nil if then == "sent" { runFor(h, c, 2*time.Minute) - if !heard("Still open after the delivery of mesh-tools to novox:\n- Urgent: "+headlineOf(k.Key), tg, dt) || saidOn(tg, dt) != 2 { + if !heard("Still open after the delivery of mesh-tools to node-c:\n- Urgent: "+headlineOf(k.Key), tg, dt) || saidOn(tg, dt) != 2 { t.Fatalf("not told once in the walk's message: telegram %+v, desk %+v", tg.sends, dt.sends) } if r := h.open[k.Key]; r == nil || !r.told() || r.Owed != "" || r.Sent["telegram"] != "" || r.Sent["desktop"] != "" { @@ -694,11 +694,11 @@ func TestAWalksEndHandsOnOnlyWhatALaterWalkWouldHold(t *testing.T) { h, tg, dt, c, _, _ := newRouter(t) h.Start() stand(h, c) - walk(t, h, "plan-a", WalkStarted, "", c.now(), 1200, novox("mesh-tools")) - quiet := cond("machine.novox.network", Urgent, "novox lost its default route") + walk(t, h, "plan-a", WalkStarted, "", c.now(), 1200, nodeC("mesh-tools")) + quiet := cond("machine.node-c.network", Urgent, "node-c lost its default route") quiet.Raised = c.now() h.Condition(EventRaised, quiet) - asked := cond("machine.novox.units", Urgent, "2 failed services on novox") + asked := cond("machine.node-c.units", Urgent, "2 failed services on node-c") asked.Raised = c.now() h.Condition(EventRaised, asked) runFor(h, c, time.Minute) @@ -713,7 +713,7 @@ func TestAWalksEndHandsOnOnlyWhatALaterWalkWouldHold(t *testing.T) { submit(t, h, ConditionOwner, ask) runFor(h, c, time.Minute) stand(h, c) - walk(t, h, "plan-b", WalkStarted, "", c.now(), 1200, novox("node-tools")) + walk(t, h, "plan-b", WalkStarted, "", c.now(), 1200, nodeC("node-tools")) runFor(h, c, time.Minute) stand(h, c) helds := func(key string) int { @@ -747,7 +747,7 @@ func TestAStartHeardAfterItsEndOpensNothingWhenTheControllersClockIsAhead(t *tes h, _, _, c, _ := newHolder(t) ended := c.now().Add(10 * time.Minute) // by the controller's clock started := ended.Add(-20 * time.Second) - body := `{"walk":"plan-k","phase":"ended","outcome":"delivered","touches":[{"machine":"novox","modules":["mesh-tools"]}],` + + body := `{"walk":"plan-k","phase":"ended","outcome":"delivered","touches":[{"machine":"node-c","modules":["mesh-tools"]}],` + `"ended_at":"` + ended.Format(time.RFC3339Nano) + `"` if said == "both" { body += `,"started_at":"` + started.Format(time.RFC3339Nano) + `"` @@ -758,11 +758,11 @@ func TestAStartHeardAfterItsEndOpensNothingWhenTheControllersClockIsAhead(t *tes } h.Walked(end) c.pass(time.Second) - walk(t, h, "plan-k", WalkStarted, "", started, 600, novox("mesh-tools")) + walk(t, h, "plan-k", WalkStarted, "", started, 600, nodeC("mesh-tools")) if len(h.walks) != 0 { t.Fatalf("a start heard after its end opened a walk: %+v", h.walks) } - walk(t, h, "plan-k", WalkStarted, "", ended.Add(time.Minute), 600, novox("mesh-tools")) + walk(t, h, "plan-k", WalkStarted, "", ended.Add(time.Minute), 600, nodeC("mesh-tools")) if len(h.walks) != 1 { t.Fatalf("the next walk under its id, started after the end, did not open: %+v", h.walks) } diff --git a/modules/messenger/cmd/messenger/whole_test.go b/modules/messenger/cmd/messenger/whole_test.go index e696f832..d41a8a4f 100644 --- a/modules/messenger/cmd/messenger/whole_test.go +++ b/modules/messenger/cmd/messenger/whole_test.go @@ -16,7 +16,7 @@ import ( // with them whole, and Details with the fingerprint and where to read it, which the note shows. func proposalAsk(c *clock, id string) asks.Ask { a := heldAsk(c, id) - a.Headline = "Set mounts on shanks?" + a.Headline = "Set mounts on node-d?" a.Options = a.Options[:2] a.Explanation = "+ shares: media=‹path›\n+ sources: recalbox=‹address›@‹path›\nProposed by an agent at 15:11." a.Whole = "+ shares: media=/storage/media\n+ sources: recalbox=smb://nas.lan/recalbox@/mnt/recalbox\nProposed by an agent at 15:11." @@ -46,7 +46,7 @@ func TestAnAsksWholeWordsAreShownWhereTheSenderIsProvenAndMaskedElsewhere(t *tes !strings.Contains(phone.Note, "Read it whole: settings proposals s-1 at the controller's terminal.") { t.Errorf("the phone's note lacks the Details:\n%s", phone.Note) } - if phone.Title != "Set mounts on shanks?" || ticketFor(phone, "Release") == "" || ticketFor(phone, DetailsLabel) != "" { + if phone.Title != "Set mounts on node-d?" || ticketFor(phone, "Release") == "" || ticketFor(phone, DetailsLabel) != "" { t.Errorf("the phone's message: %q offering %s", phone.Title, labelsOf(phone)) } // The desk proves nothing: the same record composed for it shows the explanation, its values masked. @@ -69,7 +69,7 @@ func TestAnAsksWholeWordsAreShownWhereTheSenderIsProvenAndMaskedElsewhere(t *tes if !ok { t.Fatalf("the phone's message was not edited: %+v", tg.edits) } - if edited.Title != "Set mounts on shanks?" || edited.Body == "" || + if edited.Title != "Set mounts on node-d?" || edited.Body == "" || !strings.HasPrefix(edited.Note, "You chose Release at ") || len(edited.Actions) != 0 { t.Errorf("the edited message: %q\n%s\nactions %+v", edited.Title, edited.Body, edited.Actions) } @@ -176,7 +176,7 @@ func TestEveryKeyAndItsWholeValueIsInTheNoteWhereTheSenderIsProven(t *testing.T) return strings.Join(out, "\n") } a := proposalAsk(c, "s-9") - a.Explanation = "Changes 5 setting(s) of mounts on shanks.\n+ a: 1\n+ b: 2\nand 3 more, each whole below: c, d, shares" + a.Explanation = "Changes 5 setting(s) of mounts on node-d.\n+ a: 1\n+ b: 2\nand 3 more, each whole below: c, d, shares" a.Whole = "" a.Details = "Fingerprint 1234 5678 9abc def0 1234 5678.\n" + lines(masked) a.WholeDetails = "Fingerprint 1234 5678 9abc def0 1234 5678.\n" + lines(keys) diff --git a/modules/messenger/cmd/messenger/words_test.go b/modules/messenger/cmd/messenger/words_test.go index 5403bdf4..31f8f2ae 100644 --- a/modules/messenger/cmd/messenger/words_test.go +++ b/modules/messenger/cmd/messenger/words_test.go @@ -64,58 +64,58 @@ var examples = []example{{ cleared: "Resolved: openrazer delivery no longer waiting, after 5.0 h", openFor: 5 * time.Hour, }, { name: "a module unhealthy", - before: "WARNING: openrazer on g14 is not healthy: its unit openrazer-daemon.service failed in the account's own " + - "service manager (exit-code)\nabout: module openrazer.g14 on g14 (module-unhealthy)\nsince: 2026-10-08 " + - "10:40 UTC\nkey: module.openrazer.g14.unhealthy\nmore: conditions show module.openrazer.g14.unhealthy", - key: "module.openrazer.g14.unhealthy", kind: "module-unhealthy", severity: Warning, - subject: map[string]string{"scope": "module", "id": "openrazer.g14", "machine": "g14"}, - summary: "openrazer on g14 is not healthy: its unit openrazer-daemon.service failed in the account's own " + + before: "WARNING: openrazer on node-b is not healthy: its unit openrazer-daemon.service failed in the account's own " + + "service manager (exit-code)\nabout: module openrazer.node-b on node-b (module-unhealthy)\nsince: 2026-10-08 " + + "10:40 UTC\nkey: module.openrazer.node-b.unhealthy\nmore: conditions show module.openrazer.node-b.unhealthy", + key: "module.openrazer.node-b.unhealthy", kind: "module-unhealthy", severity: Warning, + subject: map[string]string{"scope": "module", "id": "openrazer.node-b", "machine": "node-b"}, + summary: "openrazer on node-b is not healthy: its unit openrazer-daemon.service failed in the account's own " + "service manager (exit-code)", - headline: "openrazer not working on g14", - needs: "restart its service openrazer-daemon on g14; if it fails again, the details say why.", - explanation: "Needs you: restart its service openrazer-daemon on g14; if it fails again, the details say why. " + - "openrazer on g14 is not healthy: its service openrazer-daemon stopped with an error. It clears as soon as " + + headline: "openrazer not working on node-b", + needs: "restart its service openrazer-daemon on node-b; if it fails again, the details say why.", + explanation: "Needs you: restart its service openrazer-daemon on node-b; if it fails again, the details say why. " + + "openrazer on node-b is not healthy: its service openrazer-daemon stopped with an error. It clears as soon as " + "it runs again.", - resolved: "openrazer works again on g14", popup: true, - title: "openrazer not working on g14", - body: "Needs you: restart its service openrazer-daemon on g14; if it fails again, the details say why. openrazer " + - "on g14 is not healthy: its service openrazer-daemon stopped with an error. It clears as soon as it runs " + + resolved: "openrazer works again on node-b", popup: true, + title: "openrazer not working on node-b", + body: "Needs you: restart its service openrazer-daemon on node-b; if it fails again, the details say why. openrazer " + + "on node-b is not healthy: its service openrazer-daemon stopped with an error. It clears as soon as it runs " + "again.\nNo issue tracks this yet.\nSince 12:40.\nNo delivery running.", offers: "Details", choose: "Details", - cleared: "Resolved: openrazer works again on g14, after 2.0 h", openFor: 2 * time.Hour, + cleared: "Resolved: openrazer works again on node-b, after 2.0 h", openFor: 2 * time.Hour, }, { name: "failed units on a machine", - before: "WARNING: shanks's service manager is degraded: 3 failed unit(s) no module places — mnt-recalbox.mount, " + + before: "WARNING: node-d's service manager is degraded: 3 failed unit(s) no module places — mnt-recalbox.mount, " + "storage-media.mount, greenclip.service (the account's own manager). Each is the machine's own: mend or " + - "remove it there, or have a module place it\nabout: machine shanks on shanks (machine-units)\nsince: " + - "2026-10-08 10:40 UTC\nkey: machine.shanks.units\nmore: conditions show machine.shanks.units", - key: "machine.shanks.units", kind: "machine-units", severity: Warning, - subject: map[string]string{"scope": "machine", "id": "shanks", "machine": "shanks"}, - summary: "shanks's service manager is degraded: 3 failed unit(s) no module places — mnt-recalbox.mount, " + + "remove it there, or have a module place it\nabout: machine node-d on node-d (machine-units)\nsince: " + + "2026-10-08 10:40 UTC\nkey: machine.node-d.units\nmore: conditions show machine.node-d.units", + key: "machine.node-d.units", kind: "machine-units", severity: Warning, + subject: map[string]string{"scope": "machine", "id": "node-d", "machine": "node-d"}, + summary: "node-d's service manager is degraded: 3 failed unit(s) no module places — mnt-recalbox.mount, " + "storage-media.mount, greenclip.service (the account's own manager). Each is the machine's own: mend or " + "remove it there, or have a module place it", - headline: "3 failed services on shanks", needs: "mend or remove them on shanks, or silence this if they do not matter.", - explanation: "Needs you: mend or remove them on shanks, or silence this if they do not matter. On shanks, " + + headline: "3 failed services on node-d", needs: "mend or remove them on node-d, or silence this if they do not matter.", + explanation: "Needs you: mend or remove them on node-d, or silence this if they do not matter. On node-d, " + "mnt-recalbox (a mount), storage-media (a mount) and greenclip failed. No module manages them, so the mesh " + "does not repair them.", actions: []Action{{Label: "Silence for a week", Verb: "mesh-controller.conditions", - Arguments: map[string]string{"silence": "machine.shanks.units", "for": "7d", "why": "", "cause": "operator-answer"}}}, - resolved: "No failed services on shanks any more", popup: true, - title: "3 failed services on shanks", - body: "Needs you: mend or remove them on shanks, or silence this if they do not matter. On shanks, mnt-recalbox " + + Arguments: map[string]string{"silence": "machine.node-d.units", "for": "7d", "why": "", "cause": "operator-answer"}}}, + resolved: "No failed services on node-d any more", popup: true, + title: "3 failed services on node-d", + body: "Needs you: mend or remove them on node-d, or silence this if they do not matter. On node-d, mnt-recalbox " + "(a mount), storage-media (a mount) and greenclip failed. No module manages them, so the mesh does not repair " + "them.\nNo issue tracks this yet.\nSince 12:40.\nNo delivery running.", offers: "Details", choose: "Details", - cleared: "Resolved: no failed services on shanks any more, after 45 min", openFor: 45 * time.Minute, + cleared: "Resolved: no failed services on node-d any more, after 45 min", openFor: 45 * time.Minute, }, { name: "a healer wanted", - before: "WARNING: \"push\" was repaired by hand 35 times in 14 days, the last by g14.node-tools, through the " + + before: "WARNING: \"push\" was repaired by hand 35 times in 14 days, the last by node-b.node-tools, through the " + "mesh-controller seat: a healer is wanted for it\nabout: mesh hand-acts.push (healer-wanted)\nsince: " + "2026-10-08 10:40 UTC\nkey: mesh.hand-acts.push.healer-wanted\nmore: conditions show " + "mesh.hand-acts.push.healer-wanted", key: "mesh.hand-acts.push.healer-wanted", kind: "healer-wanted", severity: Warning, subject: map[string]string{"scope": "mesh", "id": "hand-acts.push"}, - summary: "\"push\" was repaired by hand 35 times in 14 days, the last by g14.node-tools, through the " + + summary: "\"push\" was repaired by hand 35 times in 14 days, the last by node-b.node-tools, through the " + "mesh-controller seat: a healer is wanted for it", headline: "Push keeps being fixed by hand", explanation: "Nothing for you to do. A person repaired push by hand 35 times in 14 days, so an automatic repair " + @@ -217,7 +217,7 @@ func TestRealNotificationsReadInOneGlanceAndAreAnsweredFromTheNotification(t *te } // The router performs nothing: Details is shown where it was chosen, and the condition's own actions // are never called from here (novox/hq ADR 0259) — the controller asks for them. - outcome, err := h.Chosen("desktop", choiceOf(tok, "g14", c.now())) + outcome, err := h.Chosen("desktop", choiceOf(tok, "node-b", c.now())) done := dt.sends[len(dt.sends)-1] if err != nil || outcome != "shown" || len(asked) != 0 || done.Title != "Details: "+e.headline { t.Fatalf("details: %q %v %v %q", outcome, err, asked, done.Title) @@ -230,7 +230,7 @@ func TestRealNotificationsReadInOneGlanceAndAreAnsweredFromTheNotification(t *te h.Condition(EventCleared, cleared) c.pass(ClearSettle) h.Tick() - end := dt.edits["g14=1"] + end := dt.edits["node-b=1"] if end.Title != e.cleared || end.Body != "" || len(end.Actions) != 0 { t.Errorf("clearance %q / %q / %v, want one line %q", end.Title, end.Body, end.Actions, e.cleared) } @@ -275,7 +275,7 @@ func TestDetailsAreShownOnTheMachineThatAsked(t *testing.T) { if details.Label != DetailsLabel { t.Fatalf("%+v", m.Actions) } - if _, err := h.Chosen("desktop", choiceOf(details.Token, "g14", c.now())); err != nil { + if _, err := h.Chosen("desktop", choiceOf(details.Token, "node-b", c.now())); err != nil { t.Fatal(err) } shown := dt.sends[len(dt.sends)-1] @@ -283,7 +283,7 @@ func TestDetailsAreShownOnTheMachineThatAsked(t *testing.T) { !strings.Contains(shown.Body, "Since: 8 Oct 10:40") { t.Errorf("details: %q / %q", shown.Title, shown.Body) } - if _, err := h.Chosen("desktop", choiceOf("not-a-token", "g14", c.now())); err == nil { + if _, err := h.Chosen("desktop", choiceOf("not-a-token", "node-b", c.now())); err == nil { t.Error("an unknown answer was taken") } } @@ -292,11 +292,11 @@ func TestDetailsAreShownOnTheMachineThatAsked(t *testing.T) { func TestAConditionWithoutPlainWordsIsSaidFromItsSummary(t *testing.T) { h, tg, _, c, _ := newHolder(t) h.Zone = func() *time.Location { return time.UTC } - k := Condition{Key: "machine.ace.silent", Scope: "machine", ID: "ace", Kind: "silent", Severity: Urgent, - Summary: "ace has not been heard from: `push ace` sends it again", Raised: c.now()} + k := Condition{Key: "machine.node-a.silent", Scope: "machine", ID: "node-a", Kind: "silent", Severity: Urgent, + Summary: "node-a has not been heard from: `push node-a` sends it again", Raised: c.now()} h.Condition(EventRaised, k) m := tg.sends[0] - if m.Title != "Urgent: Silent on ace" || m.Body != "Ace has not been heard from: a command sends it again\nSince 12:00.\nNo delivery running." { + if m.Title != "Urgent: Silent on node-a" || m.Body != "Node-a has not been heard from: a command sends it again\nSince 12:00.\nNo delivery running." { t.Errorf("%q / %q", m.Title, m.Body) } keyless(t, m) From 39d724fd77dba644de0f3b6914992c9b470e9ecb Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 22 Oct 2026 21:29:02 +0200 Subject: [PATCH 3/5] Name no node in route-adapter's, rofi's, claude-licence-manager's and nextcloud-client's fixtures (issue 1838) --- .../cmd/claude-licence-manager/manager_test.go | 16 ++++++++-------- modules/nextcloud-client/README.md | 6 +++--- modules/rofi/cmd/rofi-tools/secret.go | 2 +- modules/rofi/cmd/rofi-tools/secret_test.go | 12 ++++++------ .../cmd/route-provider/provider_test.go | 16 ++++++++-------- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/modules/claude-licence-manager/cmd/claude-licence-manager/manager_test.go b/modules/claude-licence-manager/cmd/claude-licence-manager/manager_test.go index 4f8103fb..8e5de584 100644 --- a/modules/claude-licence-manager/cmd/claude-licence-manager/manager_test.go +++ b/modules/claude-licence-manager/cmd/claude-licence-manager/manager_test.go @@ -347,7 +347,7 @@ func TestAReportIsReadAsTheAgentModuleWritesIt(t *testing.T) { func TestANodeReportingAnAdoptedAccountLaterIsBoundToIt(t *testing.T) { mm := newMesh(t) ctx := context.Background() - _, _ = mm.m.Consider(ctx, []Holdings{mm.login("novox", "rt-new", true, t0)}) + _, _ = mm.m.Consider(ctx, []Holdings{mm.login("node-c", "rt-new", true, t0)}) late := mm.login("laptop", "rt-older", true, t0.Add(-24*time.Hour)) _, _ = mm.m.Consider(ctx, []Holdings{late}) if mm.state["laptop"].Licence != licence1 { @@ -477,16 +477,16 @@ func TestEveryMoveSaysWhatWhyAndWho(t *testing.T) { t.Fatal(err) } - asked := WithCause(ctx, Cause{Why: "the switch verb", By: "g14.node-tools"}) + asked := WithCause(ctx, Cause{Why: "the switch verb", By: "node-b.node-tools"}) if _, err := mm.m.Bind(asked, "laptop", "api"); err != nil { t.Fatal(err) } - if s := mm.state["laptop"]; s.Why != "the switch verb" || s.By != "g14.node-tools" { + if s := mm.state["laptop"]; s.Why != "the switch verb" || s.By != "node-b.node-tools" { t.Fatalf("the node is told %+v", s) } said := strings.Join(lines, "\n") if !strings.Contains(said, "switched laptop from "+licence1+" to api (generation ") || - !strings.Contains(said, "the switch verb; asked by g14.node-tools") { + !strings.Contains(said, "the switch verb; asked by node-b.node-tools") { t.Fatalf("the journal said:\n%s", said) } var switched string @@ -495,18 +495,18 @@ func TestEveryMoveSaysWhatWhyAndWho(t *testing.T) { switched = e } } - for _, want := range []string{`"by":"g14.node-tools"`, `"from":"` + licence1 + `"`, `"licence":"api"`, `"consumer":"laptop"`, `"generation":`} { + for _, want := range []string{`"by":"node-b.node-tools"`, `"from":"` + licence1 + `"`, `"licence":"api"`, `"consumer":"laptop"`, `"generation":`} { if !strings.Contains(switched, want) { t.Fatalf("the event %q lacks %s; events %v", switched, want, mm.events) } } last := mm.store.Audits[len(mm.store.Audits)-1] - if raw, _ := json.Marshal(last); !strings.Contains(string(raw), `"by":"g14.node-tools"`) || !strings.Contains(string(raw), "switched") { + if raw, _ := json.Marshal(last); !strings.Contains(string(raw), `"by":"node-b.node-tools"`) || !strings.Contains(string(raw), "switched") { t.Fatalf("the audit kept %s", raw) } - _, _ = mm.m.Rotate(WithCause(ctx, Cause{Why: "the refresh verb", By: "novox.node-tools"}), licence1, true) - if !strings.Contains(strings.Join(mm.events, "|"), `licence.rotated {"by":"novox.node-tools"`) { + _, _ = mm.m.Rotate(WithCause(ctx, Cause{Why: "the refresh verb", By: "node-c.node-tools"}), licence1, true) + if !strings.Contains(strings.Join(mm.events, "|"), `licence.rotated {"by":"node-c.node-tools"`) { t.Fatalf("a rotation asked for said no caller: %v", mm.events) } diff --git a/modules/nextcloud-client/README.md b/modules/nextcloud-client/README.md index 1ef7b1fe..ccf0b16b 100644 --- a/modules/nextcloud-client/README.md +++ b/modules/nextcloud-client/README.md @@ -71,7 +71,7 @@ through an injected runner and a fake root in the tests. ## What changes when it is assigned -| | g14 | shanks | +| | node-b | node-d | |---|---|---| | package | none: `nextcloud-client` 34.0.4 is installed, explicitly, from `extra` | the same | | start | none: dex starts it from the client's own entry (`--background`, in the login session's scope) | none on disk. **The client running now came from the predecessor's window-manager line** (`nextcloud`, a child of i3, since the session of 2026-10-04 16:00). That session began before the `i3` module dropped the line and installed `dex`, so the next login is the first that starts it from its entry | @@ -83,11 +83,11 @@ The workstations are already in the state this module describes. Nothing is required on either machine. -- **shanks:** log out and in once, or run `nextcloud_restart`, and the client runs from its one start. +- **node-d:** log out and in once, or run `nextcloud_restart`, and the client runs from its one start. `nextcloud_check` then answers `ok`. - **Optional, both:** the client has kept a `nextcloud.cfg.backup__` from every upgrade since 2023 (about twenty on each machine). It also keeps a sync log that it no longer writes, at - `~/.config/Nextcloud/Nextcloud_sync.log`, from 2024 on g14 and 2023 on shanks. They are the + `~/.config/Nextcloud/Nextcloud_sync.log`, from 2024 on node-b and 2023 on node-d. They are the operator's to delete. The module leaves them. ## Leaves as found diff --git a/modules/rofi/cmd/rofi-tools/secret.go b/modules/rofi/cmd/rofi-tools/secret.go index 80377868..aa23a8c1 100644 --- a/modules/rofi/cmd/rofi-tools/secret.go +++ b/modules/rofi/cmd/rofi-tools/secret.go @@ -43,7 +43,7 @@ type SecretAnswer struct { var aName = regexp.MustCompile(`^[a-z0-9][a-z0-9-]{0,62}$`) // aCaller is who asked, as the controller names the bus's caller (novox/hq ADR 0277): a principal such as -// `g14/claude-code`, or an account at a shell, in a name's characters and spaces, at most 80. Nothing else — no line +// `node-b/claude-code`, or an account at a shell, in a name's characters and spaces, at most 80. Nothing else — no line // break, no markup, no punctuation a sentence is written with — so the prompt's words stay this holder's. var aCaller = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._/@ -]{0,79}$`) diff --git a/modules/rofi/cmd/rofi-tools/secret_test.go b/modules/rofi/cmd/rofi-tools/secret_test.go index 454a97fc..7c58781f 100644 --- a/modules/rofi/cmd/rofi-tools/secret_test.go +++ b/modules/rofi/cmd/rofi-tools/secret_test.go @@ -113,11 +113,11 @@ func TestThePromptIsWrittenHereFromNamesAndSaysTheControllerAsks(t *testing.T) { t.Errorf("prompt %q, message %q", q.Prompt, q.Message) } // Asked by the vault's own account, as the runtime proved it (issue 723): the prompt says the vault asks. - if q, err := secretQuestion("novox.mesh-vault", base); err != nil || + if q, err := secretQuestion("node-c.mesh-vault", base); err != nil || !strings.HasPrefix(q.Message, "The mesh's vault asks for telegram-token") { t.Errorf("asked by the vault: %q %v", q.Message, err) } - if q, _ := secretQuestion("novox.mesh-vault-not", base); !strings.HasPrefix(q.Message, "The mesh's controller") { + if q, _ := secretQuestion("node-c.mesh-vault-not", base); !strings.HasPrefix(q.Message, "The mesh's controller") { t.Errorf("a caller that is not the vault's account is said to be the vault: %q", q.Message) } // And who asked the controller, when it says so (novox/hq ADR 0277): a caller's name, in a name's characters. @@ -125,13 +125,13 @@ func TestThePromptIsWrittenHereFromNamesAndSaysTheControllerAsks(t *testing.T) { for k, v := range base { withAsker[k] = v } - withAsker["asked_by"] = "g14/claude-code" + withAsker["asked_by"] = "node-b/claude-code" q, err = secretQuestion("unproven", withAsker) - if err != nil || !strings.Contains(q.Message, "It was asked for by g14/claude-code.") { + if err != nil || !strings.Contains(q.Message, "It was asked for by node-b/claude-code.") { t.Errorf("asked_by: %q %v", q.Message, err) } - withAsker["asked_by"] = "jochen at a shell on novox" - if q, err = secretQuestion("unproven", withAsker); err != nil || !strings.Contains(q.Message, "It was asked for by jochen at a shell on novox.") { + withAsker["asked_by"] = "operator at a shell on node-c" + if q, err = secretQuestion("unproven", withAsker); err != nil || !strings.Contains(q.Message, "It was asked for by operator at a shell on node-c.") { t.Errorf("asked_by at a shell: %q %v", q.Message, err) } for key, value := range map[string]any{ diff --git a/modules/route-adapter/cmd/route-provider/provider_test.go b/modules/route-adapter/cmd/route-provider/provider_test.go index abb464e1..e541a992 100644 --- a/modules/route-adapter/cmd/route-provider/provider_test.go +++ b/modules/route-adapter/cmd/route-provider/provider_test.go @@ -45,15 +45,15 @@ func (b *bucketBus) Delete(_ context.Context, bucket, key string) error { // the entry's values are the controller's composition, copied unchanged, and no vault is asked. func TestAConsumerOfARouteIsToldItsNamesFromItsPlanEntry(t *testing.T) { bus := &bucketBus{buckets: map[string]map[string][]byte{}} - plan, _ := json.Marshal(map[string]any{"node": "g14", "module": "gitea", "provisioning": map[string]any{ - "provisions": []any{map[string]any{"provision": ProvisionName, "provider": "novox", - "provider-module": ModuleName, "at": "10.7.0.1", "from": "novox", "as": "mesh_g14_gitea", - "names": map[string]any{"name": "git.example.org", "internal-name": "git.novox.internal", + plan, _ := json.Marshal(map[string]any{"node": "node-b", "module": "gitea", "provisioning": map[string]any{ + "provisions": []any{map[string]any{"provision": ProvisionName, "provider": "node-c", + "provider-module": ModuleName, "at": "10.7.0.1", "from": "node-c", "as": "mesh_node_b_gitea", + "names": map[string]any{"name": "git.example.org", "internal-name": "git.node-c.internal", "name-web": "git.example.org"}}}}}) - if err := bus.Put(context.Background(), provider.AssignmentsBucket, "g14.gitea", plan); err != nil { + if err := bus.Put(context.Background(), provider.AssignmentsBucket, "node-b.gitea", plan); err != nil { t.Fatal(err) } - p := newProvider("novox", bus, t.Logf) + p := newProvider("node-c", bus, t.Logf) out, err := p.Pass(context.Background()) if err != nil { t.Fatal(err) @@ -62,11 +62,11 @@ func TestAConsumerOfARouteIsToldItsNamesFromItsPlanEntry(t *testing.T) { t.Fatalf("the pass did %+v", out) } var e provider.Entry - if err := json.Unmarshal(bus.buckets[provider.BucketOf(ModuleName)]["g14.gitea.route"], &e); err != nil { + if err := json.Unmarshal(bus.buckets[provider.BucketOf(ModuleName)]["node-b.gitea.route"], &e); err != nil { t.Fatal(err) } if e.Values["name-web"] != "git.example.org" || e.Values["name"] != "git.example.org" || - e.Values["internal-name"] != "git.novox.internal" || e.VaultName != "" || e.User != "" || e.Refused != "" { + e.Values["internal-name"] != "git.node-c.internal" || e.VaultName != "" || e.User != "" || e.Refused != "" { t.Fatalf("the entry is %+v", e) } } From 5db896c81373541aaac053ab591ed861d1766c56 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 22 Oct 2026 21:31:02 +0200 Subject: [PATCH 4/5] Name no node in mesh-vault's fixtures (issue 1838) --- .../mesh-vault/cmd/mesh-vault/core_test.go | 4 +- .../mesh-vault/cmd/mesh-vault/ended_test.go | 26 ++-- .../cmd/mesh-vault/followups_test.go | 2 +- .../mesh-vault/cmd/mesh-vault/form_test.go | 64 ++++----- .../mesh-vault/cmd/mesh-vault/intake_test.go | 86 ++++++------ .../cmd/mesh-vault/issued_account_test.go | 16 +-- .../mesh-vault/cmd/mesh-vault/move_test.go | 40 +++--- .../cmd/mesh-vault/named_pair_test.go | 26 ++-- .../mesh-vault/cmd/mesh-vault/nodekey_test.go | 80 +++++------ .../mesh-vault/cmd/mesh-vault/notyet_test.go | 12 +- .../cmd/mesh-vault/own_issue_test.go | 26 ++-- .../cmd/mesh-vault/owncalls_test.go | 20 +-- .../mesh-vault/cmd/mesh-vault/pair_test.go | 130 +++++++++--------- .../cmd/mesh-vault/perholder_bus_test.go | 26 ++-- .../cmd/mesh-vault/perholder_test.go | 28 ++-- .../cmd/mesh-vault/providers_test.go | 8 +- .../cmd/mesh-vault/pulled_in_test.go | 20 +-- .../cmd/mesh-vault/retirement_test.go | 6 +- .../cmd/mesh-vault/rotate_one_test.go | 52 +++---- .../mesh-vault/testdata/retirement-state.json | 2 +- .../mesh-vault/testdata/retirement-word.json | 2 +- .../mesh-vault/cmd/mesh-vault/tools_test.go | 8 +- .../mesh-vault/cmd/mesh-vault/vault_test.go | 128 ++++++++--------- 23 files changed, 406 insertions(+), 406 deletions(-) diff --git a/modules/mesh-vault/cmd/mesh-vault/core_test.go b/modules/mesh-vault/cmd/mesh-vault/core_test.go index 0e98843e..962f2e1b 100644 --- a/modules/mesh-vault/cmd/mesh-vault/core_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/core_test.go @@ -98,7 +98,7 @@ func coreOnABus(t *testing.T) (ask func(name, key string) (Answer, error), ancho const conf = `listen: 127.0.0.1:-1 authorization { users = [ - { user: "novox.mesh-vault", password: "pw", permissions: { + { user: "node-c.mesh-vault", password: "pw", permissions: { publish: { deny: [">"] } subscribe: { allow: ["mesh.seat.mesh-vault.call.get.*"] } allow_responses: true } } @@ -150,7 +150,7 @@ authorization { t.Fatal(err) } - vaultConn := connectAs(t, url, "novox.mesh-vault") + vaultConn := connectAs(t, url, "node-c.mesh-vault") if _, err := vaultConn.Subscribe("mesh.seat.mesh-vault.call.get.*", func(m *nats.Msg) { parts := strings.Split(m.Subject, ".") var args struct { diff --git a/modules/mesh-vault/cmd/mesh-vault/ended_test.go b/modules/mesh-vault/cmd/mesh-vault/ended_test.go index e82d5e5a..ff02451a 100644 --- a/modules/mesh-vault/cmd/mesh-vault/ended_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/ended_test.go @@ -6,25 +6,25 @@ import "testing" // `state`) reads as a removed key, whichever way the vault reads it; the fields the controller adds change nothing. func TestAnEndedAssignmentIsNotAnAssignmentToTheVault(t *testing.T) { plan := `"provisioning":{"templates":{"source":"x","digest":"y"},"files":[],"secrets":[{"name":"token"}],` + - `"provisions":[{"provision":"gitea-read","provider":"novox","provider-module":"gitea"},` + - `{"name":"gitea-read","provision":"gitea-read","provider":"novox","provider-module":"gitea"}]}` - head := `{"node":"g14","module":"dunst","assigned":"2026-10-14T20:00:00Z",` + `"provisions":[{"provision":"gitea-read","provider":"node-c","provider-module":"gitea"},` + + `{"name":"gitea-read","provision":"gitea-read","provider":"node-c","provider-module":"gitea"}]}` + head := `{"node":"node-b","module":"dunst","assigned":"2026-10-14T20:00:00Z",` mirror := assignments{ - "g14.dunst": head + plan + `}`, - "g14.ended": `{"node":"g14","module":"ended","ended":"2026-10-18T01:00:00Z",` + plan + `}`, - "g14.wait": `{"node":"g14","module":"wait","state":"pending",` + plan + `}`, - "g14.new": `{"node":"g14","module":"new","build":"b1","artifact":{"name":"x","version":"1"},"commit":"c1",` + + "node-b.dunst": head + plan + `}`, + "node-b.ended": `{"node":"node-b","module":"ended","ended":"2026-10-18T01:00:00Z",` + plan + `}`, + "node-b.wait": `{"node":"node-b","module":"wait","state":"pending",` + plan + `}`, + "node-b.new": `{"node":"node-b","module":"new","build":"b1","artifact":{"name":"x","version":"1"},"commit":"c1",` + `"rollout":"r1","since":"2026-10-18T00:00:00Z","unknown-field":[1],"ended":"","state":"",` + plan + `}`, } rule := Declared{Read: mirror.read} for module, want := range map[string]bool{"dunst": true, "new": true, "ended": false, "wait": false} { - if ok, why := rule.May("provisioner.g14", "own/g14/"+module+"/token"); ok != want { + if ok, why := rule.May("provisioner.node-b", "own/node-b/"+module+"/token"); ok != want { t.Errorf("own secret of %s: allowed %v (%s), want %v", module, ok, why, want) } - if ok, why := rule.May("provisioner.g14", "provision/novox/gitea-read/g14/"+module); ok != want { + if ok, why := rule.May("provisioner.node-b", "provision/node-c/gitea-read/node-b/"+module); ok != want { t.Errorf("credential of %s: allowed %v (%s), want %v", module, ok, why, want) } - if why := pairRowRefusal(mirror.read, "g14", []string{"pair", "novox", "gitea-read", "g14", module}); (why == "") != want { + if why := pairRowRefusal(mirror.read, "node-b", []string{"pair", "node-c", "gitea-read", "node-b", module}); (why == "") != want { t.Errorf("pair row of %s: refusal %q, want allowed %v", module, why, want) } } @@ -33,11 +33,11 @@ func TestAnEndedAssignmentIsNotAnAssignmentToTheVault(t *testing.T) { t.Fatal(err) } for module, want := range map[string]bool{"dunst": true, "new": true, "ended": false, "wait": false} { - if seen.assigned["g14."+module] != want || seen.handed["g14."+module] != want { - t.Errorf("binding of %s: assigned %v, want %v", module, seen.assigned["g14."+module], want) + if seen.assigned["node-b."+module] != want || seen.handed["node-b."+module] != want { + t.Errorf("binding of %s: assigned %v, want %v", module, seen.assigned["node-b."+module], want) } } - if got := seen.bound[pairKey{"novox", "gitea-read"}]; got == nil || len(got.holders) != 2 { + if got := seen.bound[pairKey{"node-c", "gitea-read"}]; got == nil || len(got.holders) != 2 { t.Errorf("the bound holders of the provision: %+v", got) } } diff --git a/modules/mesh-vault/cmd/mesh-vault/followups_test.go b/modules/mesh-vault/cmd/mesh-vault/followups_test.go index aa5fbb8d..6bfd42b3 100644 --- a/modules/mesh-vault/cmd/mesh-vault/followups_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/followups_test.go @@ -98,7 +98,7 @@ func TestARolledRecordOfHandOutsIsSaid(t *testing.T) { v.Store.HandedMax = 600 asker, _ := seal.GenerateKeyPair() for i := 0; i < 20; i++ { - _, _ = v.Get("g14.flood", "pair/postgres/gitea", asker.PublicKey) + _, _ = v.Get("node-b.flood", "pair/postgres/gitea", asker.PublicKey) } rolled := 0 for _, s := range said { diff --git a/modules/mesh-vault/cmd/mesh-vault/form_test.go b/modules/mesh-vault/cmd/mesh-vault/form_test.go index 7c7d6e1d..5da9b183 100644 --- a/modules/mesh-vault/cmd/mesh-vault/form_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/form_test.go @@ -13,8 +13,8 @@ import ( func TestANewSharedProviderGetsOneFirstValueForEveryHolder(t *testing.T) { mirror := assignments{ "anchor.stand-in": handedWith("anchor", "stand-in"), - "g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in+shared"), - "ace.other": handedWith("ace", "other", "stand-in-api@anchor/stand-in+shared"), + "node-b.app": handedWith("node-b", "app", "stand-in-api@anchor/stand-in+shared"), + "node-a.other": handedWith("node-a", "other", "stand-in-api@anchor/stand-in+shared"), } v := pairVault(t, mirror) if o := pass(t, v, standIn); o.Outcome != PairMade || o.Generation != 1 { @@ -24,7 +24,7 @@ func TestANewSharedProviderGetsOneFirstValueForEveryHolder(t *testing.T) { if err != nil || value == "" { t.Fatalf("the provider's machine was refused its first value: %v", err) } - for _, c := range []string{"provisioner.g14", "provisioner.ace"} { + for _, c := range []string{"provisioner.node-b", "provisioner.node-a"} { if got, _, err := asks(v, c, standIn); err != nil || got != value { t.Fatalf("%s got %q (%v), not the one value", c, got, err) } @@ -42,11 +42,11 @@ func TestANewSharedProviderGetsOneFirstValueForEveryHolder(t *testing.T) { } func TestANewPerLoginProviderGetsAFirstLoginOfItsOwnForEachConsumer(t *testing.T) { - const pg = "provision/novox/postgres-database" + const pg = "provision/node-c/postgres-database" mirror := assignments{ - "novox.postgres": handedWith("novox", "postgres"), - "g14.gitea": handedWith("g14", "gitea", "postgres-database@novox/postgres+pair"), - "ace.umami": handedWith("ace", "umami", "postgres-database@novox/postgres#stats+pair"), + "node-c.postgres": handedWith("node-c", "postgres"), + "node-b.gitea": handedWith("node-b", "gitea", "postgres-database@node-c/postgres+pair"), + "node-a.umami": handedWith("node-a", "umami", "postgres-database@node-c/postgres#stats+pair"), } v := pairVault(t, mirror) if o := pass(t, v, pg); o.Outcome != PairMade { @@ -55,23 +55,23 @@ func TestANewPerLoginProviderGetsAFirstLoginOfItsOwnForEachConsumer(t *testing.T if _, held, _ := v.Store.Read(pg); held { t.Fatal("one shared value was made for a provider whose consumers each keep a login of their own") } - gitea, umami := "pair/novox/postgres-database/g14/gitea", "pair/novox/postgres-database/ace/umami/stats" - ofGitea, _, err := asks(v, "provisioner.g14", gitea) + gitea, umami := "pair/node-c/postgres-database/node-b/gitea", "pair/node-c/postgres-database/node-a/umami/stats" + ofGitea, _, err := asks(v, "provisioner.node-b", gitea) if err != nil || ofGitea == "" { t.Fatalf("gitea's machine was refused its first login: %v", err) } - ofUmami, _, err := asks(v, "provisioner.ace", umami) + ofUmami, _, err := asks(v, "provisioner.node-a", umami) if err != nil || ofUmami == "" { t.Fatalf("umami's machine was refused its first login: %v", err) } if ofGitea == ofUmami { t.Fatal("two consumers of a per-login provider were given one value") } - if _, _, err := asks(v, "provisioner.g14", umami); err == nil { + if _, _, err := asks(v, "provisioner.node-b", umami); err == nil { t.Fatal("gitea's machine was handed umami's login") } for name, want := range map[string]string{gitea: ofGitea, umami: ofUmami} { - if got, _, err := asks(v, "provisioner.novox", name); err != nil || got != want { + if got, _, err := asks(v, "provisioner.node-c", name); err != nil || got != want { t.Fatalf("the provider's machine got %q for %s (%v)", got, name, err) } } @@ -79,7 +79,7 @@ func TestANewPerLoginProviderGetsAFirstLoginOfItsOwnForEachConsumer(t *testing.T if o := pass(t, v, pg); o.Outcome != PairPerPair { t.Fatalf("the pass after the first logins: %+v", o) } - if got, gen, _ := asks(v, "provisioner.g14", gitea); got != ofGitea || gen != 1 { + if got, gen, _ := asks(v, "provisioner.node-b", gitea); got != ofGitea || gen != 1 { t.Fatal("a consumer's login was remade by the next pass") } } @@ -89,33 +89,33 @@ func TestAProviderWithRowsIsUnchangedByTheFormItsPlansName(t *testing.T) { t.Run("stamped rows", func(t *testing.T) { mirror := assignments{ "anchor.stand-in": handedWith("anchor", "stand-in"), - "g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in+shared"), + "node-b.app": handedWith("node-b", "app", "stand-in-api@anchor/stand-in+shared"), } v := pairVault(t, mirror) - movedRow(t, v, "g14", "app", "the-value-they-share", "stamp-1", OriginMade) + movedRow(t, v, "node-b", "app", "the-value-they-share", "stamp-1", OriginMade) if o := pass(t, v, standIn); o.Outcome != PairAdopted { t.Fatalf("stamped rows: %+v", o) } - if got, gen, _ := asks(v, "provisioner.g14", standIn); got != "the-value-they-share" || gen != 1 { + if got, gen, _ := asks(v, "provisioner.node-b", standIn); got != "the-value-they-share" || gen != 1 { t.Fatal("the adopted value is not the move's") } }) t.Run("logins of their own", func(t *testing.T) { mirror := assignments{ "anchor.stand-in": handedWith("anchor", "stand-in"), - "g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in+shared"), - "ace.other": handedWith("ace", "other", "stand-in-api@anchor/stand-in+pair"), + "node-b.app": handedWith("node-b", "app", "stand-in-api@anchor/stand-in+shared"), + "node-a.other": handedWith("node-a", "other", "stand-in-api@anchor/stand-in+pair"), } v := pairVault(t, mirror) - movedRow(t, v, "g14", "app", "login-of-app", "", OriginMade) - movedRow(t, v, "ace", "other", "login-of-other", "", OriginMade) + movedRow(t, v, "node-b", "app", "login-of-app", "", OriginMade) + movedRow(t, v, "node-a", "other", "login-of-other", "", OriginMade) if o := pass(t, v, standIn); o.Outcome != PairPerPair { t.Fatalf("unstamped rows: %+v", o) } if _, held, _ := v.Store.Read(standIn); held { t.Fatal("a shared value was made for a provider whose rows are logins of their own") } - if got, gen, _ := asks(v, "provisioner.g14", "pair/anchor/stand-in-api/g14/app"); got != "login-of-app" || + if got, gen, _ := asks(v, "provisioner.node-b", "pair/anchor/stand-in-api/node-b/app"); got != "login-of-app" || gen != 1 { t.Fatal("a consumer's own login changed") } @@ -150,8 +150,8 @@ func TestTheVaultMakesNothingForAFormItDoesNotMakeOrCannotTrust(t *testing.T) { } mirror := assignments{ "anchor.stand-in": provider, - "g14.app": handedWith("g14", "app", entry(first)), - "ace.other": handedWith("ace", "other", entry(second)), + "node-b.app": handedWith("node-b", "app", entry(first)), + "node-a.other": handedWith("node-a", "other", entry(second)), } v := pairVault(t, mirror) if o := pass(t, v, standIn); o.Outcome != PairHeld || !strings.Contains(o.Why, said) { @@ -172,25 +172,25 @@ func TestTheVaultMakesNothingForAFormItDoesNotMakeOrCannotTrust(t *testing.T) { func TestANewConsumerOfAPerLoginProviderWithRowsGetsALoginOfItsOwn(t *testing.T) { mirror := assignments{ "anchor.stand-in": handedWith("anchor", "stand-in"), - "g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in+pair"), - "ace.other": handedWith("ace", "other", "stand-in-api@anchor/stand-in+pair"), + "node-b.app": handedWith("node-b", "app", "stand-in-api@anchor/stand-in+pair"), + "node-a.other": handedWith("node-a", "other", "stand-in-api@anchor/stand-in+pair"), } v := pairVault(t, mirror) - movedRow(t, v, "g14", "app", "login-of-app", "", OriginMade) - movedRow(t, v, "ace", "other", "login-of-other", "", OriginMade) - app, other := "pair/anchor/stand-in-api/g14/app", "pair/anchor/stand-in-api/ace/other" - third := "pair/anchor/stand-in-api/novox/third" + movedRow(t, v, "node-b", "app", "login-of-app", "", OriginMade) + movedRow(t, v, "node-a", "other", "login-of-other", "", OriginMade) + app, other := "pair/anchor/stand-in-api/node-b/app", "pair/anchor/stand-in-api/node-a/other" + third := "pair/anchor/stand-in-api/node-c/third" before, said := map[string]Record{}, map[string]int{} for _, n := range []string{app, other} { r, _, _ := v.Store.Read(n) before[n], said[n] = r, changedSaid(t, v, n, "") } - mirror["novox.third"] = handedWith("novox", "third", "stand-in-api@anchor/stand-in+pair") + mirror["node-c.third"] = handedWith("node-c", "third", "stand-in-api@anchor/stand-in+pair") if o := pass(t, v, standIn); o.Outcome != PairMade { t.Fatalf("a third consumer binding: %+v", o) } - got, _, err := asks(v, "provisioner.novox", third) + got, _, err := asks(v, "provisioner.node-c", third) if err != nil || got == "" || got == "login-of-app" || got == "login-of-other" { t.Fatalf("the third consumer has no login of its own: %q (%v)", got, err) } @@ -215,7 +215,7 @@ func TestANewConsumerOfAPerLoginProviderWithRowsGetsALoginOfItsOwn(t *testing.T) if o := pass(t, v, standIn); o.Outcome != PairPerPair { t.Fatalf("the pass after the new login: %+v", o) } - if got2, _, _ := asks(v, "provisioner.novox", third); got2 != got { + if got2, _, _ := asks(v, "provisioner.node-c", third); got2 != got { t.Fatal("the new login was remade by the next pass") } } diff --git a/modules/mesh-vault/cmd/mesh-vault/intake_test.go b/modules/mesh-vault/cmd/mesh-vault/intake_test.go index e795bad7..061ffea1 100644 --- a/modules/mesh-vault/cmd/mesh-vault/intake_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/intake_test.go @@ -83,18 +83,18 @@ func telegramAsk(by string) AskOf { // it; the typed value opens only in the vault; the controller carries ciphertext only. func TestAnAskIsRecordedBeforeThePromptAndTheTypedValueOpensOnlyInTheVault(t *testing.T) { v := newVault(t, AllowList{"anchor.node-provisioner": {"own/anchor/telegram/telegram-token"}}) - opened, err := v.AskOpen(ControllerCaller, telegramAsk("g14/claude-code, via the console")) + opened, err := v.AskOpen(ControllerCaller, telegramAsk("node-b/claude-code, via the console")) if err != nil { t.Fatal(err) } // Recorded before any prompt opens: the record holds the ask now, with no end. asks, _ := v.Store.Asks(10) - if len(asks) != 1 || asks[0].Event != AskOpened || asks[0].ID != opened.Call || asks[0].AskedBy != "g14/claude-code" || + if len(asks) != 1 || asks[0].Event != AskOpened || asks[0].ID != opened.Call || asks[0].AskedBy != "node-b/claude-code" || asks[0].Caller != ControllerCaller || asks[0].Desk != "laptop" || asks[0].Secret != "own/anchor/telegram/telegram-token" { t.Fatalf("the record before the prompt: %+v", asks) } // The prompt names the asker as the bus named it, cut to a name: what the vault answers is what it recorded. - if opened.AskedBy != "g14/claude-code" { + if opened.AskedBy != "node-b/claude-code" { t.Errorf("the prompt would name %q", opened.AskedBy) } // The desk seals what is typed to the call's key; the controller passes it on. @@ -102,14 +102,14 @@ func TestAnAskIsRecordedBeforeThePromptAndTheTypedValueOpensOnlyInTheVault(t *te if err != nil { t.Fatal(err) } - if changed.Generation != 1 || changed.By != "g14/claude-code" { + if changed.Generation != 1 || changed.By != "node-b/claude-code" { t.Errorf("kept as %+v", changed) } if got := handedTo(t, v, "anchor.node-provisioner", "own/anchor/telegram/telegram-token"); got != typedAtTheDesk { t.Errorf("the vault holds %q, not what was typed with its line ending taken off", got) } rec, _, _ := v.Store.Read("own/anchor/telegram/telegram-token") - if rec.Origin != OriginTyped || rec.ChangedBy != "g14/claude-code" || rec.ChangedVia != ControllerCaller { + if rec.Origin != OriginTyped || rec.ChangedBy != "node-b/claude-code" || rec.ChangedVia != ControllerCaller { t.Errorf("the record says origin %q, by %q, via %q", rec.Origin, rec.ChangedBy, rec.ChangedVia) } asks, _ = v.Store.Asks(10) @@ -124,16 +124,16 @@ func TestAnAskIsRecordedBeforeThePromptAndTheTypedValueOpensOnlyInTheVault(t *te // One open ask per secret, and three an hour (ADR 0277 §24), read from the vault's own record. func TestAnAskIsBoundedToOneOpenPerSecretAndThreeAnHour(t *testing.T) { v := newVault(t, nil) - first, err := v.AskOpen(ControllerCaller, telegramAsk("g14.claude-code")) + first, err := v.AskOpen(ControllerCaller, telegramAsk("node-b.claude-code")) if err != nil { t.Fatal(err) } - if _, err := v.AskOpen(ControllerCaller, telegramAsk("ace.claude-code")); err == nil || - !strings.Contains(err.Error(), "still open (asked by g14.claude-code)") { + if _, err := v.AskOpen(ControllerCaller, telegramAsk("node-a.claude-code")); err == nil || + !strings.Contains(err.Error(), "still open (asked by node-b.claude-code)") { t.Fatalf("a second ask while one is open: %v", err) } // Another secret is not held back by it. - other := telegramAsk("ace.claude-code") + other := telegramAsk("node-a.claude-code") other.Name = "webhook-secret" if _, err := v.AskOpen(ControllerCaller, other); err != nil { t.Fatalf("another secret's ask was held back: %v", err) @@ -142,7 +142,7 @@ func TestAnAskIsBoundedToOneOpenPerSecretAndThreeAnHour(t *testing.T) { t.Fatal(err) } for i := 0; i < 2; i++ { - o, err := v.AskOpen(ControllerCaller, telegramAsk("g14.claude-code")) + o, err := v.AskOpen(ControllerCaller, telegramAsk("node-b.claude-code")) if err != nil { t.Fatalf("ask %d of the hour: %v", i+2, err) } @@ -150,7 +150,7 @@ func TestAnAskIsBoundedToOneOpenPerSecretAndThreeAnHour(t *testing.T) { t.Fatal(err) } } - if _, err := v.AskOpen(ControllerCaller, telegramAsk("g14.claude-code")); err == nil || + if _, err := v.AskOpen(ControllerCaller, telegramAsk("node-b.claude-code")); err == nil || !strings.Contains(err.Error(), "3 times in the last hour") { t.Fatalf("a fourth ask in the hour: %v", err) } @@ -166,11 +166,11 @@ func TestAnAskIsBoundedToOneOpenPerSecretAndThreeAnHour(t *testing.T) { w := newVault(t, nil) clock := time.Date(2026, 10, 14, 9, 0, 0, 0, time.UTC) w.Now = func() time.Time { return clock } - if _, err := w.AskOpen(ControllerCaller, telegramAsk("g14.claude-code")); err != nil { + if _, err := w.AskOpen(ControllerCaller, telegramAsk("node-b.claude-code")); err != nil { t.Fatal(err) } clock = clock.Add(SecretAskOpenFor + time.Second) - if _, err := w.AskOpen(ControllerCaller, telegramAsk("g14.claude-code")); err != nil { + if _, err := w.AskOpen(ControllerCaller, telegramAsk("node-b.claude-code")); err != nil { t.Errorf("an ask left open past its time still held the secret: %v", err) } } @@ -179,7 +179,7 @@ func TestAnAskIsBoundedToOneOpenPerSecretAndThreeAnHour(t *testing.T) { // call's key, or a call that waited too long, keeps nothing. func TestAnAskIsTakenFromTheControllerAloneAndOnlySealedToItsCall(t *testing.T) { v := newVault(t, nil) - for _, caller := range []string{"g14.node-tools", "unproven", "", "person.jochen"} { + for _, caller := range []string{"node-b.node-tools", "unproven", "", "person.jochen"} { if _, err := v.AskOpen(caller, telegramAsk("x")); err == nil { t.Errorf("%q opened an ask", caller) } @@ -187,11 +187,11 @@ func TestAnAskIsTakenFromTheControllerAloneAndOnlySealedToItsCall(t *testing.T) if asks, _ := v.Store.Asks(10); len(asks) != 0 { t.Fatalf("a refused caller filled the record: %+v", asks) } - opened, err := v.AskOpen(ControllerCaller, telegramAsk("g14.claude-code")) + opened, err := v.AskOpen(ControllerCaller, telegramAsk("node-b.claude-code")) if err != nil { t.Fatal(err) } - if _, err := v.AskEnd("g14.node-tools", opened.Call, sealToCall(t, opened.SealTo, "x"), ""); err == nil { + if _, err := v.AskEnd("node-b.node-tools", opened.Call, sealToCall(t, opened.SealTo, "x"), ""); err == nil { t.Error("another caller ended the ask") } other, _, _ := box.GenerateKey(rand.Reader) @@ -223,7 +223,7 @@ func TestAnAskIsTakenFromTheControllerAloneAndOnlySealedToItsCall(t *testing.T) } // An empty answer gives nothing and says so. clock = clock.Add(time.Hour) - empty, _ := v.AskOpen(ControllerCaller, telegramAsk("g14.claude-code")) + empty, _ := v.AskOpen(ControllerCaller, telegramAsk("node-b.claude-code")) if _, err := v.AskEnd(ControllerCaller, empty.Call, sealToCall(t, empty.SealTo, " \n"), ""); err == nil { t.Error("an empty answer was kept") } @@ -278,7 +278,7 @@ func TestAnIssuingProviderAnswersOnlyTheVaultsCallSealedToTheVault(t *testing.T) provider := standInProvider(&software) // The provider's tool refuses every caller but the vault's account and the controller, whatever it asks. - for _, caller := range []string{"anchor.node-tools", "g14.claude-code", "unproven", ""} { + for _, caller := range []string{"anchor.node-tools", "node-b.claude-code", "unproven", ""} { if _, err := provider(caller, map[string]any{"provision": "plex-api", "seal_to": "x"}); err == nil { t.Errorf("the provider's tool answered %q", caller) } @@ -351,11 +351,11 @@ func TestAnIssuingProviderAnswersOnlyTheVaultsCallSealedToTheVault(t *testing.T) // A value given at the controller's terminal is sealed there to the vault's call and opened here alone; an // accepted provision's credential is never remade; a module's own given value rotates as a made one (ADR 0228). func TestAnAcceptedValueOpensInTheVaultAloneAndIsNotRemade(t *testing.T) { - v := newVault(t, AllowList{"g14.node-provisioner": {"provision/novox/postgres", "own/g14/dunst/token"}}) - if _, err := v.AcceptOpen("g14.claude-code", "provision/novox/postgres", "", ""); err == nil { + v := newVault(t, AllowList{"node-b.node-provisioner": {"provision/node-c/postgres", "own/node-b/dunst/token"}}) + if _, err := v.AcceptOpen("node-b.claude-code", "provision/node-c/postgres", "", ""); err == nil { t.Error("accept was opened for a caller that is not the controller") } - for name, value := range map[string]string{"provision/novox/postgres": "pw-of-last-year", "own/g14/dunst/token": "tok"} { + for name, value := range map[string]string{"provision/node-c/postgres": "pw-of-last-year", "own/node-b/dunst/token": "tok"} { opened, err := v.AcceptOpen(ControllerCaller, name, "jochen", "") if err != nil { t.Fatal(err) @@ -367,7 +367,7 @@ func TestAnAcceptedValueOpensInTheVaultAloneAndIsNotRemade(t *testing.T) { if changed.By != "jochen" { t.Errorf("%s accepted by %q", name, changed.By) } - if got := handedTo(t, v, "g14.node-provisioner", name); got != value { + if got := handedTo(t, v, "node-b.node-provisioner", name); got != value { t.Errorf("%s holds %q", name, got) } rec, _, _ := v.Store.Read(name) @@ -375,15 +375,15 @@ func TestAnAcceptedValueOpensInTheVaultAloneAndIsNotRemade(t *testing.T) { t.Errorf("%s: origin %q via %q", name, rec.Origin, rec.ChangedVia) } } - if _, err := v.Rotate(ControllerCaller, "provision/novox/postgres", "jochen", "leaked"); err == nil || + if _, err := v.Rotate(ControllerCaller, "provision/node-c/postgres", "jochen", "leaked"); err == nil || !strings.Contains(err.Error(), "not remade") { t.Errorf("rotate of an accepted credential: %v", err) } - rotated, err := v.Rotate(ControllerCaller, "own/g14/dunst/token", "jochen", "leaked") + rotated, err := v.Rotate(ControllerCaller, "own/node-b/dunst/token", "jochen", "leaked") if err != nil || rotated.Generation != 2 { t.Fatalf("rotate of a module's own given value: %+v %v", rotated, err) } - if got := handedTo(t, v, "g14.node-provisioner", "own/g14/dunst/token"); got == "tok" || len(got) != 40 { + if got := handedTo(t, v, "node-b.node-provisioner", "own/node-b/dunst/token"); got == "tok" || len(got) != 40 { t.Errorf("rotated to %q", got) } if strings.Contains(everything(t, v), "pw-of-last-year") { @@ -395,19 +395,19 @@ func TestAnAcceptedValueOpensInTheVaultAloneAndIsNotRemade(t *testing.T) { // person the controller names when it carries the act — both kept. func TestRotateKeepsWhoAskedAndWhoCarriedIt(t *testing.T) { v := newVault(t, nil) - if _, err := v.Rotate(ControllerCaller, "own/g14/dunst/token", "jochen", "leaked"); err == nil { + if _, err := v.Rotate(ControllerCaller, "own/node-b/dunst/token", "jochen", "leaked"); err == nil { t.Error("a secret not held was rotated") } - if _, err := v.Mint("own/g14/dunst/token", "the test"); err != nil { + if _, err := v.Mint("own/node-b/dunst/token", "the test"); err != nil { t.Fatal(err) } - if _, err := v.Rotate("unproven", "own/g14/dunst/token", "", "leaked"); err == nil { + if _, err := v.Rotate("unproven", "own/node-b/dunst/token", "", "leaked"); err == nil { t.Error("an unproven caller rotated") } - if _, err := v.Rotate(ControllerCaller, "own/g14/dunst/token", "jochen", "leaked"); err != nil { + if _, err := v.Rotate(ControllerCaller, "own/node-b/dunst/token", "jochen", "leaked"); err != nil { t.Fatal(err) } - rec, _, _ := v.Store.Read("own/g14/dunst/token") + rec, _, _ := v.Store.Read("own/node-b/dunst/token") if rec.ChangedBy != "jochen" || rec.ChangedVia != ControllerCaller || rec.Generation != 2 { t.Errorf("by %q via %q generation %d", rec.ChangedBy, rec.ChangedVia, rec.Generation) } @@ -418,35 +418,35 @@ func TestRotateKeepsWhoAskedAndWhoCarriedIt(t *testing.T) { // drift from the value the controller holds; and a rotation without a reason is refused. Neither changes anything. func TestRotateIsTheControllersAloneAndSaysWhy(t *testing.T) { v := newVault(t, nil) - if _, err := v.Mint("own/g14/dunst/token", "the test"); err != nil { + if _, err := v.Mint("own/node-b/dunst/token", "the test"); err != nil { t.Fatal(err) } - for _, caller := range []string{"g14.claude-code", "g14.node-provisioner", "unproven", ""} { - if _, err := v.Rotate(caller, "own/g14/dunst/token", "jochen", "leaked"); err == nil || + for _, caller := range []string{"node-b.claude-code", "node-b.node-provisioner", "unproven", ""} { + if _, err := v.Rotate(caller, "own/node-b/dunst/token", "jochen", "leaked"); err == nil || !strings.Contains(err.Error(), "controller alone") { t.Errorf("%q rotated: %v", caller, err) } } for _, why := range []string{"", " "} { - if _, err := v.Rotate(ControllerCaller, "own/g14/dunst/token", "jochen", why); err == nil || + if _, err := v.Rotate(ControllerCaller, "own/node-b/dunst/token", "jochen", why); err == nil || !strings.Contains(err.Error(), "why") { t.Errorf("a rotation without a why (%q): %v", why, err) } } - if rec, _, _ := v.Store.Read("own/g14/dunst/token"); rec.Generation != 1 { + if rec, _, _ := v.Store.Read("own/node-b/dunst/token"); rec.Generation != 1 { t.Fatalf("a refused rotation changed the secret: generation %d", rec.Generation) } } // The names the vault keeps them under are names, never paths. func TestTheNamesOfWhatIsTakenIn(t *testing.T) { - if n, err := OwnSecret("g14", "dunst", "token"); err != nil || n != "own/g14/dunst/token" { + if n, err := OwnSecret("node-b", "dunst", "token"); err != nil || n != "own/node-b/dunst/token" { t.Errorf("%q %v", n, err) } - if n, err := ProvisionSecret("novox", "postgres"); err != nil || n != "provision/novox/postgres" { + if n, err := ProvisionSecret("node-c", "postgres"); err != nil || n != "provision/node-c/postgres" { t.Errorf("%q %v", n, err) } - for _, bad := range [][3]string{{"..", "x", "y"}, {"g14", "a/b", "y"}, {"g14", "x", ""}, {"G14", "x", "y"}} { + for _, bad := range [][3]string{{"..", "x", "y"}, {"node-b", "a/b", "y"}, {"node-b", "x", ""}, {"NODE-B", "x", "y"}} { if _, err := OwnSecret(bad[0], bad[1], bad[2]); err == nil { t.Errorf("%v was taken", bad) } @@ -466,7 +466,7 @@ func TestTheVerbsTakeTheirCallerFromTheRuntime(t *testing.T) { "plex.plex_issued_credential@anchor": standInProvider(&software)}}).ask ask := toolNamed(t, defs, Seat+".secret-ask") args := map[string]any{"node": "anchor", "module": "telegram", "name": "telegram-token", "desk": "laptop", - "asked_by": "g14.claude-code", "caller": ControllerCaller} + "asked_by": "node-b.claude-code", "caller": ControllerCaller} if _, err := ask.Run(args); err == nil { t.Error("an ask opened for a caller named in the arguments") } @@ -480,10 +480,10 @@ func TestTheVerbsTakeTheirCallerFromTheRuntime(t *testing.T) { } accept := toolNamed(t, defs, Seat+".accept") - if _, err := accept.runAs(ControllerCaller, map[string]any{"node": "g14", "provision": "postgres"}); err == nil { + if _, err := accept.runAs(ControllerCaller, map[string]any{"node": "node-b", "provision": "postgres"}); err == nil { t.Error("accept took a name both ways") } - answer, err = accept.runAs(ControllerCaller, map[string]any{"provider": "novox", "provision": "postgres", "by": "jochen"}) + answer, err = accept.runAs(ControllerCaller, map[string]any{"provider": "node-c", "provision": "postgres", "by": "jochen"}) if err != nil { t.Fatal(err) } @@ -492,7 +492,7 @@ func TestTheVerbsTakeTheirCallerFromTheRuntime(t *testing.T) { t.Fatal(err) } rotate := toolNamed(t, defs, Seat+".rotate") - if _, err := rotate.runAs("g14.claude-code", map[string]any{"node": "g14", "module": "dunst", "name": "token"}); err == nil { + if _, err := rotate.runAs("node-b.claude-code", map[string]any{"node": "node-b", "module": "dunst", "name": "token"}); err == nil { t.Error("a secret not held was rotated through the verb") } @@ -514,7 +514,7 @@ func TestTheVerbsTakeTheirCallerFromTheRuntime(t *testing.T) { // With the lock held elsewhere, AskEnd waits, and writes nothing until it is let go. func TestTheEndOfAnAskIsWrittenUnderTheRecordsLock(t *testing.T) { v := newVault(t, nil) - opened, err := v.AskOpen(ControllerCaller, telegramAsk("g14.claude-code")) + opened, err := v.AskOpen(ControllerCaller, telegramAsk("node-b.claude-code")) if err != nil { t.Fatal(err) } diff --git a/modules/mesh-vault/cmd/mesh-vault/issued_account_test.go b/modules/mesh-vault/cmd/mesh-vault/issued_account_test.go index 01e99e8f..50d837d6 100644 --- a/modules/mesh-vault/cmd/mesh-vault/issued_account_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/issued_account_test.go @@ -19,8 +19,8 @@ func handIssued(t *testing.T, v testVault, caller, secret, value string) (Change } func TestAHandedBusAccountIsKeptServedReplacedAndNeverMadeByTheVault(t *testing.T) { - const moved = "own/g14/moved-bot/broker" - v := newVault(t, AllowList{"provisioner.g14": {moved}}) + const moved = "own/node-b/moved-bot/broker" + v := newVault(t, AllowList{"provisioner.node-b": {moved}}) first, err := handIssued(t, v, ControllerCaller, moved, `{"password":"first-pw"}`) if err != nil || first.Generation != 1 { @@ -30,7 +30,7 @@ func TestAHandedBusAccountIsKeptServedReplacedAndNeverMadeByTheVault(t *testing. if !held || rec.Origin != OriginIssued || rec.ChangedVia != ControllerCaller { t.Fatalf("kept as origin %q via %q (held %v), want issued via the controller", rec.Origin, rec.ChangedVia, held) } - if got := handedTo(t, v, "provisioner.g14", moved); got != `{"password":"first-pw"}` { + if got := handedTo(t, v, "provisioner.node-b", moved); got != `{"password":"first-pw"}` { t.Errorf("the moved module's client is handed %q", got) } @@ -40,7 +40,7 @@ func TestAHandedBusAccountIsKeptServedReplacedAndNeverMadeByTheVault(t *testing. if err != nil || second.Generation != 2 || second.Unchanged { t.Fatalf("the re-issue: %+v %v", second, err) } - if got := handedTo(t, v, "provisioner.g14", moved); got != `{"password":"second-pw"}` { + if got := handedTo(t, v, "provisioner.node-b", moved); got != `{"password":"second-pw"}` { t.Errorf("after the re-issue the client is handed %q: a stale value stayed", got) } changedEvents := 0 @@ -57,21 +57,21 @@ func TestAHandedBusAccountIsKeptServedReplacedAndNeverMadeByTheVault(t *testing. if _, err := v.Rotate(ControllerCaller, moved, "jochen", "leaked"); err == nil || !strings.Contains(err.Error(), "ADR 0374") { t.Errorf("the vault rotated a covered account: %v", err) } - if _, err := v.Rotate(ControllerCaller, "own/g14/moved-bot/provisioner-broker", "jochen", "leaked"); err == nil { + if _, err := v.Rotate(ControllerCaller, "own/node-b/moved-bot/provisioner-broker", "jochen", "leaked"); err == nil { t.Error("the vault made a first value for a covered account by rotating it") } - if got := handedTo(t, v, "provisioner.g14", moved); got != `{"password":"second-pw"}` { + if got := handedTo(t, v, "provisioner.node-b", moved); got != `{"password":"second-pw"}` { t.Errorf("a refused rotation changed the value to %q", got) } // A secret that is not a covered account is not handed with origin issued; and only the controller hands one. - if _, err := v.AcceptOpen(ControllerCaller, "own/g14/moved-bot/token", "x", OriginIssued); err == nil { + if _, err := v.AcceptOpen(ControllerCaller, "own/node-b/moved-bot/token", "x", OriginIssued); err == nil { t.Error("origin issued was taken for a secret that is not a bus account") } if _, err := v.AcceptOpen(ControllerCaller, "provision/anchor/postgres", "x", OriginIssued); err == nil { t.Error("origin issued was taken for a provision's credential") } - if _, err := v.AcceptOpen("g14.moved-bot", moved, "x", OriginIssued); err == nil { + if _, err := v.AcceptOpen("node-b.moved-bot", moved, "x", OriginIssued); err == nil { t.Error("a caller that is not the controller handed a covered account") } if _, err := v.AcceptOpen(ControllerCaller, moved, "x", "made"); err == nil { diff --git a/modules/mesh-vault/cmd/mesh-vault/move_test.go b/modules/mesh-vault/cmd/mesh-vault/move_test.go index d2e41c1b..66eac840 100644 --- a/modules/mesh-vault/cmd/mesh-vault/move_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/move_test.go @@ -121,21 +121,21 @@ func TestAMovedValueKeepsWhereItCameFrom(t *testing.T) { // tools, not another machine's node-engine. func TestOnlyTheNodeEngineOfAMachineTheValueWasSealedToMovesIt(t *testing.T) { v := newVault(t, nil) - for _, caller := range []string{ControllerCaller, "anchor.node-tools", "anchor.mesh-vault", "node.shanks", "", + for _, caller := range []string{ControllerCaller, "anchor.node-tools", "anchor.mesh-vault", "node.node-d", "", "node.", "node.anchor.x"} { if _, err := v.MoveOpen(caller, superuser()); err == nil { t.Errorf("%q opened a move of anchor's value", caller) } } // A pair credential was sealed to both its ends: either may move it, and nobody else. - pair := MoveOf{Provider: "anchor", Provision: "database", Consumer: "shanks", ConsumerModule: "gitea", + pair := MoveOf{Provider: "anchor", Provision: "database", Consumer: "node-d", ConsumerModule: "gitea", Origin: "made", Generation: "g-1"} - for _, caller := range []string{"node.anchor", "node.shanks"} { + for _, caller := range []string{"node.anchor", "node.node-d"} { if _, err := v.MoveOpen(caller, pair); err != nil { t.Errorf("%s, an end of the pair, was refused: %v", caller, err) } } - if _, err := v.MoveOpen("node.g14", pair); err == nil { + if _, err := v.MoveOpen("node.node-b", pair); err == nil { t.Error("a machine at neither end opened a move of the pair") } // The second step is the first step's caller's alone. @@ -144,7 +144,7 @@ func TestOnlyTheNodeEngineOfAMachineTheValueWasSealedToMovesIt(t *testing.T) { t.Fatal(err) } key, _, _ := aReadBackKey(t) - if _, err := v.MoveTake("node.shanks", opened.Call, sealToCall(t, opened.SealTo, movedValue), key); err == nil { + if _, err := v.MoveTake("node.node-d", opened.Call, sealToCall(t, opened.SealTo, movedValue), key); err == nil { t.Error("another machine's node-engine took the second step") } if _, held, _ := v.Store.Read("own/anchor/postgres/superuser-password"); held { @@ -156,18 +156,18 @@ func TestOnlyTheNodeEngineOfAMachineTheValueWasSealedToMovesIt(t *testing.T) { // secret in the vault, kept as it is. func TestAPairCredentialMovesUnderTheNameOfItsRow(t *testing.T) { v := newVault(t, nil) - pair := MoveOf{Provider: "anchor", Provision: "database", Consumer: "shanks", ConsumerModule: "gitea", + pair := MoveOf{Provider: "anchor", Provision: "database", Consumer: "node-d", ConsumerModule: "gitea", Local: "replica", Origin: "accepted", Generation: "g-7"} - moved, err := moveIn(t, v, "node.shanks", pair, "the-pair-value") + moved, err := moveIn(t, v, "node.node-d", pair, "the-pair-value") if err != nil { t.Fatal(err) } - if moved.Name != "pair/anchor/database/shanks/gitea/replica" { + if moved.Name != "pair/anchor/database/node-d/gitea/replica" { t.Errorf("named %s", moved.Name) } pair.Local = "" if moved, err = moveIn(t, v, "node.anchor", pair, "the-ordinary-value"); err != nil || - moved.Name != "pair/anchor/database/shanks/gitea" { + moved.Name != "pair/anchor/database/node-d/gitea" { t.Errorf("the ordinary one: %+v, %v", moved, err) } } @@ -176,31 +176,31 @@ func TestAPairCredentialMovesUnderTheNameOfItsRow(t *testing.T) { // twice), and a different one is refused, so a value the vault holds is never put back to an older one. func TestTheMoveNeverReplacesAValueTheVaultHolds(t *testing.T) { v := newVault(t, nil) - pair := MoveOf{Provider: "anchor", Provision: "database", Consumer: "shanks", ConsumerModule: "gitea", + pair := MoveOf{Provider: "anchor", Provision: "database", Consumer: "node-d", ConsumerModule: "gitea", Origin: "made", Generation: "g-1"} if _, err := moveIn(t, v, "node.anchor", pair, "the-pair-value"); err != nil { t.Fatal(err) } - opened, err := v.MoveOpen("node.shanks", pair) + opened, err := v.MoveOpen("node.node-d", pair) if err != nil { t.Fatal(err) } key, pub, priv := aReadBackKey(t) - again, err := v.MoveTake("node.shanks", opened.Call, sealToCall(t, opened.SealTo, "the-pair-value"), key) + again, err := v.MoveTake("node.node-d", opened.Call, sealToCall(t, opened.SealTo, "the-pair-value"), key) if err != nil || !again.Unchanged || again.Generation != 1 { t.Fatalf("the other end's same value: %+v, %v", again, err) } if got := openReadBack(t, again.ReadBack, pub, priv); got != "the-pair-value" { t.Errorf("read back %q", got) } - if _, err := v.Rotate(ControllerCaller, "pair/anchor/database/shanks/gitea", "jochen", "a test"); err != nil { + if _, err := v.Rotate(ControllerCaller, "pair/anchor/database/node-d/gitea", "jochen", "a test"); err != nil { t.Fatal(err) } if _, err := moveIn(t, v, "node.anchor", pair, "the-pair-value"); err == nil || !strings.Contains(err.Error(), "never replaces") { t.Fatalf("a move over a value the vault changed since: %v", err) } - rec, _, _ := v.Store.Read("pair/anchor/database/shanks/gitea") + rec, _, _ := v.Store.Read("pair/anchor/database/node-d/gitea") if rec.Generation != 2 || rec.Origin != OriginMade { t.Errorf("the vault's own value was touched: %+v", rec) } @@ -240,11 +240,11 @@ func TestTheRecordOfAsksIsCopiedAsItIsOnce(t *testing.T) { now := v.Now() ended := now.Add(-30 * time.Second) asks := []MovedAsk{ - {ID: 41, Node: "anchor", Module: "telegram", Name: "telegram-token", Desk: "laptop", AskedBy: "g14/claude-code", + {ID: 41, Node: "anchor", Module: "telegram", Name: "telegram-token", Desk: "laptop", AskedBy: "node-b/claude-code", OpenedAt: now.Add(-50 * time.Minute), EndedAt: &ended, Outcome: "given"}, - {ID: 42, Node: "anchor", Module: "telegram", Name: "telegram-token", Desk: "laptop", AskedBy: "g14/claude-code", + {ID: 42, Node: "anchor", Module: "telegram", Name: "telegram-token", Desk: "laptop", AskedBy: "node-b/claude-code", OpenedAt: now.Add(-40 * time.Minute), EndedAt: &ended, Outcome: "dismissed"}, - {ID: 43, Node: "anchor", Module: "telegram", Name: "telegram-token", Desk: "laptop", AskedBy: "ace/agent", + {ID: 43, Node: "anchor", Module: "telegram", Name: "telegram-token", Desk: "laptop", AskedBy: "node-a/agent", OpenedAt: now.Add(-20 * time.Minute)}, } if _, err := v.MoveAsks("node.anchor", asks); err == nil { @@ -268,12 +268,12 @@ func TestTheRecordOfAsksIsCopiedAsItIsOnce(t *testing.T) { opened[r.ID] = r } } - if r := opened["controller-41"]; r.Secret != "own/anchor/telegram/telegram-token" || r.AskedBy != "g14/claude-code" || + if r := opened["controller-41"]; r.Secret != "own/anchor/telegram/telegram-token" || r.AskedBy != "node-b/claude-code" || r.Desk != "laptop" || !r.At.Equal(asks[0].OpenedAt) || r.Caller != ControllerCaller { t.Errorf("ask 41: %+v", r) } // Three asks in the hour, from the controller's record: the vault's bound holds them. - if _, err := v.AskOpen(ControllerCaller, telegramAsk("g14/claude-code")); err == nil || + if _, err := v.AskOpen(ControllerCaller, telegramAsk("node-b/claude-code")); err == nil || !strings.Contains(err.Error(), "in the last hour") { t.Errorf("an ask after three copied in the hour: %v", err) } @@ -313,7 +313,7 @@ func TestMoveInThroughTheTool(t *testing.T) { } asks := toolNamed(t, definitions(&Env{Vault: v.Vault}), Seat+".move-asks") moved, err := asks.runAs("controller", map[string]any{"asks": []any{map[string]any{"id": 7, "node": "anchor", - "module": "telegram", "name": "telegram-token", "desk": "laptop", "asked_by": "g14/claude-code", + "module": "telegram", "name": "telegram-token", "desk": "laptop", "asked_by": "node-b/claude-code", "opened_at": "2026-10-01T10:00:00Z", "ended_at": "2026-10-01T10:00:20Z", "outcome": "given"}}}) if err != nil || moved.(AsksMoved).Copied != 1 { t.Fatalf("asks through the tool: %+v, %v", moved, err) diff --git a/modules/mesh-vault/cmd/mesh-vault/named_pair_test.go b/modules/mesh-vault/cmd/mesh-vault/named_pair_test.go index 779f1a51..6497f915 100644 --- a/modules/mesh-vault/cmd/mesh-vault/named_pair_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/named_pair_test.go @@ -7,38 +7,38 @@ package main import "testing" func TestANamedPairEntryHandsTheConsumersMachineItsOwnLoginAndNoOtherConsumers(t *testing.T) { - const pg = "provision/novox/postgres-database" + const pg = "provision/node-c/postgres-database" mirror := assignments{ - "novox.postgres": handedWith("novox", "postgres"), - "g14.gitea": handedWith("g14", "gitea", "postgres-database@novox/postgres=database+pair"), - "ace.umami": handedWith("ace", "umami", "postgres-database@novox/postgres#stats=database-stats+pair"), - "shanks.other": handedWith("shanks", "other", "postgres-database@novox/postgres=database+pair"), + "node-c.postgres": handedWith("node-c", "postgres"), + "node-b.gitea": handedWith("node-b", "gitea", "postgres-database@node-c/postgres=database+pair"), + "node-a.umami": handedWith("node-a", "umami", "postgres-database@node-c/postgres#stats=database-stats+pair"), + "node-d.other": handedWith("node-d", "other", "postgres-database@node-c/postgres=database+pair"), } v := pairVault(t, mirror) if o := pass(t, v, pg); o.Outcome != PairMade { t.Fatalf("a named pair entry held the provider back: %+v", o) } - gitea, umami := "pair/novox/postgres-database/g14/gitea", "pair/novox/postgres-database/ace/umami/stats" - ofGitea, _, err := asks(v, "provisioner.g14", gitea) + gitea, umami := "pair/node-c/postgres-database/node-b/gitea", "pair/node-c/postgres-database/node-a/umami/stats" + ofGitea, _, err := asks(v, "provisioner.node-b", gitea) if err != nil || ofGitea == "" { t.Fatalf("the consumer's machine was refused its own login: %v", err) } - if ofUmami, _, err := asks(v, "provisioner.ace", umami); err != nil || ofUmami == "" || ofUmami == ofGitea { + if ofUmami, _, err := asks(v, "provisioner.node-a", umami); err != nil || ofUmami == "" || ofUmami == ofGitea { t.Fatalf("the second consumer's login: %q (%v)", ofUmami, err) } - if _, _, err := asks(v, "provisioner.g14", umami); err == nil { + if _, _, err := asks(v, "provisioner.node-b", umami); err == nil { t.Fatal("a consumer's machine was handed another consumer's login") } - if _, _, err := asks(v, "provisioner.shanks", gitea); err == nil { + if _, _, err := asks(v, "provisioner.node-d", gitea); err == nil { t.Fatal("a machine was handed the login of a module that is not its own") } // A named entry of another form is still not a pair row's. other := assignments{ - "novox.postgres": handedWith("novox", "postgres"), - "g14.gitea": handedWith("g14", "gitea", "postgres-database@novox/postgres=database+issued"), + "node-c.postgres": handedWith("node-c", "postgres"), + "node-b.gitea": handedWith("node-b", "gitea", "postgres-database@node-c/postgres=database+issued"), } w := pairVault(t, other) - if _, _, err := asks(w, "provisioner.g14", gitea); err == nil { + if _, _, err := asks(w, "provisioner.node-b", gitea); err == nil { t.Fatal("a named entry of the issued form was handed a pair row") } } diff --git a/modules/mesh-vault/cmd/mesh-vault/nodekey_test.go b/modules/mesh-vault/cmd/mesh-vault/nodekey_test.go index e266dc3d..5ba4b395 100644 --- a/modules/mesh-vault/cmd/mesh-vault/nodekey_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/nodekey_test.go @@ -31,20 +31,20 @@ func changedNames(p *published) []string { func TestANodeEngineStatesItsOwnKeyAndAChangeRaisesItsCoreSecrets(t *testing.T) { v := newVault(t, nil) tool := toolNamed(t, definitions(&Env{Vault: v.Vault}), Seat+".node-key") - // ace holds two core secrets and a leaf module's; g14 holds a core secret too. + // node-a holds two core secrets and a leaf module's; node-b holds a core secret too. old, _ := aSealingKey(t) for _, m := range []MoveOf{ - {Node: "ace", Module: "mesh-provisioner-client", Name: "provisioner-broker", Origin: "made", Generation: "g-1", SealingKey: old}, - {Node: "ace", Module: "nats", Name: "broker", Origin: "made", Generation: "g-1"}, - {Node: "ace", Module: "postgres", Name: "superuser-password", Origin: "made", Generation: "g-1"}, - {Node: "g14", Module: "nats", Name: "broker", Origin: "made", Generation: "g-1"}, + {Node: "node-a", Module: "mesh-provisioner-client", Name: "provisioner-broker", Origin: "made", Generation: "g-1", SealingKey: old}, + {Node: "node-a", Module: "nats", Name: "broker", Origin: "made", Generation: "g-1"}, + {Node: "node-a", Module: "postgres", Name: "superuser-password", Origin: "made", Generation: "g-1"}, + {Node: "node-b", Module: "nats", Name: "broker", Origin: "made", Generation: "g-1"}, } { if _, err := moveIn(t, v, "node."+m.Node, m, movedValue); err != nil { t.Fatal(err) } } - // ace never stated a key in the moves above except through the first row; forget it to be a machine that never moved. - if err := os.Remove(v.Store.nodeKeyPath("ace")); err != nil { + // node-a never stated a key in the moves above except through the first row; forget it to be a machine that never moved. + if err := os.Remove(v.Store.nodeKeyPath("node-a")); err != nil { t.Fatal(err) } before := len(changedNames(v.bus)) @@ -56,27 +56,27 @@ func TestANodeEngineStatesItsOwnKeyAndAChangeRaisesItsCoreSecrets(t *testing.T) if _, err := tool.runAs("", map[string]any{"key": pub}); err == nil { t.Error("an unproven caller stated a key") } - if _, err := tool.runAs("node.ace", map[string]any{"key": "c2hvcnQ="}); err == nil { + if _, err := tool.runAs("node.node-a", map[string]any{"key": "c2hvcnQ="}); err == nil { t.Error("a short key was taken") } - if _, err := tool.runAs("node.ace", map[string]any{"node": "g14", "key": pub}); err != nil { + if _, err := tool.runAs("node.node-a", map[string]any{"node": "node-b", "key": pub}); err != nil { t.Fatal(err) } // The machine is the caller's; an argument naming another one changes nothing. - if got, held, _ := v.Store.NodeKey("ace"); !held || got != pub { - t.Errorf("ace's key is %q, %v", got, held) + if got, held, _ := v.Store.NodeKey("node-a"); !held || got != pub { + t.Errorf("node-a's key is %q, %v", got, held) } - if _, held, _ := v.Store.NodeKey("g14"); held { - t.Error("a key was recorded for g14 by ace's engine") + if _, held, _ := v.Store.NodeKey("node-b"); held { + t.Error("a key was recorded for node-b by node-a's engine") } got := changedNames(v.bus)[before:] - want := []string{"own/ace/mesh-provisioner-client/provisioner-broker", "own/ace/nats/broker"} + want := []string{"own/node-a/mesh-provisioner-client/provisioner-broker", "own/node-a/nats/broker"} if strings.Join(got, ",") != strings.Join(want, ",") { t.Errorf("secret-changed was raised for %v, want %v", got, want) } // The same key again changes nothing and says nothing. - if _, err := tool.runAs("node.ace", map[string]any{"key": pub}); err != nil { + if _, err := tool.runAs("node.node-a", map[string]any{"key": pub}); err != nil { t.Fatal(err) } if n := len(changedNames(v.bus)); n != before+2 { @@ -84,13 +84,13 @@ func TestANodeEngineStatesItsOwnKeyAndAChangeRaisesItsCoreSecrets(t *testing.T) } // A different key raises them again. other, _ := aSealingKey(t) - if _, err := tool.runAs("node.ace", map[string]any{"key": other}); err != nil { + if _, err := tool.runAs("node.node-a", map[string]any{"key": other}); err != nil { t.Fatal(err) } if n := len(changedNames(v.bus)); n != before+4 { t.Errorf("a changed key raised %d, want 2", n-before-2) } - if got, _, _ := v.Store.NodeKey("ace"); got != other { + if got, _, _ := v.Store.NodeKey("node-a"); got != other { t.Error("the changed key was not recorded") } } @@ -98,22 +98,22 @@ func TestANodeEngineStatesItsOwnKeyAndAChangeRaisesItsCoreSecrets(t *testing.T) const nodeKeyBus = `listen: 127.0.0.1:-1 authorization { users = [ - { user: "novox.mesh-vault", password: "pw", permissions: { + { user: "node-c.mesh-vault", password: "pw", permissions: { publish: { deny: [">"] } subscribe: { allow: ["mesh.seat.mesh-vault.call.node-key.*"] } allow_responses: true } } - { user: "node.ace", password: "pw", permissions: { - publish: { allow: ["mesh.seat.mesh-vault.call.node-key.node_ace"] } - subscribe: { allow: ["_INBOX.node.ace.>"] } } } - { user: "node.g14", password: "pw", permissions: { - publish: { allow: ["mesh.seat.mesh-vault.call.node-key.node_g14"] } - subscribe: { allow: ["_INBOX.node.g14.>"] } } } + { user: "node.node-a", password: "pw", permissions: { + publish: { allow: ["mesh.seat.mesh-vault.call.node-key.node_node-a"] } + subscribe: { allow: ["_INBOX.node.node-a.>"] } } } + { user: "node.node-b", password: "pw", permissions: { + publish: { allow: ["mesh.seat.mesh-vault.call.node-key.node_node-b"] } + subscribe: { allow: ["_INBOX.node.node-b.>"] } } } ] } ` -// On a real bus whose accounts may publish only their own subject: node.ace's statement records ace's key; node.g14 -// cannot speak in ace's name, and what it states is g14's. +// On a real bus whose accounts may publish only their own subject: node.node-a's statement records node-a's key; node.node-b +// cannot speak in node-a's name, and what it states is node-b's. func TestOnARealBusANodeEngineStatesOnlyItsOwnKey(t *testing.T) { file := filepath.Join(t.TempDir(), "bus.conf") if err := os.WriteFile(file, []byte(nodeKeyBus), 0o600); err != nil { @@ -136,7 +136,7 @@ func TestOnARealBusANodeEngineStatesOnlyItsOwnKey(t *testing.T) { v := newVault(t, nil) tool := toolNamed(t, definitions(&Env{Vault: v.Vault}), Seat+".node-key") - vaultConn := connectAs(t, s.ClientURL(), "novox.mesh-vault") + vaultConn := connectAs(t, s.ClientURL(), "node-c.mesh-vault") if _, err := vaultConn.Subscribe("mesh.seat.mesh-vault.call.node-key.*", func(m *nats.Msg) { parts := strings.Split(m.Subject, ".") var args map[string]any @@ -167,25 +167,25 @@ func TestOnARealBusANodeEngineStatesOnlyItsOwnKey(t *testing.T) { } return "", nil } - aceKey, _ := aSealingKey(t) - g14Key, _ := aSealingKey(t) - if _, err := say("node.ace", "mesh.seat.mesh-vault.call.node-key.node_ace", aceKey); err != nil { + nodeAKey, _ := aSealingKey(t) + nodeBKey, _ := aSealingKey(t) + if _, err := say("node.node-a", "mesh.seat.mesh-vault.call.node-key.node_node-a", nodeAKey); err != nil { t.Fatal(err) } - if got, held, _ := v.Store.NodeKey("ace"); !held || got != aceKey { - t.Errorf("ace's key is %q, %v", got, held) + if got, held, _ := v.Store.NodeKey("node-a"); !held || got != nodeAKey { + t.Errorf("node-a's key is %q, %v", got, held) } - // g14 may not publish on ace's subject: the bus refuses it, so the vault never hears it. - if _, err := say("node.g14", "mesh.seat.mesh-vault.call.node-key.node_ace", g14Key); err == nil { - t.Error("node.g14 spoke in ace's name") + // node-b may not publish on node-a's subject: the bus refuses it, so the vault never hears it. + if _, err := say("node.node-b", "mesh.seat.mesh-vault.call.node-key.node_node-a", nodeBKey); err == nil { + t.Error("node.node-b spoke in node-a's name") } - if got, _, _ := v.Store.NodeKey("ace"); got != aceKey { - t.Error("ace's key was replaced by g14's") + if got, _, _ := v.Store.NodeKey("node-a"); got != nodeAKey { + t.Error("node-a's key was replaced by node-b's") } - if _, err := say("node.g14", "mesh.seat.mesh-vault.call.node-key.node_g14", g14Key); err != nil { + if _, err := say("node.node-b", "mesh.seat.mesh-vault.call.node-key.node_node-b", nodeBKey); err != nil { t.Fatal(err) } - if got, held, _ := v.Store.NodeKey("g14"); !held || got != g14Key { - t.Errorf("g14's key is %q, %v", got, held) + if got, held, _ := v.Store.NodeKey("node-b"); !held || got != nodeBKey { + t.Errorf("node-b's key is %q, %v", got, held) } } diff --git a/modules/mesh-vault/cmd/mesh-vault/notyet_test.go b/modules/mesh-vault/cmd/mesh-vault/notyet_test.go index 951ae1b6..33b31d25 100644 --- a/modules/mesh-vault/cmd/mesh-vault/notyet_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/notyet_test.go @@ -15,8 +15,8 @@ func TestAnAssignmentThatCannotBeReadIsNotYetAndNotARefusal(t *testing.T) { read := func(string) ([]byte, error) { return nil, down } v := newVault(t, Declared{Read: read}) asker, _ := seal.GenerateKeyPair() - for _, name := range []string{"own/g14/claude-code/token", "provision/novox/gitea-read/g14/claude-code"} { - _, err := v.Get("provisioner.g14", name, asker.PublicKey) + for _, name := range []string{"own/node-b/claude-code/token", "provision/node-c/gitea-read/node-b/claude-code"} { + _, err := v.Get("provisioner.node-b", name, asker.PublicKey) if err == nil { t.Fatalf("%s: answered while the assignment cannot be read and the vault holds nothing", name) } @@ -36,13 +36,13 @@ func TestAnAssignmentThatCannotBeReadIsNotYetAndNotARefusal(t *testing.T) { // assignment reads as absent stays "not on". func TestAPairRowWhoseAssignmentCannotBeReadIsNotYet(t *testing.T) { down := errors.New("nats: no responders available for request") - parts := []string{"pair", "novox", "db", "g14", "claude-code"} - why := pairRowRefusal(func(string) ([]byte, error) { return nil, down }, "g14", parts) + parts := []string{"pair", "node-c", "db", "node-b", "claude-code"} + why := pairRowRefusal(func(string) ([]byte, error) { return nil, down }, "node-b", parts) if !strings.HasPrefix(why, notYetPrefix) || !strings.Contains(why, "no responders") { t.Errorf("a read error answered %q, want a not-yet carrying the reason", why) } - why = pairRowRefusal(func(string) ([]byte, error) { return nil, nil }, "g14", parts) - if strings.HasPrefix(why, notYetPrefix) || !strings.Contains(why, "is not on g14") { + why = pairRowRefusal(func(string) ([]byte, error) { return nil, nil }, "node-b", parts) + if strings.HasPrefix(why, notYetPrefix) || !strings.Contains(why, "is not on node-b") { t.Errorf("an absent assignment answered %q, want the refusal 'not on'", why) } } diff --git a/modules/mesh-vault/cmd/mesh-vault/own_issue_test.go b/modules/mesh-vault/cmd/mesh-vault/own_issue_test.go index 84bacaac..2e72e0a3 100644 --- a/modules/mesh-vault/cmd/mesh-vault/own_issue_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/own_issue_test.go @@ -11,14 +11,14 @@ import ( // value for each; the next pass leaves them be, and a holder bound later is the only one asked. func TestThePassAsksAnIssuingProvidersToolForTheHoldersItHoldsNothingFor(t *testing.T) { mirror := assignments{ - "novox.gitea": handedWith("novox", "gitea"), - "anchor.claude-code": handedWith("anchor", "claude-code", "gitea-read@novox/gitea=gitea-read+issued~gitea_agent_token"), + "node-c.gitea": handedWith("node-c", "gitea"), + "anchor.claude-code": handedWith("anchor", "claude-code", "gitea-read@node-c/gitea=gitea-read+issued~gitea_agent_token"), } v := pairVault(t, mirror) var asked []map[string]any v.Ask = forgeMesh(perHolderProvider(agentTokens, &asked)).ask - o := pass(t, v, "provision/novox/gitea-read") + o := pass(t, v, "provision/node-c/gitea-read") if o.Outcome != PairPerHolder { t.Fatalf("outcome %+v", o) } @@ -33,14 +33,14 @@ func TestThePassAsksAnIssuingProvidersToolForTheHoldersItHoldsNothingFor(t *test } // Held is left untouched: no second ask, so the forge does not mint anew (rotation is the software's). - pass(t, v, "provision/novox/gitea-read") + pass(t, v, "provision/node-c/gitea-read") if len(asked) != 1 { t.Errorf("the tool was asked again for a holder that holds its value (%d asks)", len(asked)) } // A holder bound since is the only one asked. - mirror["laptop.claude-code"] = handedWith("laptop", "claude-code", "gitea-read@novox/gitea=gitea-read+issued~gitea_agent_token") - pass(t, v, "provision/novox/gitea-read") + mirror["laptop.claude-code"] = handedWith("laptop", "claude-code", "gitea-read@node-c/gitea=gitea-read+issued~gitea_agent_token") + pass(t, v, "provision/node-c/gitea-read") if len(asked) != 2 || strings.Contains(toString(asked[1]["holders"]), "anchor") { t.Fatalf("asks %v, want a second naming laptop alone", asked) } @@ -53,28 +53,28 @@ func TestThePassAsksAnIssuingProvidersToolForTheHoldersItHoldsNothingFor(t *test // tool is said, not guessed. func TestAFailedAskOfTheToolIsAskedAgainAndNoToolIsSaid(t *testing.T) { mirror := assignments{ - "novox.gitea": handedWith("novox", "gitea"), - "anchor.claude-code": handedWith("anchor", "claude-code", "gitea-read@novox/gitea=gitea-read+issued~gitea_agent_token"), + "node-c.gitea": handedWith("node-c", "gitea"), + "anchor.claude-code": handedWith("anchor", "claude-code", "gitea-read@node-c/gitea=gitea-read+issued~gitea_agent_token"), } v := pairVault(t, mirror) v.Ask = forgeMesh(func(string, map[string]any) (map[string]any, error) { return nil, errTest }).ask - o := pass(t, v, "provision/novox/gitea-read") + o := pass(t, v, "provision/node-c/gitea-read") if o.Outcome != PairHeld || !strings.Contains(o.Why, "could not be asked") { t.Fatalf("a failed ask is %+v", o) } var asked []map[string]any v.Ask = forgeMesh(perHolderProvider(agentTokens, &asked)).ask - pass(t, v, "provision/novox/gitea-read") + pass(t, v, "provision/node-c/gitea-read") if _, held, _ := v.Store.Read(anchorsToken); !held || len(asked) != 1 { t.Fatal("the next pass did not ask again and keep the value") } noTool := pairVault(t, assignments{ - "novox.gitea": handedWith("novox", "gitea"), - "anchor.claude-code": handedWith("anchor", "claude-code", "gitea-read@novox/gitea=gitea-read+issued"), + "node-c.gitea": handedWith("node-c", "gitea"), + "anchor.claude-code": handedWith("anchor", "claude-code", "gitea-read@node-c/gitea=gitea-read+issued"), }) noTool.Ask = v.Ask - if o := pass(t, noTool, "provision/novox/gitea-read"); o.Outcome != PairHeld || !strings.Contains(o.Why, "name no tool") { + if o := pass(t, noTool, "provision/node-c/gitea-read"); o.Outcome != PairHeld || !strings.Contains(o.Why, "name no tool") { t.Errorf("a plan with no tool is %+v", o) } } diff --git a/modules/mesh-vault/cmd/mesh-vault/owncalls_test.go b/modules/mesh-vault/cmd/mesh-vault/owncalls_test.go index 5f303955..0f62a142 100644 --- a/modules/mesh-vault/cmd/mesh-vault/owncalls_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/owncalls_test.go @@ -18,7 +18,7 @@ import ( ) // vaultsAccount is the vault's bus user as its own runtime names it to a tool it calls. -const vaultsAccount = "novox.mesh-vault" +const vaultsAccount = "node-c.mesh-vault" // aMesh stands in for the bus the vault's runtime calls on: each call is answered by the desk's prompt or a // provider's tool, named by the caller the vault's own account is, and everything that crosses is kept. @@ -97,11 +97,11 @@ func TestTheVaultAsksTheDesksPromptItselfAndOnlyASealedValueCrosses(t *testing.T mesh := &aMesh{desk: aDesk(typedAtTheDesk, &asked)} v.Ask = mesh.ask - got, err := v.AskAtDesk(ControllerCaller, telegramAsk("g14/claude-code, via the console")) + got, err := v.AskAtDesk(ControllerCaller, telegramAsk("node-b/claude-code, via the console")) if err != nil { t.Fatal(err) } - if got.Outcome != "given" || got.Generation != 1 || got.AskedBy != "g14/claude-code" || + if got.Outcome != "given" || got.Generation != 1 || got.AskedBy != "node-b/claude-code" || got.Secret != "own/anchor/telegram/telegram-token" { t.Errorf("answered %+v", got) } @@ -109,7 +109,7 @@ func TestTheVaultAsksTheDesksPromptItselfAndOnlyASealedValueCrosses(t *testing.T t.Fatalf("the vault asked %v", mesh.keys) } p := asked[0] - if p["asked_by"] != "g14/claude-code" || p["module"] != "telegram" || p["secret"] != "telegram-token" || + if p["asked_by"] != "node-b/claude-code" || p["module"] != "telegram" || p["secret"] != "telegram-token" || p["node"] != "anchor" || p["seal_to"] == "" || p["timeout_seconds"] != float64(DeskPromptFor) { t.Errorf("the prompt was asked %v", p) } @@ -117,7 +117,7 @@ func TestTheVaultAsksTheDesksPromptItselfAndOnlyASealedValueCrosses(t *testing.T t.Errorf("the vault holds %q", v) } rec, _, _ := v.Store.Read("own/anchor/telegram/telegram-token") - if rec.Origin != OriginTyped || rec.ChangedBy != "g14/claude-code" || rec.ChangedVia != ControllerCaller { + if rec.Origin != OriginTyped || rec.ChangedBy != "node-b/claude-code" || rec.ChangedVia != ControllerCaller { t.Errorf("the record: origin %q by %q via %q", rec.Origin, rec.ChangedBy, rec.ChangedVia) } asks, _ := v.Store.Asks(10) @@ -133,7 +133,7 @@ func TestTheVaultAsksTheDesksPromptItselfAndOnlyASealedValueCrosses(t *testing.T w := newVault(t, nil) var a []map[string]any w.Ask = (&aMesh{desk: aDesk(typed, &a)}).ask - got, err := w.AskAtDesk(ControllerCaller, telegramAsk("g14.claude-code")) + got, err := w.AskAtDesk(ControllerCaller, telegramAsk("node-b.claude-code")) if err != nil || got.Outcome != outcome { t.Errorf("%s: %+v %v", outcome, got, err) } @@ -148,13 +148,13 @@ func TestTheVaultAsksTheDesksPromptItselfAndOnlyASealedValueCrosses(t *testing.T e := newVault(t, nil) var ea []map[string]any e.Ask = (&aMesh{desk: aDesk(" ", &ea)}).ask - if got, err := e.AskAtDesk(ControllerCaller, telegramAsk("g14.claude-code")); err != nil || got.Outcome != "empty" { + if got, err := e.AskAtDesk(ControllerCaller, telegramAsk("node-b.claude-code")); err != nil || got.Outcome != "empty" { t.Errorf("empty: %+v %v", got, err) } // The desk cannot be asked: refused, recorded so. r := newVault(t, nil) r.Ask = (&aMesh{}).ask - if _, err := r.AskAtDesk(ControllerCaller, telegramAsk("g14.claude-code")); err == nil { + if _, err := r.AskAtDesk(ControllerCaller, telegramAsk("node-b.claude-code")); err == nil { t.Error("an ask nobody answered was said to be done") } if asks, _ := r.Store.Asks(1); asks[0].Outcome != "refused" { @@ -164,7 +164,7 @@ func TestTheVaultAsksTheDesksPromptItselfAndOnlyASealedValueCrosses(t *testing.T n := newVault(t, nil) var na []map[string]any n.Ask = (&aMesh{desk: aDesk(typedAtTheDesk, &na)}).ask - for _, caller := range []string{"g14.node-tools", "g14.claude-code", "unproven", ""} { + for _, caller := range []string{"node-b.node-tools", "node-b.claude-code", "unproven", ""} { if _, err := n.AskAtDesk(caller, telegramAsk("x")); err == nil { t.Errorf("%q had the vault ask a desk", caller) } @@ -205,7 +205,7 @@ func TestTheVaultAsksTheIssuingToolItselfAndOnlyASealedValueCrosses(t *testing.T } // Only the controller asks the vault to take it; a tool's name that is not one is refused; a tool that is not // answered, or answers no sealed value, keeps nothing. - for _, caller := range []string{"anchor.node-tools", "g14.claude-code", "unproven", ""} { + for _, caller := range []string{"anchor.node-tools", "node-b.claude-code", "unproven", ""} { if _, err := v.TakeIssued(caller, "plex-api", "anchor", "plex", "plex_issued_credential"); err == nil { t.Errorf("%q had the vault ask a provider", caller) } diff --git a/modules/mesh-vault/cmd/mesh-vault/pair_test.go b/modules/mesh-vault/cmd/mesh-vault/pair_test.go index f241624a..53f2e1f7 100644 --- a/modules/mesh-vault/cmd/mesh-vault/pair_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/pair_test.go @@ -130,10 +130,10 @@ func changedSaid(t *testing.T, v testVault, name, value string) int { func TestAConsumerBindingOrUnbindingRemakesTheProvidersOneCredentialForEveryHolder(t *testing.T) { mirror := assignments{ "anchor.stand-in": handedWith("anchor", "stand-in"), - "g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"), + "node-b.app": handedWith("node-b", "app", "stand-in-api@anchor/stand-in"), } v := pairVault(t, mirror) - movedRow(t, v, "g14", "app", "shared-from-the-move", "stamp-1", OriginMade) + movedRow(t, v, "node-b", "app", "shared-from-the-move", "stamp-1", OriginMade) // The move's shared value is adopted, and said to have changed in the vault. if o := pass(t, v, standIn); o.Outcome != PairAdopted || o.Generation != 1 { @@ -143,13 +143,13 @@ func TestAConsumerBindingOrUnbindingRemakesTheProvidersOneCredentialForEveryHold if err != nil { t.Fatalf("the provider's machine was refused its credential: %v", err) } - if got, _, err := asks(v, "provisioner.g14", standIn); err != nil || got != first { + if got, _, err := asks(v, "provisioner.node-b", standIn); err != nil || got != first { t.Fatalf("the consumer got %q (%v), the provider %q", got, err, first) } if first != "shared-from-the-move" || changedSaid(t, v, standIn, "") != 1 { t.Fatal("the adopted value is not the move's, or secret-changed was not said once for it") } - if _, _, err := asks(v, "provisioner.ace", standIn); err == nil { + if _, _, err := asks(v, "provisioner.node-a", standIn); err == nil { t.Fatal("a machine holding nothing of it was handed the credential") } @@ -159,7 +159,7 @@ func TestAConsumerBindingOrUnbindingRemakesTheProvidersOneCredentialForEveryHold } // A second consumer binds: the vault remakes it without the provider asking, one new value for all three. - mirror["ace.other"] = handedWith("ace", "other", "stand-in-api@anchor/stand-in") + mirror["node-a.other"] = handedWith("node-a", "other", "stand-in-api@anchor/stand-in") if o := pass(t, v, standIn); o.Outcome != PairRemade || o.Generation != 2 { t.Fatalf("a consumer binding: %+v", o) } @@ -167,7 +167,7 @@ func TestAConsumerBindingOrUnbindingRemakesTheProvidersOneCredentialForEveryHold if second == first || gen != 2 { t.Fatal("the value was not remade when a consumer bound") } - for _, c := range []string{"provisioner.g14", "provisioner.ace"} { + for _, c := range []string{"provisioner.node-b", "provisioner.node-a"} { if got, _, err := asks(v, c, standIn); err != nil || got != second { t.Fatalf("%s got %q (%v) after the bind, not the one new value", c, got, err) } @@ -177,24 +177,24 @@ func TestAConsumerBindingOrUnbindingRemakesTheProvidersOneCredentialForEveryHold } // It unbinds (its plan no longer names it): remade for the holders left, and it is handed nothing more. - mirror["ace.other"] = handedWith("ace", "other") + mirror["node-a.other"] = handedWith("node-a", "other") if o := pass(t, v, standIn); o.Outcome != PairRemade || o.Generation != 3 { t.Fatalf("a consumer unbinding: %+v", o) } third, _, _ := asks(v, "provisioner.anchor", standIn) - if got, _, _ := asks(v, "provisioner.g14", standIn); third == second || got != third { + if got, _, _ := asks(v, "provisioner.node-b", standIn); third == second || got != third { t.Fatal("the holders left do not share one new value after the unbind") } - if _, _, err := asks(v, "provisioner.ace", standIn); err == nil { + if _, _, err := asks(v, "provisioner.node-a", standIn); err == nil { t.Fatal("a consumer that unbound was still handed the credential") } // Its assignment goes: an unbind too. - delete(mirror, "g14.app") + delete(mirror, "node-b.app") if o := pass(t, v, standIn); o.Outcome != PairRemade { t.Fatalf("a consumer taken off its machine: %+v", o) } - if _, _, err := asks(v, "provisioner.g14", standIn); err == nil { + if _, _, err := asks(v, "provisioner.node-b", standIn); err == nil { t.Fatal("a machine whose consumer left was still handed the credential") } } @@ -203,23 +203,23 @@ func TestAConsumerBindingOrUnbindingRemakesTheProvidersOneCredentialForEveryHold // 757) has no one shared value. func TestLocalNamesAreBindsAndAPerHolderCredentialIsNotShared(t *testing.T) { mirror := assignments{ - "anchor.stand-in": handedWith("anchor", "stand-in"), - "g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in#reader"), - "novox.gitea": handedWith("novox", "gitea"), - "g14.claude-code": handedWith("g14", "claude-code", "gitea-read@novox/gitea=gitea-read"), + "anchor.stand-in": handedWith("anchor", "stand-in"), + "node-b.app": handedWith("node-b", "app", "stand-in-api@anchor/stand-in#reader"), + "node-c.gitea": handedWith("node-c", "gitea"), + "node-b.claude-code": handedWith("node-b", "claude-code", "gitea-read@node-c/gitea=gitea-read"), } v := pairVault(t, mirror) - movedRow(t, v, "g14", "app", "shared", "stamp-1", OriginMade, "reader") + movedRow(t, v, "node-b", "app", "shared", "stamp-1", OriginMade, "reader") pass(t, v, standIn) - mirror["g14.app"] = handedWith("g14", "app", "stand-in-api@anchor/stand-in#reader", + mirror["node-b.app"] = handedWith("node-b", "app", "stand-in-api@anchor/stand-in#reader", "stand-in-api@anchor/stand-in#writer") if o := pass(t, v, standIn); o.Outcome != PairRemade { t.Fatalf("a second local name binding: %+v", o) } - if o := pass(t, v, "provision/novox/gitea-read"); o.Outcome != PairPerHolder { + if o := pass(t, v, "provision/node-c/gitea-read"); o.Outcome != PairPerHolder { t.Fatalf("a credential per holder: %+v", o) } - if _, held, _ := v.Store.Read("provision/novox/gitea-read"); held { + if _, held, _ := v.Store.Read("provision/node-c/gitea-read"); held { t.Fatal("a shared value was made for a credential issued per holder") } } @@ -231,7 +231,7 @@ func TestAnAcceptedOrIssuedValueIsNotRemadeOnABind(t *testing.T) { t.Run(origin, func(t *testing.T) { mirror := assignments{ "anchor.stand-in": handedWith("anchor", "stand-in"), - "g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"), + "node-b.app": handedWith("node-b", "app", "stand-in-api@anchor/stand-in"), } v := pairVault(t, mirror) if _, err := v.keep(standIn, "given-by-a-person", "person.jochen", ControllerCaller, origin); err != nil { @@ -240,11 +240,11 @@ func TestAnAcceptedOrIssuedValueIsNotRemadeOnABind(t *testing.T) { if o := pass(t, v, standIn); o.Outcome != PairRecorded || o.Generation != 1 { t.Fatalf("the first pass: %+v", o) } - mirror["ace.other"] = handedWith("ace", "other", "stand-in-api@anchor/stand-in") + mirror["node-a.other"] = handedWith("node-a", "other", "stand-in-api@anchor/stand-in") if o := pass(t, v, standIn); o.Outcome != PairRecorded || o.Generation != 1 { t.Fatalf("a bind to a value %s: %+v", origin, o) } - for _, c := range []string{"provisioner.anchor", "provisioner.g14", "provisioner.ace"} { + for _, c := range []string{"provisioner.anchor", "provisioner.node-b", "provisioner.node-a"} { if got, gen, err := asks(v, c, standIn); err != nil || got != "given-by-a-person" || gen != 1 { t.Fatalf("%s got %q generation %d (%v)", c, got, gen, err) } @@ -272,17 +272,17 @@ func movedRow(t *testing.T, v testVault, consumer, module, value, stamp, origin func TestPairRowsSharingAGenerationStampAreAdoptedAndNothingIsRemade(t *testing.T) { mirror := assignments{ "anchor.stand-in": handedWith("anchor", "stand-in"), - "g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"), - "ace.other": handedWith("ace", "other", "stand-in-api@anchor/stand-in"), + "node-b.app": handedWith("node-b", "app", "stand-in-api@anchor/stand-in"), + "node-a.other": handedWith("node-a", "other", "stand-in-api@anchor/stand-in"), } v := pairVault(t, mirror) - movedRow(t, v, "g14", "app", "the-value-they-share", "20260901T000000-1", OriginMade) - movedRow(t, v, "ace", "other", "the-value-they-share", "20260901T000000-1", OriginMade) + movedRow(t, v, "node-b", "app", "the-value-they-share", "20260901T000000-1", OriginMade) + movedRow(t, v, "node-a", "other", "the-value-they-share", "20260901T000000-1", OriginMade) if o := pass(t, v, standIn); o.Outcome != PairAdopted || o.Generation != 1 { t.Fatalf("stamped rows: %+v", o) } - for _, c := range []string{"provisioner.anchor", "provisioner.g14", "provisioner.ace"} { + for _, c := range []string{"provisioner.anchor", "provisioner.node-b", "provisioner.node-a"} { if got, _, err := asks(v, c, standIn); err != nil || got != "the-value-they-share" { t.Fatalf("%s got %q (%v), not the value it had", c, got, err) } @@ -295,7 +295,7 @@ func TestPairRowsSharingAGenerationStampAreAdoptedAndNothingIsRemade(t *testing. if o := pass(t, v, standIn); o.Outcome != PairUnchanged { t.Fatalf("the pass after the adoption: %+v", o) } - if got, gen, _ := asks(v, "provisioner.g14", standIn); got != "the-value-they-share" || gen != 1 { + if got, gen, _ := asks(v, "provisioner.node-b", standIn); got != "the-value-they-share" || gen != 1 { t.Fatal("the adopted value was remade with no bind or unbind") } } @@ -305,19 +305,19 @@ func TestPairRowsSharingAGenerationStampAreAdoptedAndNothingIsRemade(t *testing. func TestUnstampedPairRowsAreNeverMadeOneSharedValue(t *testing.T) { mirror := assignments{ "anchor.stand-in": handedWith("anchor", "stand-in"), - "g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"), - "ace.other": handedWith("ace", "other", "stand-in-api@anchor/stand-in"), + "node-b.app": handedWith("node-b", "app", "stand-in-api@anchor/stand-in"), + "node-a.other": handedWith("node-a", "other", "stand-in-api@anchor/stand-in"), } v := pairVault(t, mirror) - movedRow(t, v, "g14", "app", "login-of-app", "", OriginMade) - movedRow(t, v, "ace", "other", "login-of-other", "", OriginMade) + movedRow(t, v, "node-b", "app", "login-of-app", "", OriginMade) + movedRow(t, v, "node-a", "other", "login-of-other", "", OriginMade) for i := 0; i < 2; i++ { if o := pass(t, v, standIn); o.Outcome != PairPerPair { t.Fatalf("unstamped rows, pass %d: %+v", i, o) } } - mirror["novox.third"] = handedWith("novox", "third", "stand-in-api@anchor/stand-in") + mirror["node-c.third"] = handedWith("node-c", "third", "stand-in-api@anchor/stand-in") if o := pass(t, v, standIn); o.Outcome != PairPerPair { t.Fatalf("a bind to a provider with logins of their own: %+v", o) } @@ -336,45 +336,45 @@ func TestUnstampedPairRowsAreNeverMadeOneSharedValue(t *testing.T) { // apart, and each consumer's machine is handed only its own; the provider's machine is handed both. func TestARotationRemakesEachPostgresConsumersOwnLoginApart(t *testing.T) { mirror := assignments{ - "novox.postgres": handedWith("novox", "postgres"), - "g14.gitea": handedWith("g14", "gitea", "postgres-database@novox/postgres"), - "ace.umami": handedWith("ace", "umami", "postgres-database@novox/postgres"), + "node-c.postgres": handedWith("node-c", "postgres"), + "node-b.gitea": handedWith("node-b", "gitea", "postgres-database@node-c/postgres"), + "node-a.umami": handedWith("node-a", "umami", "postgres-database@node-c/postgres"), } v := pairVault(t, mirror) - gitea, umami := "pair/novox/postgres-database/g14/gitea", "pair/novox/postgres-database/ace/umami" + gitea, umami := "pair/node-c/postgres-database/node-b/gitea", "pair/node-c/postgres-database/node-a/umami" for name, value := range map[string]string{gitea: "login-of-gitea", umami: "login-of-umami"} { - if _, err := v.keepWith(name, value, "node.novox", "", OriginMade, keepOptions{neverReplace: true, - movedFrom: &MovedFrom{By: "node.novox"}}); err != nil { + if _, err := v.keepWith(name, value, "node.node-c", "", OriginMade, keepOptions{neverReplace: true, + movedFrom: &MovedFrom{By: "node.node-c"}}); err != nil { t.Fatal(err) } } - changed, err := v.Rotate(ControllerCaller, "provision/novox/postgres-database", "person.jochen", "yearly") + changed, err := v.Rotate(ControllerCaller, "provision/node-c/postgres-database", "person.jochen", "yearly") if err != nil || len(changed.Each) != 2 { t.Fatalf("the rotation: %+v (%v)", changed, err) } - ofGitea, _, err := asks(v, "provisioner.g14", gitea) + ofGitea, _, err := asks(v, "provisioner.node-b", gitea) if err != nil { t.Fatalf("gitea's machine was refused its own login: %v", err) } - ofUmami, _, err := asks(v, "provisioner.ace", umami) + ofUmami, _, err := asks(v, "provisioner.node-a", umami) if err != nil { t.Fatalf("umami's machine was refused its own login: %v", err) } if ofGitea == ofUmami || ofGitea == "login-of-gitea" || ofUmami == "login-of-umami" { t.Fatalf("after the rotation gitea holds %q and umami %q: not two new values of their own", ofGitea, ofUmami) } - if _, _, err := asks(v, "provisioner.g14", umami); err == nil { + if _, _, err := asks(v, "provisioner.node-b", umami); err == nil { t.Fatal("gitea's machine was handed umami's login") } - if _, _, err := asks(v, "provisioner.ace", gitea); err == nil { + if _, _, err := asks(v, "provisioner.node-a", gitea); err == nil { t.Fatal("umami's machine was handed gitea's login") } for name, want := range map[string]string{gitea: ofGitea, umami: ofUmami} { - if got, _, err := asks(v, "provisioner.novox", name); err != nil || got != want { + if got, _, err := asks(v, "provisioner.node-c", name); err != nil || got != want { t.Fatalf("the provider's machine got %q for %s (%v)", got, name, err) } } - if _, held, _ := v.Store.Read("provision/novox/postgres-database"); held { + if _, held, _ := v.Store.Read("provision/node-c/postgres-database"); held { t.Fatal("a shared value was made for postgres-database") } } @@ -384,7 +384,7 @@ func TestARotationRemakesEachPostgresConsumersOwnLoginApart(t *testing.T) { func TestAProviderTheVaultHoldsNoRowOfIsNotGuessed(t *testing.T) { mirror := assignments{ "anchor.stand-in": handedWith("anchor", "stand-in"), - "g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"), + "node-b.app": handedWith("node-b", "app", "stand-in-api@anchor/stand-in"), } v := pairVault(t, mirror) if o := pass(t, v, standIn); o.Outcome != PairHeld || !strings.Contains(o.Why, "no plan says whether") { @@ -405,7 +405,7 @@ func TestNoValueIsMadeThatAHolderFilledTheOldWayWouldNeverGet(t *testing.T) { t.Run("an unmoved provider", func(t *testing.T) { mirror := assignments{ "anchor.stand-in": unmoved("anchor", "stand-in"), - "g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"), + "node-b.app": handedWith("node-b", "app", "stand-in-api@anchor/stand-in"), } v := pairVault(t, mirror) if o := pass(t, v, standIn); o.Outcome != PairHeld || !strings.Contains(o.Why, "stand-in on anchor") { @@ -421,29 +421,29 @@ func TestNoValueIsMadeThatAHolderFilledTheOldWayWouldNeverGet(t *testing.T) { t.Run("an unmoved consumer", func(t *testing.T) { mirror := assignments{ "anchor.stand-in": handedWith("anchor", "stand-in"), - "g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"), - "ace.old": unmoved("ace", "old"), + "node-b.app": handedWith("node-b", "app", "stand-in-api@anchor/stand-in"), + "node-a.old": unmoved("node-a", "old"), } v := pairVault(t, mirror) - movedRow(t, v, "g14", "app", "shared", "stamp-1", OriginMade) - movedRow(t, v, "ace", "old", "shared", "stamp-1", OriginMade) + movedRow(t, v, "node-b", "app", "shared", "stamp-1", OriginMade) + movedRow(t, v, "node-a", "old", "shared", "stamp-1", OriginMade) if o := pass(t, v, standIn); o.Outcome != PairAdopted { t.Fatalf("adopting changes no value, so it is not held back: %+v", o) } - mirror["novox.new"] = handedWith("novox", "new", "stand-in-api@anchor/stand-in") + mirror["node-c.new"] = handedWith("node-c", "new", "stand-in-api@anchor/stand-in") o := pass(t, v, standIn) - if o.Outcome != PairHeld || !strings.Contains(o.Why, "old on ace") { + if o.Outcome != PairHeld || !strings.Contains(o.Why, "old on node-a") { t.Fatalf("a bind while a consumer is filled the old way: %+v", o) } - if got, gen, _ := asks(v, "provisioner.g14", standIn); got != "shared" || gen != 1 { + if got, gen, _ := asks(v, "provisioner.node-b", standIn); got != "shared" || gen != 1 { t.Fatal("the value was remade while a consumer filled the old way holds it") } if _, err := v.Rotate(ControllerCaller, standIn, "person.jochen", "why not"); err == nil || - !strings.Contains(err.Error(), "old on ace") { + !strings.Contains(err.Error(), "old on node-a") { t.Fatalf("a rotation while a consumer is filled the old way: %v", err) } // Once it moves, the remake the bind asked for follows. - mirror["ace.old"] = handedWith("ace", "old", "stand-in-api@anchor/stand-in") + mirror["node-a.old"] = handedWith("node-a", "old", "stand-in-api@anchor/stand-in") if o := pass(t, v, standIn); o.Outcome != PairRemade { t.Fatalf("after the consumer moved: %+v", o) } @@ -454,12 +454,12 @@ func TestNoValueIsMadeThatAHolderFilledTheOldWayWouldNeverGet(t *testing.T) { func TestAPassThatCannotReadTheAssignmentsMakesNothing(t *testing.T) { mirror := assignments{ "anchor.stand-in": handedWith("anchor", "stand-in"), - "g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"), + "node-b.app": handedWith("node-b", "app", "stand-in-api@anchor/stand-in"), } v := pairVault(t, mirror) - movedRow(t, v, "g14", "app", "shared", "stamp-1", OriginMade) + movedRow(t, v, "node-b", "app", "shared", "stamp-1", OriginMade) pass(t, v, standIn) - mirror["g14.broken"] = "not json" + mirror["node-b.broken"] = "not json" if _, err := v.PairPass(); err == nil { t.Fatal("a pass over an unreadable assignment said nothing") } @@ -467,7 +467,7 @@ func TestAPassThatCannotReadTheAssignmentsMakesNothing(t *testing.T) { if _, err := v.PairPass(); err == nil { t.Fatal("a pass that could not list the assignments said nothing") } - if _, gen, _ := asks(v, "provisioner.g14", standIn); gen != 1 { + if _, gen, _ := asks(v, "provisioner.node-b", standIn); gen != 1 { t.Fatal("a pass that could not read the assignments remade the value") } } @@ -477,17 +477,17 @@ func TestAPassThatCannotReadTheAssignmentsMakesNothing(t *testing.T) { func TestAPulledInConsumerBindsLikeAnAssignedOne(t *testing.T) { mirror := assignments{ "anchor.stand-in": handedWith("anchor", "stand-in"), - "g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"), + "node-b.app": handedWith("node-b", "app", "stand-in-api@anchor/stand-in"), } v := pairVault(t, mirror) - movedRow(t, v, "g14", "app", "shared", "stamp-1", OriginMade) + movedRow(t, v, "node-b", "app", "shared", "stamp-1", OriginMade) pass(t, v, standIn) - mirror["ace.helper"] = strings.Replace(handedWith("ace", "helper", "stand-in-api@anchor/stand-in"), + mirror["node-a.helper"] = strings.Replace(handedWith("node-a", "helper", "stand-in-api@anchor/stand-in"), `"module":"helper",`, `"module":"helper","required-by":"desk",`, 1) if o := pass(t, v, standIn); o.Outcome != PairRemade { t.Fatalf("a pulled-in consumer binding: %+v", o) } - if _, _, err := asks(v, "provisioner.ace", standIn); err != nil { + if _, _, err := asks(v, "provisioner.node-a", standIn); err != nil { t.Fatalf("the pulled-in consumer's machine was refused: %v", err) } } diff --git a/modules/mesh-vault/cmd/mesh-vault/perholder_bus_test.go b/modules/mesh-vault/cmd/mesh-vault/perholder_bus_test.go index 36fca76d..bc677166 100644 --- a/modules/mesh-vault/cmd/mesh-vault/perholder_bus_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/perholder_bus_test.go @@ -30,13 +30,13 @@ func untoken(token string) string { return strings.ReplaceAll(token, "_", ".") } const busConf = `listen: 127.0.0.1:-1 authorization { users = [ - { user: "novox.mesh-vault", password: "pw", permissions: { - publish: { allow: ["mesh.mod.gitea.call.gitea_agent_token.novox.novox_mesh-vault"] } - subscribe: { allow: ["mesh.seat.mesh-vault.call.get.*", "_INBOX.novox.mesh-vault.>"] } + { user: "node-c.mesh-vault", password: "pw", permissions: { + publish: { allow: ["mesh.mod.gitea.call.gitea_agent_token.node-c.node-c_mesh-vault"] } + subscribe: { allow: ["mesh.seat.mesh-vault.call.get.*", "_INBOX.node-c.mesh-vault.>"] } allow_responses: true } } - { user: "novox.node-tools", password: "pw", permissions: { + { user: "node-c.node-tools", password: "pw", permissions: { publish: { deny: [">"] } - subscribe: { allow: ["mesh.mod.gitea.call.gitea_agent_token.novox.*"] } + subscribe: { allow: ["mesh.mod.gitea.call.gitea_agent_token.node-c.*"] } allow_responses: true } } { user: "provisioner.anchor", password: "pw", permissions: { publish: { allow: ["mesh.seat.mesh-vault.call.get.provisioner_anchor"] } @@ -104,8 +104,8 @@ func forgeOnABus(t *testing.T, rule Askers) (ask func(user, name string) (string // The forge's machine's runtime serves the stand-in issuing tool, naming the caller the subject proves. tool := perHolderProvider(agentTokens, nil) - runtime := connectAs(t, url, "novox.node-tools") - if _, err := runtime.Subscribe("mesh.mod.gitea.call.gitea_agent_token.novox.*", func(m *nats.Msg) { + runtime := connectAs(t, url, "node-c.node-tools") + if _, err := runtime.Subscribe("mesh.mod.gitea.call.gitea_agent_token.node-c.*", func(m *nats.Msg) { parts := strings.Split(m.Subject, ".") var args map[string]any _ = json.Unmarshal(m.Data, &args) @@ -127,13 +127,13 @@ func forgeOnABus(t *testing.T, rule Askers) (ask func(user, name string) (string // the subject proves. Its rule for who may ask would let both clients ask for both values: its rule for a // holder's value is what keeps each to its own. v := newVault(t, rule) - vaultConn := connectAs(t, url, "novox.mesh-vault") + vaultConn := connectAs(t, url, "node-c.mesh-vault") v.Ask = func(key string, body any) (json.RawMessage, error) { call, node, _ := strings.Cut(key, "@") module, tl, _ := strings.Cut(call, ".") raw, _ := json.Marshal(body) msg, err := vaultConn.Request(fmt.Sprintf("mesh.mod.%s.call.%s.%s.%s", module, tl, node, - callerToken("novox.mesh-vault")), raw, 5*time.Second) + callerToken("node-c.mesh-vault")), raw, 5*time.Second) if err != nil { return nil, err } @@ -168,7 +168,7 @@ func forgeOnABus(t *testing.T, rule Askers) (ask func(user, name string) (string _ = vaultConn.Flush() // The controller's `secret issued` for the forge's read tokens, naming both holders. - issued, err := v.TakeIssuedFor(ControllerCaller, "gitea-read", "novox", "gitea", "gitea_agent_token", twoAgents) + issued, err := v.TakeIssuedFor(ControllerCaller, "gitea-read", "node-c", "gitea", "gitea_agent_token", twoAgents) if err != nil { t.Fatal(err) } @@ -222,7 +222,7 @@ func forgeOnABus(t *testing.T, rule Askers) (ask func(user, name string) (string // noneInTheClear fails when an issued value, or its base64, crossed the bus. func noneInTheClear(t *testing.T, all string) { t.Helper() - if !strings.Contains(all, "mesh.mod.gitea.call.gitea_agent_token.novox.novox_mesh-vault") || + if !strings.Contains(all, "mesh.mod.gitea.call.gitea_agent_token.node-c.node-c_mesh-vault") || !strings.Contains(all, "mesh.seat.mesh-vault.call.get.provisioner_anchor") { t.Fatalf("the listener heard nothing of the calls:\n%s", all) } @@ -258,7 +258,7 @@ func TestOnARealBusTwoHoldersOnTwoMachinesEachGetOnlyTheirOwnIssuedValueAndNoneC // is refused another machine's and another module's, sealed to its key and never in the clear. func TestOnARealBusTheRunningRuleHandsAClientTheIssuedValueItsModulesPlanNamesAndNoOther(t *testing.T) { plan := `{"templates":{"source":"x","digest":"y"},"files":[],"provisions":[{"name":"gitea-read",` + - `"provision":"gitea-read","provider":"novox","path":"/var/lib/claude-code/gitea-read.secret"}]}` + `"provision":"gitea-read","provider":"node-c","path":"/var/lib/claude-code/gitea-read.secret"}]}` mirror := assignments{ "anchor.claude-code": `{"node":"anchor","module":"claude-code","provisioning":` + plan + `}`, "laptop.claude-code": `{"node":"laptop","module":"claude-code","provisioning":` + plan + `}`, @@ -274,7 +274,7 @@ func TestOnARealBusTheRunningRuleHandsAClientTheIssuedValueItsModulesPlanNamesAn for _, r := range []struct{ user, name, why string }{ {"provisioner.anchor", laptopsToken, "another machine's holder value"}, {"provisioner.laptop", anchorsToken, "another machine's holder value"}, - {"provisioner.anchor", "provision/novox/gitea-read/anchor/zsh", "another module's, its plan naming it not"}, + {"provisioner.anchor", "provision/node-c/gitea-read/anchor/zsh", "another module's, its plan naming it not"}, } { if got, err := ask(r.user, r.name); err == nil { t.Errorf("%s was handed %s, %s: %q", r.user, r.name, r.why, got) diff --git a/modules/mesh-vault/cmd/mesh-vault/perholder_test.go b/modules/mesh-vault/cmd/mesh-vault/perholder_test.go index 440e8752..e7bc6404 100644 --- a/modules/mesh-vault/cmd/mesh-vault/perholder_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/perholder_test.go @@ -65,8 +65,8 @@ var twoAgents = []Holder{{Node: "anchor", Module: "claude-code"}, {Node: "laptop // The holders' secrets' names in the vault's store. const ( - anchorsToken = "provision/novox/gitea-read/anchor/claude-code" - laptopsToken = "provision/novox/gitea-read/laptop/claude-code" + anchorsToken = "provision/node-c/gitea-read/anchor/claude-code" + laptopsToken = "provision/node-c/gitea-read/laptop/claude-code" ) // bothMayAsk is a stand-in rule that would let both machines' clients ask for both values: the vault's own rule @@ -79,7 +79,7 @@ var bothMayAsk = AllowList{ func forgeMesh(provider func(string, map[string]any) (map[string]any, error)) *aMesh { return &aMesh{tools: map[string]func(string, map[string]any) (map[string]any, error){ - "gitea.gitea_agent_token@novox": provider}} + "gitea.gitea_agent_token@node-c": provider}} } // Two holders on two machines: the vault asks the tool naming both, keeps a value for each, and hands each only to @@ -89,7 +89,7 @@ func TestAProviderIssuesAValueForEachHolderAndEachHolderGetsOnlyItsOwn(t *testin var asked []map[string]any mesh := forgeMesh(perHolderProvider(agentTokens, &asked)) v.Ask = mesh.ask - got, err := v.TakeIssuedFor(ControllerCaller, "gitea-read", "novox", "gitea", "gitea_agent_token", twoAgents) + got, err := v.TakeIssuedFor(ControllerCaller, "gitea-read", "node-c", "gitea", "gitea_agent_token", twoAgents) if err != nil { t.Fatal(err) } @@ -100,7 +100,7 @@ func TestAProviderIssuesAValueForEachHolderAndEachHolderGetsOnlyItsOwn(t *testin got.Holders[0].Generation != 1 || got.Unchanged { t.Fatalf("answered %+v", got) } - if _, held, _ := v.Store.Read("provision/novox/gitea-read"); held { + if _, held, _ := v.Store.Read("provision/node-c/gitea-read"); held { t.Error("a value per holder was also kept as the provision's one credential") } // Each holder gets its own, by its machine's client and by itself under an account of its own. @@ -141,14 +141,14 @@ func TestAProviderIssuesAValueForEachHolderAndEachHolderGetsOnlyItsOwn(t *testin } // The same values again write nothing; one holder's new value changes that holder alone (ADR 0305 §5). - again, err := v.TakeIssuedFor(ControllerCaller, "gitea-read", "novox", "gitea", "gitea_agent_token", twoAgents) + again, err := v.TakeIssuedFor(ControllerCaller, "gitea-read", "node-c", "gitea", "gitea_agent_token", twoAgents) if err != nil || !again.Unchanged || again.Holders[0].Generation != 1 || again.Holders[1].Generation != 1 { t.Errorf("again: %+v %v", again, err) } renewed := map[string]string{"anchor/claude-code": agentTokens["anchor/claude-code"], "laptop/claude-code": "gta_laptop-agent-read-token-0003"} v.Ask = forgeMesh(perHolderProvider(renewed, nil)).ask - moved, err := v.TakeIssuedFor(ControllerCaller, "gitea-read", "novox", "gitea", "gitea_agent_token", twoAgents) + moved, err := v.TakeIssuedFor(ControllerCaller, "gitea-read", "node-c", "gitea", "gitea_agent_token", twoAgents) if err != nil || moved.Unchanged || !moved.Holders[0].Unchanged || moved.Holders[1].Unchanged || moved.Holders[1].Generation != 2 { t.Errorf("renewed: %+v %v", moved, err) @@ -179,7 +179,7 @@ func TestAPerHolderAnswerIsTakenWholeOrNotAtAll(t *testing.T) { "a holder not asked about": func(args map[string]any) map[string]any { return map[string]any{"holders": []any{ map[string]any{"node": "anchor", "module": "claude-code", "sealed": sealedTo(args, "a")}, - map[string]any{"node": "ace", "module": "claude-code", "sealed": sealedTo(args, "b")}}} + map[string]any{"node": "node-a", "module": "claude-code", "sealed": sealedTo(args, "b")}}} }, "a holder twice": func(args map[string]any) map[string]any { return map[string]any{"holders": []any{ @@ -205,7 +205,7 @@ func TestAPerHolderAnswerIsTakenWholeOrNotAtAll(t *testing.T) { v := newVault(t, nil) answer := answer v.Ask = forgeMesh(func(_ string, args map[string]any) (map[string]any, error) { return answer(args), nil }).ask - if _, err := v.TakeIssuedFor(ControllerCaller, "gitea-read", "novox", "gitea", "gitea_agent_token", twoAgents); err == nil { + if _, err := v.TakeIssuedFor(ControllerCaller, "gitea-read", "node-c", "gitea", "gitea_agent_token", twoAgents); err == nil { t.Errorf("%s was taken", what) } if all, _ := v.Store.List(); len(all) != 0 { @@ -221,13 +221,13 @@ func TestAPerHolderAnswerIsTakenWholeOrNotAtAll(t *testing.T) { return map[string]any{"holders": []any{ map[string]any{"node": "anchor", "module": "claude-code", "sealed": sealedTo(args, "a")}}}, nil }).ask - if _, err := v.TakeIssuedFor(ControllerCaller, "gitea-read", "novox", "gitea", "gitea_agent_token", nil); err == nil { + if _, err := v.TakeIssuedFor(ControllerCaller, "gitea-read", "node-c", "gitea", "gitea_agent_token", nil); err == nil { t.Error("values per holder were taken for no holder named") } // A holder the tool did not answer is said and keeps nothing; the others are kept. w := newVault(t, nil) w.Ask = forgeMesh(perHolderProvider(map[string]string{"anchor/claude-code": "only-anchors"}, nil)).ask - got, err := w.TakeIssuedFor(ControllerCaller, "gitea-read", "novox", "gitea", "gitea_agent_token", twoAgents) + got, err := w.TakeIssuedFor(ControllerCaller, "gitea-read", "node-c", "gitea", "gitea_agent_token", twoAgents) if err != nil || len(got.Holders) != 1 || len(got.NotAnswered) != 1 || got.NotAnswered[0] != twoAgents[1] { t.Errorf("a holder not answered: %+v %v", got, err) } @@ -237,7 +237,7 @@ func TestAPerHolderAnswerIsTakenWholeOrNotAtAll(t *testing.T) { // The holders the controller names are names the mesh writes, each once. for _, bad := range [][]Holder{{{Node: "anchor", Module: ""}}, {{Node: "../x", Module: "claude-code"}}, {twoAgents[0], twoAgents[0]}} { - if _, err := w.TakeIssuedFor(ControllerCaller, "gitea-read", "novox", "gitea", "gitea_agent_token", bad); err == nil { + if _, err := w.TakeIssuedFor(ControllerCaller, "gitea-read", "node-c", "gitea", "gitea_agent_token", bad); err == nil { t.Errorf("holders %v were asked for", bad) } } @@ -266,7 +266,7 @@ func TestTheIssuedVerbTakesTheHolders(t *testing.T) { v.Ask = forgeMesh(perHolderProvider(agentTokens, nil)).ask defs := definitions(&Env{Vault: v.Vault}) issued := toolNamed(t, defs, Seat+".issued") - answer, err := issued.runAs(ControllerCaller, map[string]any{"provision": "gitea-read", "provider": "novox", + answer, err := issued.runAs(ControllerCaller, map[string]any{"provision": "gitea-read", "provider": "node-c", "module": "gitea", "tool": "gitea_agent_token", "holders": []any{ map[string]any{"node": "anchor", "module": "claude-code"}, map[string]any{"node": "laptop", "module": "claude-code"}}}) @@ -274,7 +274,7 @@ func TestTheIssuedVerbTakesTheHolders(t *testing.T) { t.Fatalf("%+v %v", answer, err) } for _, bad := range []any{"anchor", []any{"anchor"}, []any{map[string]any{"node": 1}}} { - if _, err := issued.runAs(ControllerCaller, map[string]any{"provision": "gitea-read", "provider": "novox", + if _, err := issued.runAs(ControllerCaller, map[string]any{"provision": "gitea-read", "provider": "node-c", "module": "gitea", "tool": "gitea_agent_token", "holders": bad}); err == nil { t.Errorf("holders %v were read", bad) } diff --git a/modules/mesh-vault/cmd/mesh-vault/providers_test.go b/modules/mesh-vault/cmd/mesh-vault/providers_test.go index 296c13c3..3d9ec782 100644 --- a/modules/mesh-vault/cmd/mesh-vault/providers_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/providers_test.go @@ -7,15 +7,15 @@ import "testing" // for such an entry: naming a provider alone widens nothing. func TestARuleHandsOnlyACredentialThePlanNamesNotAProviderAlone(t *testing.T) { plan := `{"templates":{"source":"x","digest":"y"},"files":[],"provisions":[` + - `{"provision":"postgres-database","provider":"novox","provider-module":"postgres"},` + - `{"name":"gitea-read","provision":"gitea-read","provider":"novox","provider-module":"gitea",` + + `{"provision":"postgres-database","provider":"node-c","provider-module":"postgres"},` + + `{"name":"gitea-read","provision":"gitea-read","provider":"node-c","provider-module":"gitea",` + `"path":"/s/gitea-read.secret"}]}` mirror := assignments{"anchor.app": `{"node":"anchor","module":"app","provisioning":` + plan + `}`} rule := Declared{Read: mirror.read} - if ok, why := rule.May("provisioner.anchor", "provision/novox/gitea-read/anchor/app"); !ok { + if ok, why := rule.May("provisioner.anchor", "provision/node-c/gitea-read/anchor/app"); !ok { t.Fatalf("the credential the plan names was refused: %s", why) } - if ok, _ := rule.May("provisioner.anchor", "provision/novox/postgres-database/anchor/app"); ok { + if ok, _ := rule.May("provisioner.anchor", "provision/node-c/postgres-database/anchor/app"); ok { t.Fatal("a provision the plan names only with its provider was handed out") } } diff --git a/modules/mesh-vault/cmd/mesh-vault/pulled_in_test.go b/modules/mesh-vault/cmd/mesh-vault/pulled_in_test.go index dade00d6..fb19670a 100644 --- a/modules/mesh-vault/cmd/mesh-vault/pulled_in_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/pulled_in_test.go @@ -11,21 +11,21 @@ import ( // running rule hands that node's client what the plan names, as for an assigned module, and nothing else. func TestTheRunningVaultAnswersAMachinesClientForWhatAPulledInModulesPlanNames(t *testing.T) { mirror := assignments{ - "g14.app": `{"node":"g14","module":"app","required-by":"desk","provisioning":` + + "node-b.app": `{"node":"node-b","module":"app","required-by":"desk","provisioning":` + `{"templates":{"source":"x","digest":"y"},"files":[],"secrets":[{"name":"token"}],` + - `"provisions":[{"name":"gitea-read","provision":"gitea-read","provider":"novox"}]}}`, - "g14.kept": `{"node":"g14","module":"kept","required-by":"desk"}`, + `"provisions":[{"name":"gitea-read","provision":"gitea-read","provider":"node-c"}]}}`, + "node-b.kept": `{"node":"node-b","module":"kept","required-by":"desk"}`, } v := newVault(t, Declared{Read: mirror.read}) - for _, name := range []string{"own/g14/app/token", "own/g14/app/other", "own/g14/kept/token", - "provision/novox/gitea-read/g14/app"} { + for _, name := range []string{"own/node-b/app/token", "own/node-b/app/other", "own/node-b/kept/token", + "provision/node-c/gitea-read/node-b/app"} { if _, err := v.Put(name, "value-of-"+name, "the test"); err != nil { t.Fatal(err) } } asker, _ := seal.GenerateKeyPair() - for _, name := range []string{"own/g14/app/token", "provision/novox/gitea-read/g14/app"} { - answer, err := v.Get("provisioner.g14", name, asker.PublicKey) + for _, name := range []string{"own/node-b/app/token", "provision/node-c/gitea-read/node-b/app"} { + answer, err := v.Get("provisioner.node-b", name, asker.PublicKey) if err != nil { t.Fatalf("the machine's client was refused %s, which its pulled-in module's plan names: %v", name, err) } @@ -34,9 +34,9 @@ func TestTheRunningVaultAnswersAMachinesClientForWhatAPulledInModulesPlanNames(t } } for _, r := range []struct{ caller, name, why string }{ - {"provisioner.g14", "own/g14/app/other", "a secret the pulled-in module's plan does not name"}, - {"provisioner.g14", "own/g14/kept/token", "a pulled-in module not handed to the provisioner"}, - {"provisioner.ace", "own/g14/app/token", "another machine's client"}, + {"provisioner.node-b", "own/node-b/app/other", "a secret the pulled-in module's plan does not name"}, + {"provisioner.node-b", "own/node-b/kept/token", "a pulled-in module not handed to the provisioner"}, + {"provisioner.node-a", "own/node-b/app/token", "another machine's client"}, } { if a, err := v.Get(r.caller, r.name, asker.PublicKey); err == nil { t.Errorf("get answered %s (%s asking %s): %+v", r.why, r.caller, r.name, a) diff --git a/modules/mesh-vault/cmd/mesh-vault/retirement_test.go b/modules/mesh-vault/cmd/mesh-vault/retirement_test.go index 83c23abf..4ba8eaec 100644 --- a/modules/mesh-vault/cmd/mesh-vault/retirement_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/retirement_test.go @@ -30,7 +30,7 @@ func newCustody(t *testing.T) custodyAt { bus := &published{} clock := time.Date(2026, 10, 14, 9, 0, 0, 0, time.UTC) c := custodyAt{bus: bus, receives: filepath.Join(dir, "mesh.json"), dir: dir, clock: &clock} - c.Custody = &Custody{Ledger: l, Receives: c.receives, Resource: "secret", Node: "novox", Emit: bus.emit, + c.Custody = &Custody{Ledger: l, Receives: c.receives, Resource: "secret", Node: "node-c", Emit: bus.emit, Now: func() time.Time { return *c.clock }, Log: t.Logf} return c } @@ -249,7 +249,7 @@ func TestTheRetirementWordsAreTheControllers(t *testing.T) { if err := dec.Decode(&w); err != nil { t.Fatalf("a retirement word the controller cannot read: %v: %s", err, outer.Body) } - if w.ProviderNode != "novox" || len(w.Consumers) == 0 || w.Consumers[0].Consumer == "" { + if w.ProviderNode != "node-c" || len(w.Consumers) == 0 || w.Consumers[0].Consumer == "" { t.Errorf("a %s word names no machine or no consumer: %s", w.Change, outer.Body) } seen[w.Change] = true @@ -282,7 +282,7 @@ func TestTheRetirementAnswerIsTheControllers(t *testing.T) { sameWords(t, "the retired answer", raw, "retirement-state.json", "retired.consumer", "retired.retired_at", "retired.why", "retired.access") st := c.Retirement() - if st.RetiresBy != "mark-only" || st.Resource != "secret" || st.Node != "novox" || len(st.Retired) != 4 || + if st.RetiresBy != "mark-only" || st.Resource != "secret" || st.Node != "node-c" || len(st.Retired) != 4 || st.Retired[0].Access != "kept" { t.Errorf("the answer is %+v", st) } diff --git a/modules/mesh-vault/cmd/mesh-vault/rotate_one_test.go b/modules/mesh-vault/cmd/mesh-vault/rotate_one_test.go index 71b9a85d..8f49ce9b 100644 --- a/modules/mesh-vault/cmd/mesh-vault/rotate_one_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/rotate_one_test.go @@ -9,18 +9,18 @@ import ( "testing" ) -// postgresLogins is a vault holding a login each for gitea on g14 and umami on ace, from postgres on novox. +// postgresLogins is a vault holding a login each for gitea on node-b and umami on node-a, from postgres on node-c. func postgresLogins(t *testing.T) (testVault, string, string) { t.Helper() v := pairVault(t, assignments{ - "novox.postgres": handedWith("novox", "postgres"), - "g14.gitea": handedWith("g14", "gitea", "postgres-database@novox/postgres"), - "ace.umami": handedWith("ace", "umami", "postgres-database@novox/postgres"), + "node-c.postgres": handedWith("node-c", "postgres"), + "node-b.gitea": handedWith("node-b", "gitea", "postgres-database@node-c/postgres"), + "node-a.umami": handedWith("node-a", "umami", "postgres-database@node-c/postgres"), }) - gitea, umami := "pair/novox/postgres-database/g14/gitea", "pair/novox/postgres-database/ace/umami" + gitea, umami := "pair/node-c/postgres-database/node-b/gitea", "pair/node-c/postgres-database/node-a/umami" for name, value := range map[string]string{gitea: "login-of-gitea", umami: "login-of-umami"} { - if _, err := v.keepWith(name, value, "node.novox", "", OriginMade, keepOptions{neverReplace: true, - movedFrom: &MovedFrom{By: "node.novox"}}); err != nil { + if _, err := v.keepWith(name, value, "node.node-c", "", OriginMade, keepOptions{neverReplace: true, + movedFrom: &MovedFrom{By: "node.node-c"}}); err != nil { t.Fatal(err) } } @@ -28,18 +28,18 @@ func postgresLogins(t *testing.T) (testVault, string, string) { } func TestARotationNamingOneConsumerRemakesThatConsumersLoginAlone(t *testing.T) { - for _, one := range []Narrow{{Consumer: "g14"}, {ConsumerModule: "gitea"}, {Consumer: "g14", ConsumerModule: "gitea"}} { + for _, one := range []Narrow{{Consumer: "node-b"}, {ConsumerModule: "gitea"}, {Consumer: "node-b", ConsumerModule: "gitea"}} { v, gitea, umami := postgresLogins(t) before := changedSaid(t, v, umami, "") - changed, err := v.RotateFor(ControllerCaller, "provision/novox/postgres-database", one, "person.jochen", - "suspected on g14") + changed, err := v.RotateFor(ControllerCaller, "provision/node-c/postgres-database", one, "person.jochen", + "suspected on node-b") if err != nil || len(changed.Each) != 1 || changed.Each[0].Name != gitea { t.Fatalf("%+v: the rotation %+v (%v)", one, changed, err) } - if got, _, err := asks(v, "provisioner.g14", gitea); err != nil || got == "login-of-gitea" { + if got, _, err := asks(v, "provisioner.node-b", gitea); err != nil || got == "login-of-gitea" { t.Fatalf("%+v: gitea's login was not remade: %q (%v)", one, got, err) } - if got, gen, err := asks(v, "provisioner.ace", umami); err != nil || got != "login-of-umami" || gen != 1 { + if got, gen, err := asks(v, "provisioner.node-a", umami); err != nil || got != "login-of-umami" || gen != 1 { t.Fatalf("%+v: umami's login was touched: %q generation %d (%v)", one, got, gen, err) } if changedSaid(t, v, umami, "") != before { @@ -50,13 +50,13 @@ func TestARotationNamingOneConsumerRemakesThatConsumersLoginAlone(t *testing.T) func TestARotationNamingAConsumerThatHoldsNoLoginChangesNothing(t *testing.T) { v, gitea, umami := postgresLogins(t) - _, err := v.RotateFor(ControllerCaller, "provision/novox/postgres-database", Narrow{Consumer: "g14", + _, err := v.RotateFor(ControllerCaller, "provision/node-c/postgres-database", Narrow{Consumer: "node-b", ConsumerModule: "umami"}, "person.jochen", "suspected") - if err == nil || !strings.Contains(err.Error(), "umami on g14") { + if err == nil || !strings.Contains(err.Error(), "umami on node-b") { t.Fatalf("a consumer holding no login was not refused by name: %v", err) } for name, want := range map[string]string{gitea: "login-of-gitea", umami: "login-of-umami"} { - if got, _, _ := asks(v, "provisioner.novox", name); got != want { + if got, _, _ := asks(v, "provisioner.node-c", name); got != want { t.Fatalf("%s changed on a refused rotation", name) } } @@ -67,20 +67,20 @@ func TestARotationNamingAConsumerThatHoldsNoLoginChangesNothing(t *testing.T) { func TestASharedValueIsRotatedForEveryHolderAndNeverForOneConsumer(t *testing.T) { v := pairVault(t, assignments{ "anchor.stand-in": handedWith("anchor", "stand-in"), - "g14.app": handedWith("g14", "app", "stand-in-api@anchor/stand-in"), - "ace.other": handedWith("ace", "other", "stand-in-api@anchor/stand-in"), + "node-b.app": handedWith("node-b", "app", "stand-in-api@anchor/stand-in"), + "node-a.other": handedWith("node-a", "other", "stand-in-api@anchor/stand-in"), }) - movedRow(t, v, "g14", "app", "the-value-they-share", "20260901T000000-1", OriginMade) - movedRow(t, v, "ace", "other", "the-value-they-share", "20260901T000000-1", OriginMade) + movedRow(t, v, "node-b", "app", "the-value-they-share", "20260901T000000-1", OriginMade) + movedRow(t, v, "node-a", "other", "the-value-they-share", "20260901T000000-1", OriginMade) if o := pass(t, v, standIn); o.Outcome != PairAdopted { t.Fatalf("stamped rows: %+v", o) } - if _, err := v.RotateFor(ControllerCaller, standIn, Narrow{Consumer: "g14"}, "person.jochen", "suspected"); err == nil || + if _, err := v.RotateFor(ControllerCaller, standIn, Narrow{Consumer: "node-b"}, "person.jochen", "suspected"); err == nil || !strings.Contains(err.Error(), "every holder") { t.Fatalf("a shared value was rotated for one consumer: %v", err) } - if got, gen, _ := asks(v, "provisioner.g14", standIn); got != "the-value-they-share" || gen != 1 { + if got, gen, _ := asks(v, "provisioner.node-b", standIn); got != "the-value-they-share" || gen != 1 { t.Fatal("a refused rotation changed the shared value") } @@ -89,7 +89,7 @@ func TestASharedValueIsRotatedForEveryHolderAndNeverForOneConsumer(t *testing.T) t.Fatalf("the rotation: %+v (%v)", changed, err) } var seen string - for _, c := range []string{"provisioner.anchor", "provisioner.g14", "provisioner.ace"} { + for _, c := range []string{"provisioner.anchor", "provisioner.node-b", "provisioner.node-a"} { got, gen, err := asks(v, c, standIn) if err != nil || got == "the-value-they-share" || gen != 2 || (seen != "" && got != seen) { t.Fatalf("%s got %q generation %d (%v): not the one new value", c, got, gen, err) @@ -103,17 +103,17 @@ func TestASharedValueIsRotatedForEveryHolderAndNeverForOneConsumer(t *testing.T) func TestARotationOfAModulesOwnSecretNamesNoConsumer(t *testing.T) { v := newVault(t, nil) - if _, err := v.RotateFor(ControllerCaller, "own/g14/app/key", Narrow{Consumer: "g14"}, "person.jochen", "x"); err == nil { + if _, err := v.RotateFor(ControllerCaller, "own/node-b/app/key", Narrow{Consumer: "node-b"}, "person.jochen", "x"); err == nil { t.Fatal("a module's own secret was rotated with a consumer named") } } func TestTheRotateToolTakesTheConsumerAndItsModule(t *testing.T) { - n, err := narrowNamed(map[string]any{"consumer": "g14", "consumer_module": "gitea"}) - if err != nil || n != (Narrow{Consumer: "g14", ConsumerModule: "gitea"}) { + n, err := narrowNamed(map[string]any{"consumer": "node-b", "consumer_module": "gitea"}) + if err != nil || n != (Narrow{Consumer: "node-b", ConsumerModule: "gitea"}) { t.Fatalf("%+v (%v)", n, err) } - if _, err := narrowNamed(map[string]any{"consumer": "g14/x"}); err == nil { + if _, err := narrowNamed(map[string]any{"consumer": "node-b/x"}); err == nil { t.Fatal("a consumer that is not a name was taken") } } diff --git a/modules/mesh-vault/cmd/mesh-vault/testdata/retirement-state.json b/modules/mesh-vault/cmd/mesh-vault/testdata/retirement-state.json index 600bf79f..120d1a75 100644 --- a/modules/mesh-vault/cmd/mesh-vault/testdata/retirement-state.json +++ b/modules/mesh-vault/cmd/mesh-vault/testdata/retirement-state.json @@ -1,6 +1,6 @@ { "resource": "secret", - "node": "novox", + "node": "node-c", "held": [ "a" ], diff --git a/modules/mesh-vault/cmd/mesh-vault/testdata/retirement-word.json b/modules/mesh-vault/cmd/mesh-vault/testdata/retirement-word.json index 57792616..dc12a166 100644 --- a/modules/mesh-vault/cmd/mesh-vault/testdata/retirement-word.json +++ b/modules/mesh-vault/cmd/mesh-vault/testdata/retirement-word.json @@ -1,6 +1,6 @@ { "provider": "secret", - "provider-node": "novox", + "provider-node": "node-c", "change": "waiting", "consumers": [ { diff --git a/modules/mesh-vault/cmd/mesh-vault/tools_test.go b/modules/mesh-vault/cmd/mesh-vault/tools_test.go index dee060cb..7684bb58 100644 --- a/modules/mesh-vault/cmd/mesh-vault/tools_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/tools_test.go @@ -72,7 +72,7 @@ func TestSecretExportAnswersTheMeshsExport(t *testing.T) { if got.(map[string]any)["available"] != false { t.Errorf("no export said %v", got) } - doc := `{"export":1,"operator-key":"b3A=","fingerprint":"sha256:f","kept":[{"node":"g14","module":"dunst","name":"token","kind":"own","origin":"made","sealed":"c2VhbGVk","key":"b3A=","made-at":"2026-10-01T00:00:00Z"}],"unrecoverable":[{"node":"ace","module":"x","name":"y"}]}` + doc := `{"export":1,"operator-key":"b3A=","fingerprint":"sha256:f","kept":[{"node":"node-b","module":"dunst","name":"token","kind":"own","origin":"made","sealed":"c2VhbGVk","key":"b3A=","made-at":"2026-10-01T00:00:00Z"}],"unrecoverable":[{"node":"node-a","module":"x","name":"y"}]}` _ = os.WriteFile(filepath.Join(root, "export.json"), []byte(doc), 0o600) got, _ = export.Run(map[string]any{}) a := got.(map[string]any) @@ -122,17 +122,17 @@ func TestSecretHoldersAndVerifySayFingerprintsOnly(t *testing.T) { // The seat's verb, called as the runtime calls it: the caller is the one the runtime proved, never an // argument. func TestTheGetVerbTakesItsCallerFromTheRuntime(t *testing.T) { - v := newVault(t, AllowList{"g14.node-provisioner": {"pair/postgres/gitea"}}) + v := newVault(t, AllowList{"node-b.node-provisioner": {"pair/postgres/gitea"}}) if _, err := v.Put("pair/postgres/gitea", "x", "the test"); err != nil { t.Fatal(err) } asker, _ := seal.GenerateKeyPair() get := toolNamed(t, definitions(&Env{Vault: v.Vault}), Seat+".get") // No runtime proved a caller here, so the call is unproven whatever the arguments say. - if _, err := get.Run(map[string]any{"name": "pair/postgres/gitea", "public_key": asker.PublicKey, "caller": "g14.node-provisioner"}); err == nil { + if _, err := get.Run(map[string]any{"name": "pair/postgres/gitea", "public_key": asker.PublicKey, "caller": "node-b.node-provisioner"}); err == nil { t.Error("get answered a caller named in its arguments") } - answer, err := get.runAs("g14.node-provisioner", map[string]any{"name": "pair/postgres/gitea", "public_key": asker.PublicKey}) + answer, err := get.runAs("node-b.node-provisioner", map[string]any{"name": "pair/postgres/gitea", "public_key": asker.PublicKey}) if err != nil { t.Fatal(err) } diff --git a/modules/mesh-vault/cmd/mesh-vault/vault_test.go b/modules/mesh-vault/cmd/mesh-vault/vault_test.go index db21a44a..f11267cf 100644 --- a/modules/mesh-vault/cmd/mesh-vault/vault_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/vault_test.go @@ -164,13 +164,13 @@ func TestNoBucketHoldsASecret(t *testing.T) { // And what the vault publishes while it holds, changes and hands out secrets carries none of them, in // the clear or sealed. - v := newVault(t, AllowList{"g14.node-provisioner": {"pair/postgres/gitea"}}) + v := newVault(t, AllowList{"node-b.node-provisioner": {"pair/postgres/gitea"}}) value := "the-password-nobody-may-see" if _, err := v.Put("pair/postgres/gitea", value, "the test"); err != nil { t.Fatal(err) } asker, _ := seal.GenerateKeyPair() - answer, err := v.Get("g14.node-provisioner", "pair/postgres/gitea", asker.PublicKey) + answer, err := v.Get("node-b.node-provisioner", "pair/postgres/gitea", asker.PublicKey) if err != nil { t.Fatal(err) } @@ -188,7 +188,7 @@ func TestNoBucketHoldsASecret(t *testing.T) { // only with the vault's own key. func TestEverySecretIsEncryptedAtRest(t *testing.T) { v := newVault(t, nil) - values := map[string]string{"own/g14/dunst/token": "tok-1-plain", "pair/postgres/gitea": "pw-2-plain"} + values := map[string]string{"own/node-b/dunst/token": "tok-1-plain", "pair/postgres/gitea": "pw-2-plain"} for name, value := range values { if _, err := v.Put(name, value, "the test"); err != nil { t.Fatal(err) @@ -219,18 +219,18 @@ func TestEverySecretIsEncryptedAtRest(t *testing.T) { // ---- no private key is accepted ------------------------------------------------------------------------- func TestNoPrivateKeyIsAccepted(t *testing.T) { - v := newVault(t, AllowList{"g14.node-provisioner": {"pair/postgres/gitea"}}) + v := newVault(t, AllowList{"node-b.node-provisioner": {"pair/postgres/gitea"}}) keys, _ := seal.GenerateKeyPair() ssh := "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAA\n-----END OPENSSH PRIVATE KEY-----\n" rsa := "-----BEGIN RSA PRIVATE KEY-----\nMIIBOgIBAAJBAK\n-----END RSA PRIVATE KEY-----\n" // Not as a secret to hold: a private key stays where it was made (ADR 0113 §2). for _, value := range []string{keys.PrivateKey, ssh, rsa, "prefix " + keys.PrivateKey} { - if _, err := v.Put("own/g14/sshd/host", value, "the test"); err == nil { + if _, err := v.Put("own/node-b/sshd/host", value, "the test"); err == nil { t.Errorf("the vault took a private key as a secret: %.40q", value) } } - if _, ok, _ := v.Store.Read("own/g14/sshd/host"); ok { + if _, ok, _ := v.Store.Read("own/node-b/sshd/host"); ok { t.Error("a refused private key was kept all the same") } @@ -240,7 +240,7 @@ func TestNoPrivateKeyIsAccepted(t *testing.T) { } raw32 := base64.StdEncoding.EncodeToString(make([]byte, 32)) for _, key := range []string{keys.PrivateKey, ssh, raw32, "", "not a key"} { - if _, err := v.Get("g14.node-provisioner", "pair/postgres/gitea", key); err == nil { + if _, err := v.Get("node-b.node-provisioner", "pair/postgres/gitea", key); err == nil { t.Errorf("get sealed an answer to %.40q, which is not a PEM public key", key) } } @@ -274,7 +274,7 @@ func TestNoPrivateKeyIsAccepted(t *testing.T) { func TestEverySecretHasAnOperatorSealedCopy(t *testing.T) { v := newVault(t, nil) - values := map[string]string{"own/g14/dunst/token": "a", "pair/postgres/gitea": "b"} + values := map[string]string{"own/node-b/dunst/token": "a", "pair/postgres/gitea": "b"} for name, value := range values { if _, err := v.Put(name, value, "the test"); err != nil { t.Fatal(err) @@ -323,7 +323,7 @@ func TestNoOperatorKeyKeepsNothing(t *testing.T) { store, _ := OpenStore(filepath.Join(dir, "store")) own, _ := OwnKey(filepath.Join(dir, "state"), store) v := &Vault{Store: store, Own: own, Emit: (&published{}).emit, Now: time.Now, Log: t.Logf} - if _, err := v.Put("own/g14/dunst/token", "x", "the test"); err == nil || !strings.Contains(err.Error(), "operator key") { + if _, err := v.Put("own/node-b/dunst/token", "x", "the test"); err == nil || !strings.Contains(err.Error(), "operator key") { t.Fatalf("a secret was kept with no operator key to seal its copy to: %v", err) } if all, _ := store.List(); len(all) != 0 { @@ -334,16 +334,16 @@ func TestNoOperatorKeyKeepsNothing(t *testing.T) { // ---- get answers only an allowed asker, sealed to its key ----------------------------------------------- func TestGetAnswersOnlyAnAllowedAskerSealedToItsKey(t *testing.T) { - v := newVault(t, AllowList{"g14.node-provisioner": {"pair/postgres/gitea"}}) + v := newVault(t, AllowList{"node-b.node-provisioner": {"pair/postgres/gitea"}}) if _, err := v.Put("pair/postgres/gitea", "the-value", "the test"); err != nil { t.Fatal(err) } - if _, err := v.Put("own/ace/dunst/token", "another", "the test"); err != nil { + if _, err := v.Put("own/node-a/dunst/token", "another", "the test"); err != nil { t.Fatal(err) } asker, _ := seal.GenerateKeyPair() - answer, err := v.Get("g14.node-provisioner", "pair/postgres/gitea", asker.PublicKey) + answer, err := v.Get("node-b.node-provisioner", "pair/postgres/gitea", asker.PublicKey) if err != nil { t.Fatal(err) } @@ -362,11 +362,11 @@ func TestGetAnswersOnlyAnAllowedAskerSealedToItsKey(t *testing.T) { } refusals := []struct{ caller, name, why string }{ - {"ace.node-provisioner", "pair/postgres/gitea", "an asker not on the list"}, - {"g14.node-provisioner", "own/ace/dunst/token", "a secret the asker is not allowed"}, + {"node-a.node-provisioner", "pair/postgres/gitea", "an asker not on the list"}, + {"node-b.node-provisioner", "own/node-a/dunst/token", "a secret the asker is not allowed"}, {stdio.Unproven, "pair/postgres/gitea", "a call whose caller the runtime did not prove"}, {"", "pair/postgres/gitea", "no caller at all"}, - {"g14.node-provisioner", "pair/postgres/nothing", "a secret the vault does not hold"}, + {"node-b.node-provisioner", "pair/postgres/nothing", "a secret the vault does not hold"}, } for _, r := range refusals { if a, err := v.Get(r.caller, r.name, asker.PublicKey); err == nil { @@ -382,7 +382,7 @@ func TestAVaultWithNoRuleAnswersNobody(t *testing.T) { t.Fatal(err) } asker, _ := seal.GenerateKeyPair() - for _, caller := range []string{"provisioner.g14", "novox.mesh-provisioner", "controller", "person.jochen", "novox.node-tools"} { + for _, caller := range []string{"provisioner.node-b", "node-c.mesh-provisioner", "controller", "person.jochen", "node-c.node-tools"} { if _, err := v.Get(caller, "pair/postgres/gitea", asker.PublicKey); err == nil { t.Errorf("a vault with no rule answered %s", caller) } @@ -404,44 +404,44 @@ func (a assignments) read(key string) ([]byte, error) { // refusal is recorded with why. func TestTheRunningVaultAnswersAMachinesClientForWhatItsPlanNames(t *testing.T) { mirror := assignments{ - "g14.dunst": `{"node":"g14","module":"dunst","assigned":"2026-10-14T20:00:00Z","provisioning":` + + "node-b.dunst": `{"node":"node-b","module":"dunst","assigned":"2026-10-14T20:00:00Z","provisioning":` + `{"templates":{"source":"x","digest":"y"},"files":[],"secrets":[{"name":"token"}]}}`, - "g14.picom": `{"node":"g14","module":"picom","assigned":"2026-10-14T20:00:00Z"}`, - "ace.dunst": `{"node":"ace","module":"dunst","assigned":"2026-10-14T20:00:00Z","provisioning":{"secrets":[{"name":"token"}]}}`, - "g14.liar": `{"node":"ace","module":"liar","provisioning":{"secrets":[{"name":"token"}]}}`, - "g14.unparsed": `not json`, + "node-b.picom": `{"node":"node-b","module":"picom","assigned":"2026-10-14T20:00:00Z"}`, + "node-a.dunst": `{"node":"node-a","module":"dunst","assigned":"2026-10-14T20:00:00Z","provisioning":{"secrets":[{"name":"token"}]}}`, + "node-b.liar": `{"node":"node-a","module":"liar","provisioning":{"secrets":[{"name":"token"}]}}`, + "node-b.unparsed": `not json`, } v := newVault(t, Declared{Read: mirror.read}) - for _, name := range []string{"own/g14/dunst/token", "own/g14/dunst/other", "own/g14/picom/token", - "own/ace/dunst/token", "own/g14/liar/token", "own/g14/unparsed/token", "provision/novox/postgres", - "own/g14/absent/token"} { + for _, name := range []string{"own/node-b/dunst/token", "own/node-b/dunst/other", "own/node-b/picom/token", + "own/node-a/dunst/token", "own/node-b/liar/token", "own/node-b/unparsed/token", "provision/node-c/postgres", + "own/node-b/absent/token"} { if _, err := v.Put(name, "value-of-"+name, "the test"); err != nil { t.Fatal(err) } } asker, _ := seal.GenerateKeyPair() - answer, err := v.Get("provisioner.g14", "own/g14/dunst/token", asker.PublicKey) + answer, err := v.Get("provisioner.node-b", "own/node-b/dunst/token", asker.PublicKey) if err != nil { t.Fatalf("the machine's client was refused the secret its module's plan names: %v", err) } - if got, err := seal.Open(answer.Sealed, asker.PrivateKey); err != nil || got != "value-of-own/g14/dunst/token" { + if got, err := seal.Open(answer.Sealed, asker.PrivateKey); err != nil || got != "value-of-own/node-b/dunst/token" { t.Fatalf("the answer opens to %q (%v)", got, err) } refusals := []struct{ caller, name, why string }{ - {"provisioner.g14", "own/g14/dunst/other", "a secret the plan does not name"}, - {"provisioner.g14", "own/g14/picom/token", "a module not handed to the provisioner"}, - {"provisioner.g14", "own/ace/dunst/token", "another machine's secret"}, - {"provisioner.ace", "own/g14/dunst/token", "another machine's client"}, - {"provisioner.g14", "own/g14/absent/token", "a module not assigned there"}, - {"provisioner.g14", "own/g14/liar/token", "an assignment whose value names another machine"}, - {"provisioner.g14", "own/g14/unparsed/token", "an assignment that is not the controller's"}, - {"provisioner.g14", "provision/novox/postgres", "a provision's credential the vault made for nobody there"}, - {"g14.node-tools", "own/g14/dunst/token", "the tool runner's account, which an agent shares"}, - {"g14.dunst", "own/g14/dunst/token", "a module's own account, until issue 569"}, - {"controller", "own/g14/dunst/token", "the controller"}, - {"provisioner.", "own/g14/dunst/token", "a client naming no machine"}, + {"provisioner.node-b", "own/node-b/dunst/other", "a secret the plan does not name"}, + {"provisioner.node-b", "own/node-b/picom/token", "a module not handed to the provisioner"}, + {"provisioner.node-b", "own/node-a/dunst/token", "another machine's secret"}, + {"provisioner.node-a", "own/node-b/dunst/token", "another machine's client"}, + {"provisioner.node-b", "own/node-b/absent/token", "a module not assigned there"}, + {"provisioner.node-b", "own/node-b/liar/token", "an assignment whose value names another machine"}, + {"provisioner.node-b", "own/node-b/unparsed/token", "an assignment that is not the controller's"}, + {"provisioner.node-b", "provision/node-c/postgres", "a provision's credential the vault made for nobody there"}, + {"node-b.node-tools", "own/node-b/dunst/token", "the tool runner's account, which an agent shares"}, + {"node-b.dunst", "own/node-b/dunst/token", "a module's own account, until issue 569"}, + {"controller", "own/node-b/dunst/token", "the controller"}, + {"provisioner.", "own/node-b/dunst/token", "a client naming no machine"}, } for _, r := range refusals { if a, err := v.Get(r.caller, r.name, asker.PublicKey); err == nil { @@ -473,7 +473,7 @@ func TestTheRunningVaultAnswersAMachinesClientForWhatItsPlanNames(t *testing.T) // one credential. func TestTheRunningVaultAnswersAMachinesClientForAnIssuedValueItsPlanNames(t *testing.T) { plan := `{"templates":{"source":"x","digest":"y"},"files":[],` + - `"provisions":[{"name":"gitea-read","provision":"gitea-read","provider":"novox","path":"/s/gitea-read.secret"}]}` + `"provisions":[{"name":"gitea-read","provision":"gitea-read","provider":"node-c","path":"/s/gitea-read.secret"}]}` mirror := assignments{ "anchor.claude-code": `{"node":"anchor","module":"claude-code","provisioning":` + plan + `}`, "laptop.claude-code": `{"node":"laptop","module":"claude-code","provisioning":` + plan + `}`, @@ -481,10 +481,10 @@ func TestTheRunningVaultAnswersAMachinesClientForAnIssuedValueItsPlanNames(t *te "anchor.picom": `{"node":"anchor","module":"picom"}`, } v := newVault(t, Declared{Read: mirror.read}) - for _, name := range []string{anchorsToken, laptopsToken, "provision/novox/gitea-read/anchor/zsh", - "provision/novox/gitea-read/anchor/picom", "provision/ace/gitea-read/anchor/claude-code", - "provision/novox/other/anchor/claude-code", "provision/novox/gitea-read", - "provision/novox/gitea-read/anchor/absent"} { + for _, name := range []string{anchorsToken, laptopsToken, "provision/node-c/gitea-read/anchor/zsh", + "provision/node-c/gitea-read/anchor/picom", "provision/node-a/gitea-read/anchor/claude-code", + "provision/node-c/other/anchor/claude-code", "provision/node-c/gitea-read", + "provision/node-c/gitea-read/anchor/absent"} { if _, err := v.Put(name, "value-of-"+name, "the test"); err != nil { t.Fatal(err) } @@ -500,12 +500,12 @@ func TestTheRunningVaultAnswersAMachinesClientForAnIssuedValueItsPlanNames(t *te refusals := []struct{ caller, name, why string }{ {"provisioner.anchor", laptopsToken, "another machine's holder value"}, {"provisioner.laptop", anchorsToken, "another machine's holder value, the other way"}, - {"provisioner.anchor", "provision/novox/gitea-read/anchor/zsh", "another module's, whose plan names it not"}, - {"provisioner.anchor", "provision/novox/gitea-read/anchor/picom", "a module not handed to the provisioner"}, - {"provisioner.anchor", "provision/novox/gitea-read/anchor/absent", "a module not assigned there"}, - {"provisioner.anchor", "provision/ace/gitea-read/anchor/claude-code", "another provider's"}, - {"provisioner.anchor", "provision/novox/other/anchor/claude-code", "a provision the plan names not"}, - {"provisioner.anchor", "provision/novox/gitea-read", "the provision's one credential"}, + {"provisioner.anchor", "provision/node-c/gitea-read/anchor/zsh", "another module's, whose plan names it not"}, + {"provisioner.anchor", "provision/node-c/gitea-read/anchor/picom", "a module not handed to the provisioner"}, + {"provisioner.anchor", "provision/node-c/gitea-read/anchor/absent", "a module not assigned there"}, + {"provisioner.anchor", "provision/node-a/gitea-read/anchor/claude-code", "another provider's"}, + {"provisioner.anchor", "provision/node-c/other/anchor/claude-code", "a provision the plan names not"}, + {"provisioner.anchor", "provision/node-c/gitea-read", "the provision's one credential"}, {"anchor.node-tools", anchorsToken, "the tool runner's account, which an agent shares"}, {"anchor.claude-code", anchorsToken, "the module's own account, until issue 569"}, } @@ -521,7 +521,7 @@ func TestTheRunningVaultAnswersAMachinesClientForAnIssuedValueItsPlanNames(t *te // SPKI PEM, and opens the answer with its private half as PKCS #8 — no second key on the node, and no NaCl // in the vault's answers. This is the path V4 builds on. func TestANodesSealingKeyOpensTheAnswer(t *testing.T) { - v := newVault(t, AllowList{"g14.node-provisioner": {"pair/postgres/gitea"}}) + v := newVault(t, AllowList{"node-b.node-provisioner": {"pair/postgres/gitea"}}) if _, err := v.Put("pair/postgres/gitea", "for-the-node", "the test"); err != nil { t.Fatal(err) } @@ -535,7 +535,7 @@ func TestANodesSealingKeyOpensTheAnswer(t *testing.T) { spki, _ := x509.MarshalPKIXPublicKey(pubKey) askWith := string(pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: spki})) - answer, err := v.Get("g14.node-provisioner", "pair/postgres/gitea", askWith) + answer, err := v.Get("node-b.node-provisioner", "pair/postgres/gitea", askWith) if err != nil { t.Fatal(err) } @@ -552,13 +552,13 @@ func TestANodesSealingKeyOpensTheAnswer(t *testing.T) { func TestSecretChangedCarriesNoValue(t *testing.T) { v := newVault(t, nil) - if _, err := v.Put("pair/postgres/gitea", "first-value", "g14.mesh-vault-test"); err != nil { + if _, err := v.Put("pair/postgres/gitea", "first-value", "node-b.mesh-vault-test"); err != nil { t.Fatal(err) } if _, err := v.Put("pair/postgres/gitea", "second-value", "person.jochen"); err != nil { t.Fatal(err) } - if _, err := v.Mint("own/g14/dunst/token", "the vault"); err != nil { + if _, err := v.Mint("own/node-b/dunst/token", "the vault"); err != nil { t.Fatal(err) } var changed []map[string]any @@ -589,7 +589,7 @@ func TestSecretChangedCarriesNoValue(t *testing.T) { if changed[1]["by"] != "person.jochen" || changed[1]["generation"] != 2 { t.Errorf("the second change says %v", changed[1]) } - minted, _, _ := v.Store.Read("own/g14/dunst/token") + minted, _, _ := v.Store.Read("own/node-b/dunst/token") mintedValue, _ := seal.Open(minted.AtRest, v.Own.PrivateKey) for _, said := range v.bus.raw { for _, value := range []string{"first-value", "second-value", mintedValue} { @@ -712,23 +712,23 @@ func TestANewOperatorKeyFailingPartwayIsFinished(t *testing.T) { // Who was handed which secret, and when, and who was refused, is in the vault's own store. func TestWhoWasHandedWhatIsRecordedInTheStore(t *testing.T) { - v := newVault(t, AllowList{"g14.node-provisioner": {"pair/postgres/gitea"}}) + v := newVault(t, AllowList{"node-b.node-provisioner": {"pair/postgres/gitea"}}) if _, err := v.Put("pair/postgres/gitea", "the-value", "the test"); err != nil { t.Fatal(err) } asker, _ := seal.GenerateKeyPair() - if _, err := v.Get("g14.node-provisioner", "pair/postgres/gitea", asker.PublicKey); err != nil { + if _, err := v.Get("node-b.node-provisioner", "pair/postgres/gitea", asker.PublicKey); err != nil { t.Fatal(err) } - _, _ = v.Get("ace.node-provisioner", "pair/postgres/gitea", asker.PublicKey) + _, _ = v.Get("node-a.node-provisioner", "pair/postgres/gitea", asker.PublicKey) handed, err := v.Store.Handed(10) if err != nil || len(handed) != 2 { t.Fatalf("%v %v", handed, err) } - if handed[1].To != "g14.node-provisioner" || handed[1].Outcome != "handed" || handed[1].Generation != 1 || handed[1].At.IsZero() { + if handed[1].To != "node-b.node-provisioner" || handed[1].Outcome != "handed" || handed[1].Generation != 1 || handed[1].At.IsZero() { t.Errorf("the hand-out is recorded as %+v", handed[1]) } - if handed[0].To != "ace.node-provisioner" || handed[0].Outcome != "refused" || handed[0].Why == "" { + if handed[0].To != "node-a.node-provisioner" || handed[0].Outcome != "refused" || handed[0].Why == "" { t.Errorf("the refusal is recorded as %+v", handed[0]) } raw, _ := os.ReadFile(filepath.Join(v.dir, "store", "handed.jsonl")) @@ -806,7 +806,7 @@ func TestResealFinishesWhatIsPending(t *testing.T) { // A secret is not handed out when who was handed it cannot be recorded. func TestNoHandOutWithoutItsRecord(t *testing.T) { - v := newVault(t, AllowList{"g14.node-provisioner": {"pair/postgres/gitea"}}) + v := newVault(t, AllowList{"node-b.node-provisioner": {"pair/postgres/gitea"}}) if _, err := v.Put("pair/postgres/gitea", "x", "the test"); err != nil { t.Fatal(err) } @@ -814,7 +814,7 @@ func TestNoHandOutWithoutItsRecord(t *testing.T) { t.Fatal(err) } asker, _ := seal.GenerateKeyPair() - if a, err := v.Get("g14.node-provisioner", "pair/postgres/gitea", asker.PublicKey); err == nil { + if a, err := v.Get("node-b.node-provisioner", "pair/postgres/gitea", asker.PublicKey); err == nil { t.Fatalf("handed out with no record of it: %+v", a) } } @@ -823,7 +823,7 @@ func TestNoHandOutWithoutItsRecord(t *testing.T) { func TestAnArbitraryAskFillsNoRecord(t *testing.T) { v := newVault(t, nil) asker, _ := seal.GenerateKeyPair() - for _, ask := range [][2]string{{"g14.x", strings.Repeat("junk ", 1000)}, {"g14.x", "../../etc"}, + for _, ask := range [][2]string{{"node-b.x", strings.Repeat("junk ", 1000)}, {"node-b.x", "../../etc"}, {"not a bus user!", "pair/a"}, {strings.Repeat("a", 300), "pair/a"}} { _, _ = v.Get(ask[0], ask[1], asker.PublicKey) } @@ -838,7 +838,7 @@ func TestTheRecordOfHandOutsIsBounded(t *testing.T) { v.Store.HandedMax = 2000 asker, _ := seal.GenerateKeyPair() for i := 0; i < 500; i++ { - _, _ = v.Get("g14.flood", "pair/postgres/gitea", asker.PublicKey) + _, _ = v.Get("node-b.flood", "pair/postgres/gitea", asker.PublicKey) } var total int64 files, _ := filepath.Glob(filepath.Join(v.dir, "store", "handed.jsonl*")) @@ -858,7 +858,7 @@ func TestTheRecordOfHandOutsIsBounded(t *testing.T) { if v.Store.Rolled() == 0 { t.Error("rolling was not counted") } - if h, _ := v.Store.Handed(5); len(h) != 5 || h[0].To != "g14.flood" { + if h, _ := v.Store.Handed(5); len(h) != 5 || h[0].To != "node-b.flood" { t.Errorf("the newest are not read back: %+v", h) } } From 7ad9e531d49606cfa147fdedf3faa7d85a8d4f12 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 22 Oct 2026 21:31:08 +0200 Subject: [PATCH 5/5] Name no node in cups's, nats's, mesh-watcher's, mesh-files's, dunst's and desk-channel's fixtures (issue 1838) --- modules/cups/README.md | 2 +- modules/cups/cmd/cups-tools/cups_test.go | 14 +++++++------- modules/desk-channel/cmd/desk-channel/desk_test.go | 14 +++++++------- modules/dunst/cmd/dunst-tools/actions_test.go | 8 ++++---- modules/mesh-files/cmd/mesh-files/files_test.go | 6 +++--- modules/mesh-files/cmd/mesh-files/transfer_test.go | 6 +++--- .../mesh-watcher/cmd/mesh-watcher/watcher_test.go | 8 ++++---- modules/nats/cmd/nats-tools/tools_test.go | 8 ++++---- 8 files changed, 33 insertions(+), 33 deletions(-) diff --git a/modules/cups/README.md b/modules/cups/README.md index 927b5099..5baad0a4 100644 --- a/modules/cups/README.md +++ b/modules/cups/README.md @@ -22,7 +22,7 @@ Research 027 asked for "`cups` with the printer's driver". Measured on 2026-10-0 | workstation | queue | device | prints through | driver package installed | |---|---|---|---|---| | laptop | `Brother` (MFC-L8690CDW) | `ipp://` on the LAN | **IPP Everywhere, driverless** | `brother-mfc-l8690cdw` (AUR), unused | -| desktop | `Brother_MFC_Novox` (default) | `ipp://` on the LAN | **IPP Everywhere, driverless** | `brother-mfc-l8390cdw` and its `-debug` (AUR), unused | +| desktop | `Brother_MFC_NodeC` (default) | `ipp://` on the LAN | **IPP Everywhere, driverless** | `brother-mfc-l8390cdw` and its `-debug` (AUR), unused | | desktop | `Kanjuro` (Canon PIXMA MG4200) | `cnijnet:` | the vendor's PPD and filter | `cnijfilter-mg4200` 3.80 (AUR) | **Both Brother queues already print without a vendor driver.** CUPS's own IPP Everywhere support, diff --git a/modules/cups/cmd/cups-tools/cups_test.go b/modules/cups/cmd/cups-tools/cups_test.go index d58561a0..989f9c6a 100644 --- a/modules/cups/cmd/cups-tools/cups_test.go +++ b/modules/cups/cmd/cups-tools/cups_test.go @@ -36,13 +36,13 @@ func theDesktop(t *testing.T, more func(line string, c Cmd) (Result, bool)) *fak case "lpstat -r": return ok("scheduler is running\n") case "lpstat -d": - return ok("system default destination: Brother_MFC_Novox\n") + return ok("system default destination: Brother_MFC_NodeC\n") case "lpstat -p": - return ok("printer Brother_MFC_Novox is idle. enabled since Mon Jun 29 21:34:30 2026\n" + + return ok("printer Brother_MFC_NodeC is idle. enabled since Mon Jun 29 21:34:30 2026\n" + "printer Kanjuro disabled since Sun Jun 9 11:16:03 2024 -\n\tPaused\n") case "lpstat -a": - return ok("Brother_MFC_Novox accepting requests since Mon Jun 29 21:34:30 2026\nKanjuro not accepting requests since Sun Jun 9 11:16:03 2024 -\n\tRejecting Jobs\n") - case "lpoptions -p Brother_MFC_Novox": + return ok("Brother_MFC_NodeC accepting requests since Mon Jun 29 21:34:30 2026\nKanjuro not accepting requests since Sun Jun 9 11:16:03 2024 -\n\tRejecting Jobs\n") + case "lpoptions -p Brother_MFC_NodeC": return ok(`copies=1 device-uri=ipp://192.0.2.171/ipp/port1 finishings=3 marker-levels=70,100,8,100 marker-low-levels=10,10,10,10 marker-names='Black\ Toner\ Cartridge,Cyan\ Toner\ Cartridge,Magenta\ Toner\ Cartridge,Yellow\ Toner\ Cartridge' marker-types=toner,toner,toner,toner printer-is-shared=false printer-make-and-model='Printer - IPP Everywhere' printer-state-reasons=none`) case "lpoptions -p Kanjuro": return ok(`device-uri=cnijnet:/18-0C-AC-B0-62-83 printer-is-shared=false printer-make-and-model='Canon MG4200 series Ver.3.80' printer-state-reasons=paused`) @@ -54,7 +54,7 @@ func theDesktop(t *testing.T, more func(line string, c Cmd) (Result, bool)) *fak func TestPrintersReadsStateDeviceModelAndSupplies(t *testing.T) { theDesktop(t, nil) got, err := Printers() - if err != nil || len(got.Printers) != 2 || got.Default != "Brother_MFC_Novox" || got.Scheduler != "scheduler is running" { + if err != nil || len(got.Printers) != 2 || got.Default != "Brother_MFC_NodeC" || got.Scheduler != "scheduler is running" { t.Fatalf("%+v %v", got, err) } b, k := got.Printers[0], got.Printers[1] @@ -186,11 +186,11 @@ func TestDefaultReadsAndSetsThroughSudo(t *testing.T) { return Result{}, false }) got, err := Default("") - if err != nil || got["default"] != "Brother_MFC_Novox" { + if err != nil || got["default"] != "Brother_MFC_NodeC" { t.Fatalf("%v %v", got, err) } got, err = Default("Kanjuro") - if err != nil || got["default"] != "Kanjuro" || got["was"] != "Brother_MFC_Novox" { + if err != nil || got["default"] != "Kanjuro" || got["was"] != "Brother_MFC_NodeC" { t.Fatalf("%v %v", got, err) } if l := f.lines(); l[len(l)-1] != "sudo -n lpadmin -d Kanjuro" { diff --git a/modules/desk-channel/cmd/desk-channel/desk_test.go b/modules/desk-channel/cmd/desk-channel/desk_test.go index b4ad168f..fda76807 100644 --- a/modules/desk-channel/cmd/desk-channel/desk_test.go +++ b/modules/desk-channel/cmd/desk-channel/desk_test.go @@ -133,7 +133,7 @@ func TestANotifierThatStartedAgainIsShownNothingFromMemory(t *testing.T) { d, shown, said, store := newDesk(t, "laptop") d.Paused("laptop", false) d.SayStanding() - take(t, d, asks.Show, asks.Message{Handle: "open", Title: "2 failed services on shanks", + take(t, d, asks.Show, asks.Message{Handle: "open", Title: "2 failed services on node-d", Buttons: []asks.Button{{Label: "Silence for a week", Ticket: "t-open"}}}) take(t, d, asks.Show, asks.Message{Handle: "silenced", Title: "Agent-home shrank", Buttons: []asks.Button{{Label: "Silence for a week", Ticket: "t-silenced"}}}) @@ -162,7 +162,7 @@ func TestANotifierThatStartedAgainIsShownNothingFromMemory(t *testing.T) { t.Fatalf("the standing after the start: %d said, last %s", len(got)-standings, got[len(got)-1]) } // The router says the open one again under its handle: in place of its notification, with its answers. - take(t, d, asks.Show, asks.Message{Handle: "open", Title: "2 failed services on shanks", + take(t, d, asks.Show, asks.Message{Handle: "open", Title: "2 failed services on node-d", Buttons: []asks.Button{{Label: "Silence for a week", Ticket: "t-open"}}}) last := (*shown)[len(*shown)-1] if len(*shown) != before+1 || last.args["replace_id"] != openID || last.args["actions"] == nil { @@ -329,7 +329,7 @@ func TestItRunsAsItsOwnAccount(t *testing.T) { // was not shown; a message under a new handle replaces nothing. func TestAMessageSaidAgainUnderItsHandleReplacesItsNotification(t *testing.T) { d, shown, _, store := newDesk(t, "laptop", "desktop") - take(t, d, asks.Send, asks.Message{Handle: "m1", Title: "2 failed services on shanks"}) + take(t, d, asks.Send, asks.Message{Handle: "m1", Title: "2 failed services on node-d"}) take(t, d, asks.Send, asks.Message{Handle: "m2", Title: "another problem"}) if len(*shown) != 4 { t.Fatalf("shown %d", len(*shown)) @@ -342,7 +342,7 @@ func TestAMessageSaidAgainUnderItsHandleReplacesItsNotification(t *testing.T) { first := store["m1"].On // The desk now names a third machine as well. d.Machines = func() []string { return []string{"laptop", "desktop", "third"} } - take(t, d, asks.Show, asks.Message{Handle: "m1", Title: "Still open: 2 failed services on shanks", Urgent: true, + take(t, d, asks.Show, asks.Message{Handle: "m1", Title: "Still open: 2 failed services on node-d", Urgent: true, Buttons: []asks.Button{{Label: "Silence for a week", Ticket: "t1"}}}) again := (*shown)[4:] if len(again) != 3 { @@ -367,7 +367,7 @@ func TestAMessageSaidAgainUnderItsHandleReplacesItsNotification(t *testing.T) { // later edit or clearing still reaches it; failing everywhere, it is said to the router as failed. func TestAFailedReplaceKeepsTheNotificationItWasToReplace(t *testing.T) { d, shown, said, store := newDesk(t, "laptop", "desktop") - take(t, d, asks.Send, asks.Message{Handle: "m1", Title: "2 failed services on shanks"}) + take(t, d, asks.Send, asks.Message{Handle: "m1", Title: "2 failed services on node-d"}) first := store["m1"].On notify := d.Notify d.Notify = func(machine string, args map[string]any) (json.RawMessage, error) { @@ -376,12 +376,12 @@ func TestAFailedReplaceKeepsTheNotificationItWasToReplace(t *testing.T) { } return notify(machine, args) } - take(t, d, asks.Send, asks.Message{Handle: "m1", Title: "Still open: 2 failed services on shanks"}) + take(t, d, asks.Send, asks.Message{Handle: "m1", Title: "Still open: 2 failed services on node-d"}) if got := store["m1"].On["desktop"]; got != first["desktop"] { t.Fatalf("the desktop's notification %d was forgotten: %v", first["desktop"], store["m1"].On) } d.Notify = func(string, map[string]any) (json.RawMessage, error) { return nil, errors.New("away") } - take(t, d, asks.Send, asks.Message{Handle: "m1", Title: "Now urgent: 2 failed services on shanks"}) + take(t, d, asks.Send, asks.Message{Handle: "m1", Title: "Now urgent: 2 failed services on node-d"}) if len(said[asks.IntakeSubject(asks.FailedWhat, Kind)]) != 1 { t.Fatalf("shown nowhere, and not said as failed") } diff --git a/modules/dunst/cmd/dunst-tools/actions_test.go b/modules/dunst/cmd/dunst-tools/actions_test.go index 70a472ce..c62a1f0c 100644 --- a/modules/dunst/cmd/dunst-tools/actions_test.go +++ b/modules/dunst/cmd/dunst-tools/actions_test.go @@ -17,7 +17,7 @@ func TestANotificationsChosenAnswerIsSaidAsAnEvent(t *testing.T) { withBus(t) bin := fakeBinaries(t, map[string]string{"notify-send": `for a in "$@"; do printf '[%s]' "$a"; done > "$LOG"; echo 42; sleep 0.2; echo "$CHOSEN"`}) t.Setenv("LOG", filepath.Join(bin, "log")) - t.Setenv("MESH_NODE", "g14") + t.Setenv("MESH_NODE", "node-b") var mu sync.Mutex var said []map[string]any before := emit @@ -58,7 +58,7 @@ func TestANotificationsChosenAnswerIsSaidAsAnEvent(t *testing.T) { time.Sleep(20 * time.Millisecond) } mu.Lock() - if len(said) != 1 || said[0]["token"] != "c3d4" || said[0]["id"] != 42 || said[0]["machine"] != "g14" { + if len(said) != 1 || said[0]["token"] != "c3d4" || said[0]["id"] != 42 || said[0]["machine"] != "node-b" { t.Fatalf("said %v", said) } said = nil @@ -96,7 +96,7 @@ func TestActionsAreRefusedForWhatTheyCannotBe(t *testing.T) { // **A bundle that started says so**, so the operator channel shows again the answers lost with the one // before. func TestABundleThatStartedSaysSo(t *testing.T) { - t.Setenv("MESH_NODE", "g14") + t.Setenv("MESH_NODE", "node-b") var said []string before := emit emit = func(event string, body any) error { @@ -105,7 +105,7 @@ func TestABundleThatStartedSaysSo(t *testing.T) { } t.Cleanup(func() { emit = before }) sayStarted() - if len(said) != 1 || said[0] != "started map[machine:g14]" { + if len(said) != 1 || said[0] != "started map[machine:node-b]" { t.Fatalf("%v", said) } } diff --git a/modules/mesh-files/cmd/mesh-files/files_test.go b/modules/mesh-files/cmd/mesh-files/files_test.go index d21eee72..e98cb386 100644 --- a/modules/mesh-files/cmd/mesh-files/files_test.go +++ b/modules/mesh-files/cmd/mesh-files/files_test.go @@ -97,7 +97,7 @@ func testFiles(t *testing.T) *rig { r.Root = g.root r.Now = func() time.Time { return time.Date(2026, 10, 16, 12, 0, 0, 0, time.UTC) } seq := 0 - g.Files = &Files{Reader: r, State: filepath.Join(dir, "state"), Owned: map[string]string{}, Node: "shanks", + g.Files = &Files{Reader: r, State: filepath.Join(dir, "state"), Owned: map[string]string{}, Node: "node-d", OwnerOf: func(p string) (Ident, error) { if id, ok := g.owners[p]; ok { return id, nil @@ -344,7 +344,7 @@ func TestAnOwnedPathIsRefusedNamingItsOwnerAndPassesWithAnOverride(t *testing.T) if len(lines) != 1 || lines[0]["override"] != ov.Override { t.Errorf("log: %v", lines) } - if len(g.told) != 1 || !strings.HasPrefix(g.told[0], "mesh-files on shanks | ") || + if len(g.told) != 1 || !strings.HasPrefix(g.told[0], "mesh-files on node-d | ") || !strings.Contains(g.told[0], ov.Override) || !strings.Contains(g.told[0], "mesh-hosts (node-hostname)") || !strings.Contains(g.told[0], "person.jochen") { t.Errorf("told: %v", g.told) @@ -384,7 +384,7 @@ func TestACredentialFileIsRefusedToReadButMayBeCopied(t *testing.T) { func TestATargetOnAnotherNodeIsRefused(t *testing.T) { g := testFiles(t) write(t, g.path("a"), "x") - for _, to := range []string{"ace:/tmp/a", "novox:/etc/hosts"} { + for _, to := range []string{"node-a:/tmp/a", "node-c:/etc/hosts"} { for _, run := range []func() error{ func() error { _, err := g.Copy(by, g.path("a"), to); return err }, func() error { _, err := g.Move(by, g.path("a"), to); return err }, diff --git a/modules/mesh-files/cmd/mesh-files/transfer_test.go b/modules/mesh-files/cmd/mesh-files/transfer_test.go index ffc71864..e2fbda8c 100644 --- a/modules/mesh-files/cmd/mesh-files/transfer_test.go +++ b/modules/mesh-files/cmd/mesh-files/transfer_test.go @@ -80,7 +80,7 @@ func TestUploadSendsTheFileUnderItsHash(t *testing.T) { g, st, lv := transferRig(t) body := bytes.Repeat([]byte("a document\n"), 1000) write(t, g.path("home/ops/doc.pdf"), string(body)) - ans, err := g.Upload(g.path("home/ops/doc.pdf"), "mesh-shanks-brother", "") + ans, err := g.Upload(g.path("home/ops/doc.pdf"), "mesh-node-d-brother", "") if err != nil { t.Fatal(err) } @@ -88,10 +88,10 @@ func TestUploadSendsTheFileUnderItsHash(t *testing.T) { if ans.Key != want || ans.SHA256 != want || ans.Size != int64(len(body)) { t.Fatalf("answer %+v", ans) } - if !bytes.Equal(st.objects["/mesh-shanks-brother/"+want], body) { + if !bytes.Equal(st.objects["/mesh-node-d-brother/"+want], body) { t.Fatal("the store did not receive exactly the file's bytes") } - if len(lv.asks) != 1 || lv.asks[0] != "put mesh-shanks-brother/"+want { + if len(lv.asks) != 1 || lv.asks[0] != "put mesh-node-d-brother/"+want { t.Fatalf("link asks %v", lv.asks) } } diff --git a/modules/mesh-watcher/cmd/mesh-watcher/watcher_test.go b/modules/mesh-watcher/cmd/mesh-watcher/watcher_test.go index a335af11..27832284 100644 --- a/modules/mesh-watcher/cmd/mesh-watcher/watcher_test.go +++ b/modules/mesh-watcher/cmd/mesh-watcher/watcher_test.go @@ -31,7 +31,7 @@ func (c *clock) pass(d time.Duration) { c.t = c.t.Add(d) } func watcher(t *testing.T) (*Watcher, *fakeTelegram, *clock) { c := &clock{t: time.Date(2026, 10, 6, 12, 0, 0, 0, time.UTC)} tg := &fakeTelegram{} - return NewWatcher(tg, c.now, t.Logf, "ace"), tg, c + return NewWatcher(tg, c.now, t.Logf, "node-a"), tg, c } // beatEvery has the controller's doctor run, and the bus answer, every five minutes up to d. @@ -204,11 +204,11 @@ func TestNotGivenATokenIsBlind(t *testing.T) { func TestOnTheControlNodeItSaysItIsMisplaced(t *testing.T) { w, _, _ := watcher(t) - w.Placed([]string{"novox"}) - if st := w.Status("listening"); st.Verdict != "ok: watching" || st.Control != "novox" { + w.Placed([]string{"node-c"}) + if st := w.Status("listening"); st.Verdict != "ok: watching" || st.Control != "node-c" { t.Fatalf("%+v", st) } - w.Placed([]string{"ace"}) + w.Placed([]string{"node-a"}) if st := w.Status("listening"); !strings.HasPrefix(st.Verdict, "MISPLACED") { t.Fatalf("%+v", st) } diff --git a/modules/nats/cmd/nats-tools/tools_test.go b/modules/nats/cmd/nats-tools/tools_test.go index bd0e7d0f..2311ad13 100644 --- a/modules/nats/cmd/nats-tools/tools_test.go +++ b/modules/nats/cmd/nats-tools/tools_test.go @@ -135,8 +135,8 @@ func TestClosedConnectionsArePerUserAndNameAndSayWhichWereDropped(t *testing.T) const closed = `{"connections":[ {"cid":10,"name":"mesh-controller verb conditions","authorized_user":"controller","start":"2026-10-08T14:12:00Z","stop":"2026-10-08T14:12:01Z","reason":"Client Closed"}, {"cid":11,"name":"mesh-controller verb conditions","authorized_user":"controller","start":"2026-10-08T14:13:00Z","stop":"2026-10-08T14:13:03Z","reason":"Client Closed"}, - {"cid":12,"name":"ace.node-tools","authorized_user":"ace.node-tools","start":"2026-10-08T13:00:00Z","stop":"2026-10-08T14:14:00Z","reason":"Stale Connection"}, - {"cid":13,"name":"ace.node-tools","authorized_user":"ace.node-tools","start":"2026-10-08T14:14:05Z","stop":"2026-10-08T14:15:00Z","reason":"Read Error"}, + {"cid":12,"name":"node-a.node-tools","authorized_user":"node-a.node-tools","start":"2026-10-08T13:00:00Z","stop":"2026-10-08T14:14:00Z","reason":"Stale Connection"}, + {"cid":13,"name":"node-a.node-tools","authorized_user":"node-a.node-tools","start":"2026-10-08T14:14:05Z","stop":"2026-10-08T14:15:00Z","reason":"Read Error"}, {"cid":5,"name":"old","authorized_user":"controller","start":"2026-10-08T10:00:00Z","stop":"2026-10-08T10:00:01Z","reason":"Client Closed"}, {"cid":14,"name":"","start":"2026-10-08T14:16:00Z","stop":"2026-10-08T14:16:00Z","reason":"Authentication Failure"}]}` now, _ := time.Parse(time.RFC3339, "2026-10-08T14:20:00Z") @@ -157,7 +157,7 @@ func TestClosedConnectionsArePerUserAndNameAndSayWhichWereDropped(t *testing.T) c.Names[0].Name != "mesh-controller verb conditions" || c.Names[0].Lived != 3 { t.Errorf("the controller's: %+v", c) } - tools := byUser["ace.node-tools"] + tools := byUser["node-a.node-tools"] if tools.Closed != 2 || tools.Dropped != 2 || tools.Names[0].Reasons["Stale Connection"] != 1 { t.Errorf("the runtime's: %+v", tools) } @@ -168,7 +168,7 @@ func TestClosedConnectionsArePerUserAndNameAndSayWhichWereDropped(t *testing.T) t.Error("a record older than the window does not reach back the whole window") } narrowed, _ := ClosedConnections([]byte(closed), now, 1, "node-tools") - if got := narrowed["users"].([]ClosedUser); len(got) != 1 || got[0].User != "ace.node-tools" { + if got := narrowed["users"].([]ClosedUser); len(got) != 1 || got[0].User != "node-a.node-tools" { t.Errorf("narrowed: %+v", got) } }