diff --git a/modules/betterbird/README.md b/modules/betterbird/README.md index bbc081d1..d1253dc7 100644 --- a/modules/betterbird/README.md +++ b/modules/betterbird/README.md @@ -1,6 +1,6 @@ # betterbird -Betterbird, the mail and calendar client of g14 and shanks (a Thunderbird fork, with the operator's +Betterbird, the mail and calendar client of node-b and node-d (a Thunderbird fork, with the operator's Exchange calendar through the Owl add-on), as a module (novox/hq issue 345, issue 586, ADR 0208, ADR 0316, ADR 0317, ADR 0329, to-be 56). It requires `x11-display`, so it is assigned only where a display server is held on the same machine. It installs Betterbird from a pinned upstream release, ships Owl with it through @@ -58,7 +58,7 @@ reading the new range there (ADR 0316 §8). **The policy** turns Betterbird's own updater off (`DisableAppUpdate`, which Betterbird's update check honours) and installs Owl into every profile from `file:///opt/betterbird/owl/owl.xpi` as `force_installed`, with `updates_disabled`. A profile that already runs another Owl keeps it: the policy -installs the pinned one where Owl is missing. A newer Owl in the profile (g14 runs 1.5.7) is said as a +installs the pinned one where Owl is missing. A newer Owl in the profile (node-b runs 1.5.7) is said as a fact by `betterbird_status`; Owl installed by policy cannot be removed in Betterbird, so the remedy is moving the pin. An older one is a finding of `betterbird_check`, with the same remedy. @@ -323,10 +323,10 @@ question. ## What changes when it is pushed -The module is assigned to shanks today (look-only, from issue 345's first part); g14 runs Betterbird +The module is assigned to node-d today (look-only, from issue 345's first part); node-b runs Betterbird outside the mesh. With this version, a push to a node (each waits for the operator: `upgrade: record`): -| | on a node with the community package (g14, shanks) | +| | on a node with the community package (node-b, node-d) | |---|---| | the package | `betterbird-bin` removed (quit Betterbird first) | | `/opt/betterbird` | the mesh's 153.4.0esr-bb10, in the same place, so the same profile opens | diff --git a/modules/betterbird/cmd/betterbird-tools/config_test.go b/modules/betterbird/cmd/betterbird-tools/config_test.go index c92a7288..c8efe5c1 100644 --- a/modules/betterbird/cmd/betterbird-tools/config_test.go +++ b/modules/betterbird/cmd/betterbird-tools/config_test.go @@ -412,13 +412,13 @@ func TestKeepProposesANodeLayerThroughTheController(t *testing.T) { f.write(profileDir+"/prefs.js", `user_pref("mail.uifontsize", 16);`+"\n"+`user_pref("mail.spam.manualMark", true);`+"\n") oldNode, oldAsk := nodeName, asker t.Cleanup(func() { nodeName, asker = oldNode, oldAsk }) - nodeName = func() string { return "shanks" } + nodeName = func() string { return "node-d" } var asked []map[string]any asker = func(v string, a any) (json.RawMessage, error) { args := a.(map[string]any) asked = append(asked, args) if args["propose"] == nil { - return json.RawMessage(`{"ok": true, "output": "{\"prefs\": {\"calendar.alarms.playsound\": false}, \"identities\": {\"mail\": {\"account\": \"mail\"}}}\n set at the terminal\nbetterbird on shanks, every value"}`), nil + return json.RawMessage(`{"ok": true, "output": "{\"prefs\": {\"calendar.alarms.playsound\": false}, \"identities\": {\"mail\": {\"account\": \"mail\"}}}\n set at the terminal\nbetterbird on node-d, every value"}`), nil } return json.RawMessage(`{"ok": true, "output": "proposed: p-1"}`), nil } @@ -427,7 +427,7 @@ func TestKeepProposesANodeLayerThroughTheController(t *testing.T) { if err != nil { t.Fatal(err) } - if len(asked) != 2 || asked[0]["node"] != "shanks" || asked[1]["node"] != "shanks" || asked[1]["propose"] != "true" || + if len(asked) != 2 || asked[0]["node"] != "node-d" || asked[1]["node"] != "node-d" || asked[1]["propose"] != "true" || asked[1]["module"] != "betterbird" { t.Fatalf("the node's layer read, then proposed: %v", asked) } diff --git a/modules/betterbird/cmd/betterbird-tools/derive_test.go b/modules/betterbird/cmd/betterbird-tools/derive_test.go index 549e98d9..ea1651f5 100644 --- a/modules/betterbird/cmd/betterbird-tools/derive_test.go +++ b/modules/betterbird/cmd/betterbird-tools/derive_test.go @@ -12,11 +12,11 @@ import ( // ADR 0329 §10, §12: derived from every desktop node's profile, laid out per layer, and proposed one layer at a // time, carrying the layer as it stands. -// derivingMesh is two desktop nodes, g14 (this one, f) and shanks (f2), and a server that holds no Betterbird, as the +// derivingMesh is two desktop nodes, node-b (this one, f) and node-d (f2), and a server that holds no Betterbird, as the // controller answers them; layers are the controller's layers, open the proposals that wait. type derivingMesh struct { t *testing.T - shanks *fake + nodeD *fake layers map[string]map[string]any open bool proposed []map[string]any @@ -35,17 +35,17 @@ func (d *derivingMesh) ask(key string, body any) (json.RawMessage, error) { } switch { case key == "seat:mesh-controller.nodes": - return answer(true, `[{"name": "g14"}, {"name": "novox"}, {"name": "shanks"}]`) + return answer(true, `[{"name": "node-b"}, {"name": "node-c"}, {"name": "node-d"}]`) case key == "seat:mesh-controller.node": - if args["node"] == "novox" { - return answer(true, "novox\n assigned: postgres, nats\n") + if args["node"] == "node-c" { + return answer(true, "node-c\n assigned: postgres, nats\n") } return answer(true, fmt.Sprintf("%s\n last heard from here\n assigned: adwaita, betterbird, dunst\n", args["node"])) - case key == "betterbird.betterbird_derive@shanks": + case key == "betterbird.betterbird_derive@node-d": if d.asleep { return nil, errors.New("nats: no responders available for request") } - here, err := d.shanks.deriveHere(stringsOf(args["kinds"])) + here, err := d.nodeD.deriveHere(stringsOf(args["kinds"])) if err != nil { d.t.Fatal(err) } @@ -53,10 +53,10 @@ func (d *derivingMesh) ask(key string, body any) (json.RawMessage, error) { return json.Marshal(map[string]any{"content": []any{map[string]any{"type": "text", "text": string(text)}}}) case key == "seat:mesh-controller.settings" && args["proposals"] == "true": if d.open { - return answer(true, "sab12 set betterbird on the whole mesh (accounts, identities)\n by g14.node-tools at 2026-10-13 01:00; fingerprint ab12\n waiting for the operator until 2026-10-14 01:00\n"+ - "scd34 set mounts on shanks (sources)\n by g14.node-tools at 2026-10-11 00:05; fingerprint dd0b\n chosen: done\n") + return answer(true, "sab12 set betterbird on the whole mesh (accounts, identities)\n by node-b.node-tools at 2026-10-13 01:00; fingerprint ab12\n waiting for the operator until 2026-10-14 01:00\n"+ + "scd34 set mounts on node-d (sources)\n by node-b.node-tools at 2026-10-11 00:05; fingerprint dd0b\n chosen: done\n") } - return answer(true, "scd34 set mounts on shanks (sources)\n by g14.node-tools; fingerprint dd0b\n chosen: done\n") + return answer(true, "scd34 set mounts on node-d (sources)\n by node-b.node-tools; fingerprint dd0b\n chosen: done\n") case key == "seat:mesh-controller.settings" && args["propose"] == "true": d.proposed = append(d.proposed, args) return answer(true, "proposal sab12: Set the settings of betterbird?\n fingerprint ab12") @@ -107,23 +107,23 @@ func TestDeriveLaysEachEntryOutPerLayerAndProposesOneLayerAtATime(t *testing.T) f2 := newFake(t) f2.profileWithAccounts() f2.profileWithConfiguration() - // shanks holds the same accounts and calendars, another signature, another tag colour and a calendar of its own. + // node-d holds the same accounts and calendars, another signature, another tag colour and a calendar of its own. f2.write(profileDir+"/prefs.js", strings.NewReplacer(`"Regards"`, `"Cheers"`, `"#FF0000"`, `"#CC0000"`).Replace(f2.read(profileDir+"/prefs.js"))+ `user_pref("calendar.registry.s1.type", "caldav");`+"\n"+ `user_pref("calendar.registry.s1.uri", "https://dav.example.org/cal/standup/");`+"\n"+ `user_pref("calendar.registry.s1.name", "Standup");`+"\n") f2.declareAccounts(adoptable) - mesh := &derivingMesh{t: t, shanks: f2, layers: map[string]map[string]any{"": {"accounts": map[string]any{"mail": "as approved"}}}} + mesh := &derivingMesh{t: t, nodeD: f2, layers: map[string]map[string]any{"": {"accounts": map[string]any{"mail": "as approved"}}}} oldNode, oldAsk := nodeName, asker t.Cleanup(func() { nodeName, asker = oldNode, oldAsk }) - nodeName = func() string { return "g14" } + nodeName = func() string { return "node-b" } asker = mesh.ask a, err := f.Derive(nil, false, false, nil, "") if err != nil { t.Fatal(err) } - if !reflect.DeepEqual(a.From, []string{"g14", "shanks"}) || len(a.NotHeard) != 0 { + if !reflect.DeepEqual(a.From, []string{"node-b", "node-d"}) || len(a.NotHeard) != 0 { t.Fatalf("derived from the nodes holding Betterbird: %v %v", a.From, a.NotHeard) } whole := mustJSON(a) @@ -134,9 +134,9 @@ func TestDeriveLaysEachEntryOutPerLayerAndProposesOneLayerAtATime(t *testing.T) } cals, _ := mw[kindCalendars].(map[string]any) if cals["home"] == nil || cals["standup"] != nil { - t.Errorf("a calendar both hold is mesh-wide, one only shanks holds is not: %v", cals) + t.Errorf("a calendar both hold is mesh-wide, one only node-d holds is not: %v", cals) } - if sh := mustJSON(a.Layers["shanks"]); !strings.Contains(sh, "https://dav.example.org/cal/standup/") { + if sh := mustJSON(a.Layers["node-d"]); !strings.Contains(sh, "https://dav.example.org/cal/standup/") { t.Errorf("an entry on one node only goes into that node's layer: %s", sh) } tags, _ := mw[kindTags].(map[string]any) @@ -147,8 +147,8 @@ func TestDeriveLaysEachEntryOutPerLayerAndProposesOneLayerAtATime(t *testing.T) for _, d := range a.Differences { diffs[d.Kind+"/"+d.Entry+"/"+d.Field] = d } - if d := diffs["identities/mail/signature"]; d.Node != "shanks" || mustJSON(d.There) != `["Cheers"]` { - t.Errorf("the answer lists the field shanks holds differently: %+v", a.Differences) + if d := diffs["identities/mail/signature"]; d.Node != "node-d" || mustJSON(d.There) != `["Cheers"]` { + t.Errorf("the answer lists the field node-d holds differently: %+v", a.Differences) } if d := diffs["tags/$label1/color"]; d.There != "#CC0000" || d.MeshWide != "#FF0000" { t.Errorf("%+v", a.Differences) @@ -195,22 +195,22 @@ func TestDeriveLaysEachEntryOutPerLayerAndProposesOneLayerAtATime(t *testing.T) if _, err := f.Derive(nil, false, true, nil, ""); err == nil || !strings.Contains(err.Error(), "sab12 (the whole mesh)") || len(mesh.proposed) != 1 { t.Fatalf("one open proposal of the module's at a time: %v", err) } - // Approved: the mesh-wide layer holds it, so the next layer is shanks's own. + // Approved: the mesh-wide layer holds it, so the next layer is node-d's own. mesh.open = false mesh.layers[""] = values a, err = f.Derive(nil, false, true, prefs, "") if err != nil { t.Fatal(err) } - if len(mesh.proposed) != 2 || mesh.proposed[1]["node"] != "shanks" || a.Next != "shanks" || + if len(mesh.proposed) != 2 || mesh.proposed[1]["node"] != "node-d" || a.Next != "node-d" || !strings.Contains(mesh.proposed[1]["values"].(string), "standup") { t.Fatalf("then the node's own layer: %v", mesh.proposed) } - var shanks map[string]any - if err := json.Unmarshal([]byte(mesh.proposed[1]["values"].(string)), &shanks); err != nil { + var nodeD map[string]any + if err := json.Unmarshal([]byte(mesh.proposed[1]["values"].(string)), &nodeD); err != nil { t.Fatal(err) } - mesh.layers["shanks"] = shanks + mesh.layers["node-d"] = nodeD if a, err = f.Derive(nil, false, true, prefs, ""); err != nil || len(mesh.proposed) != 2 || !strings.HasPrefix(a.Next, "none") { t.Fatalf("nothing left to propose: %v %s", err, a.Next) } @@ -240,10 +240,10 @@ func TestALayerThatCannotBeReadRefusesTheProposal(t *testing.T) { f2 := newFake(t) f2.profileWithAccounts() f2.declareAccounts(adoptable) - mesh := &derivingMesh{t: t, shanks: f2, garbled: true} + mesh := &derivingMesh{t: t, nodeD: f2, garbled: true} oldNode, oldAsk := nodeName, asker t.Cleanup(func() { nodeName, asker = oldNode, oldAsk }) - nodeName = func() string { return "g14" } + nodeName = func() string { return "node-b" } asker = mesh.ask if _, err := f.Derive(nil, false, true, nil, ""); err == nil || !strings.Contains(err.Error(), "cannot be read as the layer") || len(mesh.proposed) != 0 { @@ -257,7 +257,7 @@ func TestALayerThatCannotBeReadRefusesTheProposal(t *testing.T) { t.Fatal("an unreadable layer is an error, never an empty layer") } mesh.garbled = false - if got, err := readLayer("shanks"); err != nil || len(got) != 0 { + if got, err := readLayer("node-d"); err != nil || len(got) != 0 { t.Fatalf("no layer, in the controller's words, is an empty layer: %v %v", got, err) } } diff --git a/modules/brother/cmd/brother/device_integration_test.go b/modules/brother/cmd/brother/device_integration_test.go index e54cd5fa..b4118853 100644 --- a/modules/brother/cmd/brother/device_integration_test.go +++ b/modules/brother/cmd/brother/device_integration_test.go @@ -64,7 +64,7 @@ func TestTheAdminProcessAnswersAnAskOverARealBus(t *testing.T) { Retention: jetstream.WorkQueuePolicy, Discard: jetstream.DiscardNew, MaxAge: 24 * time.Hour, MaxBytes: 8 << 20}); err != nil { t.Fatal(err) } - account := process.Account{URL: url, Node: "g14", Module: "brother", User: "g14.brother." + DeviceProcessID, Password: "pw"} + account := process.Account{URL: url, Node: "node-b", Module: "brother", User: "node-b.brother." + DeviceProcessID, Password: "pw"} if _, err := js.CreateConsumer(ctx, AsksStream, jetstream.ConsumerConfig{Durable: account.QueueConsumerName(), AckPolicy: jetstream.AckExplicitPolicy, AckWait: 30 * time.Second, MaxDeliver: 3}); err != nil { t.Fatal(err) diff --git a/modules/brother/cmd/brother/fetch_test.go b/modules/brother/cmd/brother/fetch_test.go index 434b5041..5d4ce13b 100644 --- a/modules/brother/cmd/brother/fetch_test.go +++ b/modules/brother/cmd/brother/fetch_test.go @@ -234,7 +234,7 @@ func TestAFetchedPDFIsStoredUnderItsHashAndPrinted(t *testing.T) { // A refusal inside the mesh is answered, and nothing is stored nor printed. fake.body = nil before := len(r.objects.keys()) - if _, err := r.call(t, "printer.print", map[string]any{"url": "http://127.0.0.1:9000/mesh-shanks-brother/x"}); err == nil || !strings.Contains(err.Error(), "loopback") { + if _, err := r.call(t, "printer.print", map[string]any{"url": "http://127.0.0.1:9000/mesh-node-d-brother/x"}); err == nil || !strings.Contains(err.Error(), "loopback") { t.Errorf("a loopback address: error = %v", err) } if len(r.objects.keys()) != before || fake.body != nil { diff --git a/modules/brother/cmd/brother/printlink_test.go b/modules/brother/cmd/brother/printlink_test.go index 56670d1f..a1a4fa6a 100644 --- a/modules/brother/cmd/brother/printlink_test.go +++ b/modules/brother/cmd/brother/printlink_test.go @@ -56,15 +56,15 @@ func TestPrintTakesExactlyOneSource(t *testing.T) { for name, args := range map[string]map[string]any{ "none": {}, "only options": {"copies": float64(2)}, - "object and path": {"object": key, "path": "/home/ops/a.pdf", "node": "g14"}, + "object and path": {"object": key, "path": "/home/ops/a.pdf", "node": "node-b"}, "object and url": {"object": key, "url": "https://example.com/a.pdf"}, - "path+node and url": {"path": "/home/ops/a.pdf", "node": "g14", "url": "https://example.com/a.pdf"}, - "all three": {"object": key, "path": "/home/ops/a.pdf", "node": "g14", "url": "https://example.com/a.pdf"}, + "path+node and url": {"path": "/home/ops/a.pdf", "node": "node-b", "url": "https://example.com/a.pdf"}, + "all three": {"object": key, "path": "/home/ops/a.pdf", "node": "node-b", "url": "https://example.com/a.pdf"}, "path without node": {"path": "/home/ops/a.pdf"}, - "node without path": {"node": "g14", "object": key}, + "node without path": {"node": "node-b", "object": key}, "the retired upload": {"upload": "u1"}, "object and upload": {"object": key, "upload": "u1"}, - "path and its object": {"path": "/home/ops/a.pdf", "node": "g14", "object": key}, + "path and its object": {"path": "/home/ops/a.pdf", "node": "node-b", "object": key}, } { _, err := r.call(t, "printer.print", args) if err == nil { @@ -82,7 +82,7 @@ func TestPrintTakesExactlyOneSource(t *testing.T) { } } -// 1598/AC2: with path and node g14, printer.print asks g14's node-files to upload the path into brother's bucket, and +// 1598/AC2: with path and node node-b, printer.print asks node-b's node-files to upload the path into brother's bucket, and // queues a print ask that carries the returned key and the options: under 4 KiB, and no path, node or bytes. func TestPrintOfAFileOfAnotherMachineUploadsThenPrintsTheKey(t *testing.T) { fake := newIPPFake(t, 31, 5) @@ -90,12 +90,12 @@ func TestPrintOfAFileOfAnotherMachineUploadsThenPrintsTheKey(t *testing.T) { key := sha256Hex(doc) up := withUpload(t, key, nil) r := newRig(t, `{"printer":"192.0.2.10"}`, "pw") - r.objects.Put(t.Context(), key, "application/pdf", doc) // what g14's upload stored - got, err := r.call(t, "printer.print", map[string]any{"path": "/home/ops/letter.pdf", "node": "g14", "copies": float64(2)}) + r.objects.Put(t.Context(), key, "application/pdf", doc) // what node-b's upload stored + got, err := r.call(t, "printer.print", map[string]any{"path": "/home/ops/letter.pdf", "node": "node-b", "copies": float64(2)}) if err != nil { t.Fatal(err) } - if len(up.seen()) != 1 || up.seen()[0] != "g14|/home/ops/letter.pdf|brother-test" { + if len(up.seen()) != 1 || up.seen()[0] != "node-b|/home/ops/letter.pdf|brother-test" { t.Fatalf("uploads asked: %v", up.seen()) } if len(r.bus.published) != 1 { @@ -114,7 +114,7 @@ func TestPrintOfAFileOfAnotherMachineUploadsThenPrintsTheKey(t *testing.T) { } } m := got.(map[string]any) - if m["job-id"] != float64(31) || m["node"] != "g14" || m["path"] != "/home/ops/letter.pdf" { + if m["job-id"] != float64(31) || m["node"] != "node-b" || m["path"] != "/home/ops/letter.pdf" { t.Errorf("answer = %v", m) } if _, sent := fake.request(t); string(sent) != string(doc) { @@ -127,7 +127,7 @@ func TestARefusedUploadIsAnsweredWithItsReasonAndNothingIsPrinted(t *testing.T) fake := newIPPFake(t, 1, 3) up := withUpload(t, "", errors.New("/home/ops/.ssh/id_ed25519 is refused by name: it is in .ssh, which holds an account's credentials")) r := newRig(t, `{"printer":"192.0.2.10"}`, "pw") - _, err := r.call(t, "printer.print", map[string]any{"path": "/home/ops/.ssh/id_ed25519", "node": "g14"}) + _, err := r.call(t, "printer.print", map[string]any{"path": "/home/ops/.ssh/id_ed25519", "node": "node-b"}) if err == nil || !strings.Contains(err.Error(), "is refused by name: it is in .ssh") { t.Fatalf("error = %v", err) } @@ -277,7 +277,7 @@ func TestASlowUploadAndPrintAnswersStartedNeverATimeout(t *testing.T) { t.Cleanup(func() { uploadVia = old }) r := newRig(t, `{"printer":"192.0.2.10"}`, "pw") r.objects.Put(t.Context(), key, "application/pdf", doc) - got, err := r.call(t, "printer.print", map[string]any{"path": "/home/ops/letter.pdf", "node": "g14"}) + got, err := r.call(t, "printer.print", map[string]any{"path": "/home/ops/letter.pdf", "node": "node-b"}) if err != nil { t.Fatalf("a slow upload failed the call: %v", err) } @@ -292,7 +292,7 @@ func TestASlowUploadAndPrintAnswersStartedNeverATimeout(t *testing.T) { t.Fatal(err) } if rm := read.(map[string]any); rm["state"] == nil { - if rm["job-id"] != float64(72) || rm["path"] != "/home/ops/letter.pdf" || rm["node"] != "g14" { + if rm["job-id"] != float64(72) || rm["path"] != "/home/ops/letter.pdf" || rm["node"] != "node-b" { t.Errorf("the outcome = %v", rm) } break @@ -309,7 +309,7 @@ func TestASlowUploadAndPrintAnswersStartedNeverATimeout(t *testing.T) { time.Sleep(150 * time.Millisecond) return "", errors.New("/home/ops/.ssh/id_ed25519 is refused by name") } - got, _ = r.call(t, "printer.print", map[string]any{"path": "/home/ops/.ssh/id_ed25519", "node": "g14"}) + got, _ = r.call(t, "printer.print", map[string]any{"path": "/home/ops/.ssh/id_ed25519", "node": "node-b"}) id2, _ := got.(map[string]any)["ask"].(string) time.Sleep(300 * time.Millisecond) if _, err := r.call(t, "printer.print", map[string]any{"ask": id2}); err == nil || !strings.Contains(err.Error(), "refused by name") { diff --git a/modules/brother/cmd/brother/rig_test.go b/modules/brother/cmd/brother/rig_test.go index 22ae831f..52b38a1d 100644 --- a/modules/brother/cmd/brother/rig_test.go +++ b/modules/brother/cmd/brother/rig_test.go @@ -139,7 +139,7 @@ func newRig(t *testing.T, settings, password string) *printerRig { return nil }, Answers: answers, - Node: "shanks", + Node: "node-d", Now: func() time.Time { return fixedNow }, } bus := &fakeAskBus{worker: w, answers: answers} diff --git a/modules/brother/cmd/brother/scanlink_test.go b/modules/brother/cmd/brother/scanlink_test.go index 7f480eec..6dbcc751 100644 --- a/modules/brother/cmd/brother/scanlink_test.go +++ b/modules/brother/cmd/brother/scanlink_test.go @@ -76,7 +76,7 @@ func TestTheDeviceAnswerCarriesALinkAndNoBytes(t *testing.T) { } // The real store: the binding's key signs, for the binding's host and port, in the module's bucket. - s3 := NewS3(StoreFacts{Scheme: "http", At: "novox.internal", Port: "20001", Bucket: "mesh-shanks-brother", Region: "eu-west", + s3 := NewS3(StoreFacts{Scheme: "http", At: "node-c.internal", Port: "20001", Bucket: "mesh-node-d-brother", Region: "eu-west", Key: "binding-key", Secret: "binding-secret"}) s3.Now = func() time.Time { return fixedNow } got, err := s3.Link("GET", "abc.pdf", 10*time.Minute) @@ -84,7 +84,7 @@ func TestTheDeviceAnswerCarriesALinkAndNoBytes(t *testing.T) { t.Fatal(err) } gu, _ := url.Parse(got) - if gu.Host != "novox.internal:20001" || gu.Path != "/mesh-shanks-brother/abc.pdf" || + if gu.Host != "node-c.internal:20001" || gu.Path != "/mesh-node-d-brother/abc.pdf" || !strings.HasPrefix(gu.Query().Get("X-Amz-Credential"), "binding-key/") || gu.Query().Get("X-Amz-Expires") != "600" { t.Errorf("link %s", got) } diff --git a/modules/brother/cmd/brother/service_test.go b/modules/brother/cmd/brother/service_test.go index 99f83dc8..6a409426 100644 --- a/modules/brother/cmd/brother/service_test.go +++ b/modules/brother/cmd/brother/service_test.go @@ -111,7 +111,7 @@ func TestScanNowEmitsOneEventAfterTheScanIsKeptUnderTheSha256(t *testing.T) { if kept, err := r.objects.Get(t.Context(), want+".pdf"); err != nil || !bytes.Equal(kept, pdf) { t.Errorf("the bucket does not hold the filed PDF under its sha256 (%v)", err) } - if ev.body["bytes"] != len(pdf) || ev.body["node"] != "shanks" || ev.body["cropped"] != true || ev.body["color-mode"] != "color" { + if ev.body["bytes"] != len(pdf) || ev.body["node"] != "node-d" || ev.body["cropped"] != true || ev.body["color-mode"] != "color" { t.Errorf("event = %v", ev.body) } if want := fixedNow.UTC().Format(time.RFC3339); ev.body["scanned-at"] != want { diff --git a/modules/keycloak/cmd/keycloak-provider/admin_test.go b/modules/keycloak/cmd/keycloak-provider/admin_test.go index 09ae9886..ebe8c866 100644 --- a/modules/keycloak/cmd/keycloak-provider/admin_test.go +++ b/modules/keycloak/cmd/keycloak-provider/admin_test.go @@ -52,7 +52,7 @@ type guardWorld struct { func newGuardWorld(t *testing.T) *guardWorld { w := &guardWorld{now: time.Date(2026, 10, 5, 23, 55, 0, 0, time.UTC)} - w.f = newFakeKeycloak(t, "Novox", "old-password-from-2022") + w.f = newFakeKeycloak(t, "NodeC", "old-password-from-2022") w.x = &fakeExec{f: w.f} w.g = &Guard{KC: w.f.client("the-mesh-minted-this"), Exec: w.x, Now: func() time.Time { return w.now }, @@ -195,7 +195,7 @@ func TestWhileTheAdminIsRefusedTheProvisionerDoesNotAskKeycloak(t *testing.T) { w := newGuardWorld(t) w.x.fails = true w.g.Ensure(ctx, true, false) - a := provisioner{clients: OidcClients{KC: w.g.KC, Realm: "Novox"}, guard: w.g, + a := provisioner{clients: OidcClients{KC: w.g.KC, Realm: "NodeC"}, guard: w.g, announce: func(string, map[string]any) {}, log: func(string, ...any) {}} logins := w.f.logins err := a.Create(ctx, grafana("s", nil)) diff --git a/modules/keycloak/cmd/keycloak-provider/grant_moved_test.go b/modules/keycloak/cmd/keycloak-provider/grant_moved_test.go index 20843dcd..3511168e 100644 --- a/modules/keycloak/cmd/keycloak-provider/grant_moved_test.go +++ b/modules/keycloak/cmd/keycloak-provider/grant_moved_test.go @@ -91,13 +91,13 @@ func movedWorld(t *testing.T, h *harness.Harness) (f *fakeKeycloak, start func() } } -// 1332/AC1: a consumer only the grant file gives (oidc-client for novox.mesh-mail-web, not moved) is wanted and +// 1332/AC1: a consumer only the grant file gives (oidc-client for node-c.mesh-mail-web, not moved) is wanted and // Adapter.Create is asked for its client, though keycloak runs on the moved path. func TestAGrantFileConsumerNotMovedIsMadeOnTheMovedPath(t *testing.T) { - mailWeb := "mesh_novox_mail_web" - receives := grantGives(t, map[string]any{"as": mailWeb, "node": "novox", "values": map[string]any{ + mailWeb := "mesh_node_c_mail_web" + receives := grantGives(t, map[string]any{"as": mailWeb, "node": "node-c", "values": map[string]any{ "label": "mail-web", "endpoint": "web", "callback": "/login/generic_oauth", "name": "mail.example.org"}}) - h := &harness.Harness{Resource: ProvisionName, Receives: receives, Node: "novox"} + h := &harness.Harness{Resource: ProvisionName, Receives: receives, Node: "node-c"} f, start := movedWorld(t, h) start() waitUntil(t, time.Second, func() bool { @@ -113,13 +113,13 @@ func TestAGrantFileConsumerNotMovedIsMadeOnTheMovedPath(t *testing.T) { }) } -// 1332/AC2: a grant-file consumer whose client already exists in the backend (mesh_ace_grafana) counts as asked and +// 1332/AC2: a grant-file consumer whose client already exists in the backend (mesh_node_a_grafana) counts as asked and // is not held for retirement on the moved path. func TestAGrantFileConsumerAlreadyInKeycloakIsNotRetiredOnTheMovedPath(t *testing.T) { - grafana := "mesh_ace_grafana" - receives := grantGives(t, map[string]any{"as": grafana, "node": "ace", "values": map[string]any{ + grafana := "mesh_node_a_grafana" + receives := grantGives(t, map[string]any{"as": grafana, "node": "node-a", "values": map[string]any{ "label": "grafana", "endpoint": "web", "callback": "/login/generic_oauth", "name": "grafana.example.org"}}) - h := &harness.Harness{Resource: ProvisionName, Receives: receives, Node: "ace", + h := &harness.Harness{Resource: ProvisionName, Receives: receives, Node: "node-a", StablePasses: 1, StableFor: time.Millisecond} f, start := movedWorld(t, h) // Seed the backend with the client the mesh made earlier, exactly as grafana's already is — before anything diff --git a/modules/keycloak/cmd/keycloak-provider/main_test.go b/modules/keycloak/cmd/keycloak-provider/main_test.go index 617873d6..6f7681f4 100644 --- a/modules/keycloak/cmd/keycloak-provider/main_test.go +++ b/modules/keycloak/cmd/keycloak-provider/main_test.go @@ -8,7 +8,7 @@ import "testing" // 1332/AC3: the moved-path harness, built from the environment, reads MESH_RECEIVES the way the grant path does // (main.go's other branch, line 67), as postgres's moved harness does (postgres-provider/main.go:43). func TestTheMovedPathHarnessReadsMESH_RECEIVESAsTheGrantPathDoes(t *testing.T) { - env := map[string]string{"MESH_RECEIVES": "/grants/mesh.json", "MESH_NODE": "novox"} + env := map[string]string{"MESH_RECEIVES": "/grants/mesh.json", "MESH_NODE": "node-c"} getenv := func(k string) string { return env[k] } h := movedHarness(getenv, provisioner{}) if h.Receives != env["MESH_RECEIVES"] { diff --git a/modules/keycloak/cmd/keycloak-provider/moved_test.go b/modules/keycloak/cmd/keycloak-provider/moved_test.go index f69aa363..03d1af3f 100644 --- a/modules/keycloak/cmd/keycloak-provider/moved_test.go +++ b/modules/keycloak/cmd/keycloak-provider/moved_test.go @@ -14,7 +14,7 @@ import ( "git.novox.be/novox/mesh-sdk/go/provider/harness" ) -const testIssuer = "https://id.example.org/realms/Novox" +const testIssuer = "https://id.example.org/realms/NodeC" // keycloak's own part of the moved path (issue 849): the shared driving of it is proven in the SDK's harness package. @@ -143,12 +143,12 @@ func TestBothPathsLeaveTheSameClientInKeycloak(t *testing.T) { }) viaFile := made(func(p provisioner) { list, _ := json.Marshal([]provider.ConsumerCredential{{Consumer: "home", Module: "grafana", - Credential: provider.PairName("novox", ProvisionName, "home", "grafana", ""), Value: "pw-" + grafana}}) + Credential: provider.PairName("node-c", ProvisionName, "home", "grafana", ""), Value: "pw-" + grafana}}) file := filepath.Join(t.TempDir(), "consumers.json") if err := os.WriteFile(file, list, 0o600); err != nil { t.Fatal(err) } - h := &harness.Harness{Resource: ProvisionName, Adapter: p, Node: "novox", + h := &harness.Harness{Resource: ProvisionName, Adapter: p, Node: "node-c", Now: func() time.Time { return now }, Log: func(string, ...any) {}} run, _, _, err := moved(file, h, testIssuer) if err != nil { @@ -156,10 +156,10 @@ func TestBothPathsLeaveTheSameClientInKeycloak(t *testing.T) { } bus := &bucketBus{buckets: map[string]map[string][]byte{}} plan, _ := json.Marshal(map[string]any{"node": "home", "module": "grafana", "provisioning": map[string]any{ - "provisions": []any{map[string]any{"provision": ProvisionName, "provider": "novox", + "provisions": []any{map[string]any{"provision": ProvisionName, "provider": "node-c", "provider-module": "keycloak", "contributes": grafanaContributes, "names": grafanaNames}}}}) _ = bus.Put(ctx, provider.AssignmentsBucket, "home.grafana", plan) - pr := provider.New(provider.Options{Node: "novox", Module: "keycloak", Bus: bus, + pr := provider.New(provider.Options{Node: "node-c", Module: "keycloak", Bus: bus, Vault: provider.ConsumersFile{Paths: []string{file}}, Offers: map[string]provider.Offer{ProvisionName: {Credential: provider.PerConsumer, Serves: servedValues(testIssuer)}}, diff --git a/modules/keycloak/cmd/keycloak-provider/oidc.go b/modules/keycloak/cmd/keycloak-provider/oidc.go index c7815462..f23804f5 100644 --- a/modules/keycloak/cmd/keycloak-provider/oidc.go +++ b/modules/keycloak/cmd/keycloak-provider/oidc.go @@ -64,7 +64,7 @@ func RolesMapper() Rep { var realmPath = regexp.MustCompile(`/realms/([^/]+)/?$`) -// RealmOf is the realm named by an issuer URL — `https://id.example/realms/Novox` is realm `Novox`. +// RealmOf is the realm named by an issuer URL — `https://id.example/realms/NodeC` is realm `NodeC`. // The issuer is the one value an assignment sets, so the realm is read out of it rather than set a // second time where the two could disagree. func RealmOf(issuer string) (string, error) { diff --git a/modules/keycloak/cmd/keycloak-provider/oidc_test.go b/modules/keycloak/cmd/keycloak-provider/oidc_test.go index 45c95ae3..4045fc91 100644 --- a/modules/keycloak/cmd/keycloak-provider/oidc_test.go +++ b/modules/keycloak/cmd/keycloak-provider/oidc_test.go @@ -15,8 +15,8 @@ import ( ) func oidcWorld(t *testing.T) (*fakeKeycloak, OidcClients) { - f := newFakeKeycloak(t, "Novox", "pw") - return f, OidcClients{KC: f.client("pw"), Realm: "Novox"} + f := newFakeKeycloak(t, "NodeC", "pw") + return f, OidcClients{KC: f.client("pw"), Realm: "NodeC"} } // grafana is a dashboard on the home server, as the mesh hands it to the provisioner. @@ -53,8 +53,8 @@ func mustHold(t *testing.T, o OidcClients, p harness.Provision, want bool) { func TestTheRealmIsReadOutOfTheIssuer(t *testing.T) { for issuer, want := range map[string]string{ - "https://id.example.org/realms/Novox": "Novox", - "https://id.example.org/realms/Novox/": "Novox", + "https://id.example.org/realms/NodeC": "NodeC", + "https://id.example.org/realms/NodeC/": "NodeC", "http://127.0.0.1:18500/realms/master": "master", } { if got, err := RealmOf(issuer); err != nil || got != want { diff --git a/modules/mailu/cmd/automx/automx_test.go b/modules/mailu/cmd/automx/automx_test.go index ab0ab5b6..984f7793 100644 --- a/modules/mailu/cmd/automx/automx_test.go +++ b/modules/mailu/cmd/automx/automx_test.go @@ -14,13 +14,13 @@ import ( "testing" ) -// The environment mailu gives automx on novox when the fixtures were captured (files/mailu.env): the mail domain, +// The environment mailu gives automx on node-c when the fixtures were captured (files/mailu.env): the mail domain, // the route name for both servers, the ports. var capturedEnvironment = map[string]string{ - "AMX_MAIL_DOMAINS": "novox.be", - "AMX_IMAP_ADDRESS": "mail.novox.be", + "AMX_MAIL_DOMAINS": "node-c.be", + "AMX_IMAP_ADDRESS": "mail.node-c.be", "AMX_IMAP_PORT": "143", - "AMX_SMTP_ADDRESS": "mail.novox.be", + "AMX_SMTP_ADDRESS": "mail.node-c.be", "AMX_SMTP_PORT": "587", "AUTOMX_PORT": "4243", } @@ -176,7 +176,7 @@ func TestTheOnlyCorrectedAnswerIsTheImapServersName(t *testing.T) { } for _, c := range corrected { orig := readFile(t, strings.TrimSuffix(c, ".corrected.body")+".body") - want := strings.Replace(orig, "", "mail.novox.be", 1) + want := strings.Replace(orig, "", "mail.node-c.be", 1) if strings.Contains(want, "") || want == orig { t.Fatalf("%s: the capture has no single empty hostname to correct", c) } @@ -198,12 +198,12 @@ func TestTheImapServerIsNamedFromTheImapAddress(t *testing.T) { t.Fatal(err) } rec := httptest.NewRecorder() - newHandler(cfg).ServeHTTP(rec, httptest.NewRequest("GET", "/mail/config-v1.1.xml?emailaddress=a@novox.be", nil)) + newHandler(cfg).ServeHTTP(rec, httptest.NewRequest("GET", "/mail/config-v1.1.xml?emailaddress=a@node-c.be", nil)) body := rec.Body.String() if !strings.Contains(body, `imap.example.test993`) { t.Errorf("incoming server not named from AMX_IMAP_ADDRESS and AMX_IMAP_PORT: %s", body) } - if !strings.Contains(body, `mail.novox.be587`) { + if !strings.Contains(body, `mail.node-c.be587`) { t.Errorf("outgoing server changed: %s", body) } } @@ -213,13 +213,13 @@ func TestEveryDomainOfTheEnvironmentIsServed(t *testing.T) { for k, v := range capturedEnvironment { env[k] = v } - env["AMX_MAIL_DOMAINS"] = "novox.be, example.test" + env["AMX_MAIL_DOMAINS"] = "node-c.be, example.test" cfg, err := configFrom(getenvOf(env)) if err != nil { t.Fatal(err) } h := newHandler(cfg) - for _, d := range []string{"novox.be", "example.test"} { + for _, d := range []string{"node-c.be", "example.test"} { rec := httptest.NewRecorder() h.ServeHTTP(rec, httptest.NewRequest("GET", "/mail/config-v1.1.xml?emailaddress=a@"+d, nil)) if rec.Code != 200 || !strings.Contains(rec.Body.String(), ""+d+"") { diff --git a/modules/mailu/cmd/automx/testdata/captured/01-thunderbird-autoconfig-ok.body b/modules/mailu/cmd/automx/testdata/captured/01-thunderbird-autoconfig-ok.body index 72d5c376..521dbf80 100644 --- a/modules/mailu/cmd/automx/testdata/captured/01-thunderbird-autoconfig-ok.body +++ b/modules/mailu/cmd/automx/testdata/captured/01-thunderbird-autoconfig-ok.body @@ -1 +1 @@ -novox.benovox.benovox.be143STARTTLS%EMAILADDRESS%password-cleartextmail.novox.be587STARTTLS%EMAILADDRESS%password-cleartext \ No newline at end of file +node-c.benode-c.benode-c.be143STARTTLS%EMAILADDRESS%password-cleartextmail.node-c.be587STARTTLS%EMAILADDRESS%password-cleartext \ No newline at end of file diff --git a/modules/mailu/cmd/automx/testdata/captured/01-thunderbird-autoconfig-ok.corrected.body b/modules/mailu/cmd/automx/testdata/captured/01-thunderbird-autoconfig-ok.corrected.body index 0adc5c4c..ad24a7a9 100644 --- a/modules/mailu/cmd/automx/testdata/captured/01-thunderbird-autoconfig-ok.corrected.body +++ b/modules/mailu/cmd/automx/testdata/captured/01-thunderbird-autoconfig-ok.corrected.body @@ -1 +1 @@ -novox.benovox.benovox.bemail.novox.be143STARTTLS%EMAILADDRESS%password-cleartextmail.novox.be587STARTTLS%EMAILADDRESS%password-cleartext \ No newline at end of file +node-c.benode-c.benode-c.bemail.node-c.be143STARTTLS%EMAILADDRESS%password-cleartextmail.node-c.be587STARTTLS%EMAILADDRESS%password-cleartext \ No newline at end of file diff --git a/modules/mailu/cmd/automx/testdata/captured/01-thunderbird-autoconfig-ok.request b/modules/mailu/cmd/automx/testdata/captured/01-thunderbird-autoconfig-ok.request index 98ae52c5..135ba262 100644 --- a/modules/mailu/cmd/automx/testdata/captured/01-thunderbird-autoconfig-ok.request +++ b/modules/mailu/cmd/automx/testdata/captured/01-thunderbird-autoconfig-ok.request @@ -1,3 +1,3 @@ -GET https://autoconfig.novox.be/mail/config-v1.1.xml?emailaddress=jochen@novox.be +GET https://autoconfig.node-c.be/mail/config-v1.1.xml?emailaddress=jochen@node-c.be User-Agent: Thunderbird Accept: */* diff --git a/modules/mailu/cmd/automx/testdata/captured/02-thunderbird-on-automx-name.body b/modules/mailu/cmd/automx/testdata/captured/02-thunderbird-on-automx-name.body index 72d5c376..521dbf80 100644 --- a/modules/mailu/cmd/automx/testdata/captured/02-thunderbird-on-automx-name.body +++ b/modules/mailu/cmd/automx/testdata/captured/02-thunderbird-on-automx-name.body @@ -1 +1 @@ -novox.benovox.benovox.be143STARTTLS%EMAILADDRESS%password-cleartextmail.novox.be587STARTTLS%EMAILADDRESS%password-cleartext \ No newline at end of file +node-c.benode-c.benode-c.be143STARTTLS%EMAILADDRESS%password-cleartextmail.node-c.be587STARTTLS%EMAILADDRESS%password-cleartext \ No newline at end of file diff --git a/modules/mailu/cmd/automx/testdata/captured/02-thunderbird-on-automx-name.corrected.body b/modules/mailu/cmd/automx/testdata/captured/02-thunderbird-on-automx-name.corrected.body index 0adc5c4c..ad24a7a9 100644 --- a/modules/mailu/cmd/automx/testdata/captured/02-thunderbird-on-automx-name.corrected.body +++ b/modules/mailu/cmd/automx/testdata/captured/02-thunderbird-on-automx-name.corrected.body @@ -1 +1 @@ -novox.benovox.benovox.bemail.novox.be143STARTTLS%EMAILADDRESS%password-cleartextmail.novox.be587STARTTLS%EMAILADDRESS%password-cleartext \ No newline at end of file +node-c.benode-c.benode-c.bemail.node-c.be143STARTTLS%EMAILADDRESS%password-cleartextmail.node-c.be587STARTTLS%EMAILADDRESS%password-cleartext \ No newline at end of file diff --git a/modules/mailu/cmd/automx/testdata/captured/02-thunderbird-on-automx-name.request b/modules/mailu/cmd/automx/testdata/captured/02-thunderbird-on-automx-name.request index 2a6405cf..9bc95279 100644 --- a/modules/mailu/cmd/automx/testdata/captured/02-thunderbird-on-automx-name.request +++ b/modules/mailu/cmd/automx/testdata/captured/02-thunderbird-on-automx-name.request @@ -1,2 +1,2 @@ -GET https://automx.novox.be/mail/config-v1.1.xml?emailaddress=jochen@novox.be +GET https://automx.node-c.be/mail/config-v1.1.xml?emailaddress=jochen@node-c.be User-Agent: Thunderbird diff --git a/modules/mailu/cmd/automx/testdata/captured/03-thunderbird-on-autodiscover-name.body b/modules/mailu/cmd/automx/testdata/captured/03-thunderbird-on-autodiscover-name.body index 72d5c376..521dbf80 100644 --- a/modules/mailu/cmd/automx/testdata/captured/03-thunderbird-on-autodiscover-name.body +++ b/modules/mailu/cmd/automx/testdata/captured/03-thunderbird-on-autodiscover-name.body @@ -1 +1 @@ -novox.benovox.benovox.be143STARTTLS%EMAILADDRESS%password-cleartextmail.novox.be587STARTTLS%EMAILADDRESS%password-cleartext \ No newline at end of file +node-c.benode-c.benode-c.be143STARTTLS%EMAILADDRESS%password-cleartextmail.node-c.be587STARTTLS%EMAILADDRESS%password-cleartext \ No newline at end of file diff --git a/modules/mailu/cmd/automx/testdata/captured/03-thunderbird-on-autodiscover-name.corrected.body b/modules/mailu/cmd/automx/testdata/captured/03-thunderbird-on-autodiscover-name.corrected.body index 0adc5c4c..ad24a7a9 100644 --- a/modules/mailu/cmd/automx/testdata/captured/03-thunderbird-on-autodiscover-name.corrected.body +++ b/modules/mailu/cmd/automx/testdata/captured/03-thunderbird-on-autodiscover-name.corrected.body @@ -1 +1 @@ -novox.benovox.benovox.bemail.novox.be143STARTTLS%EMAILADDRESS%password-cleartextmail.novox.be587STARTTLS%EMAILADDRESS%password-cleartext \ No newline at end of file +node-c.benode-c.benode-c.bemail.node-c.be143STARTTLS%EMAILADDRESS%password-cleartextmail.node-c.be587STARTTLS%EMAILADDRESS%password-cleartext \ No newline at end of file diff --git a/modules/mailu/cmd/automx/testdata/captured/03-thunderbird-on-autodiscover-name.request b/modules/mailu/cmd/automx/testdata/captured/03-thunderbird-on-autodiscover-name.request index 5b33fcce..db13436d 100644 --- a/modules/mailu/cmd/automx/testdata/captured/03-thunderbird-on-autodiscover-name.request +++ b/modules/mailu/cmd/automx/testdata/captured/03-thunderbird-on-autodiscover-name.request @@ -1,2 +1,2 @@ -GET https://autodiscover.novox.be/mail/config-v1.1.xml?emailaddress=jochen@novox.be +GET https://autodiscover.node-c.be/mail/config-v1.1.xml?emailaddress=jochen@node-c.be User-Agent: Thunderbird diff --git a/modules/mailu/cmd/automx/testdata/captured/04-thunderbird-unknown-domain.request b/modules/mailu/cmd/automx/testdata/captured/04-thunderbird-unknown-domain.request index d2459a88..f3da5866 100644 --- a/modules/mailu/cmd/automx/testdata/captured/04-thunderbird-unknown-domain.request +++ b/modules/mailu/cmd/automx/testdata/captured/04-thunderbird-unknown-domain.request @@ -1,2 +1,2 @@ -GET https://autoconfig.novox.be/mail/config-v1.1.xml?emailaddress=nobody@unknown.example +GET https://autoconfig.node-c.be/mail/config-v1.1.xml?emailaddress=nobody@unknown.example User-Agent: Thunderbird diff --git a/modules/mailu/cmd/automx/testdata/captured/05-thunderbird-missing-emailaddress.request b/modules/mailu/cmd/automx/testdata/captured/05-thunderbird-missing-emailaddress.request index 5d521f35..8b8fb6b0 100644 --- a/modules/mailu/cmd/automx/testdata/captured/05-thunderbird-missing-emailaddress.request +++ b/modules/mailu/cmd/automx/testdata/captured/05-thunderbird-missing-emailaddress.request @@ -1,2 +1,2 @@ -GET https://autoconfig.novox.be/mail/config-v1.1.xml +GET https://autoconfig.node-c.be/mail/config-v1.1.xml User-Agent: Thunderbird diff --git a/modules/mailu/cmd/automx/testdata/captured/06-autoconfig-root.request b/modules/mailu/cmd/automx/testdata/captured/06-autoconfig-root.request index 4dc45b54..35577694 100644 --- a/modules/mailu/cmd/automx/testdata/captured/06-autoconfig-root.request +++ b/modules/mailu/cmd/automx/testdata/captured/06-autoconfig-root.request @@ -1,2 +1,2 @@ -GET https://autoconfig.novox.be/ +GET https://autoconfig.node-c.be/ User-Agent: Mozilla/5.0 diff --git a/modules/mailu/cmd/automx/testdata/captured/07-wellknown-autoconfig-path.request b/modules/mailu/cmd/automx/testdata/captured/07-wellknown-autoconfig-path.request index d45d9935..a24d2125 100644 --- a/modules/mailu/cmd/automx/testdata/captured/07-wellknown-autoconfig-path.request +++ b/modules/mailu/cmd/automx/testdata/captured/07-wellknown-autoconfig-path.request @@ -1 +1 @@ -GET https://autoconfig.novox.be/.well-known/autoconfig/mail/config-v1.1.xml?emailaddress=jochen@novox.be +GET https://autoconfig.node-c.be/.well-known/autoconfig/mail/config-v1.1.xml?emailaddress=jochen@node-c.be diff --git a/modules/mailu/cmd/automx/testdata/captured/08-outlook-post-known-domain.request b/modules/mailu/cmd/automx/testdata/captured/08-outlook-post-known-domain.request index 258c92a6..5c1983c4 100644 --- a/modules/mailu/cmd/automx/testdata/captured/08-outlook-post-known-domain.request +++ b/modules/mailu/cmd/automx/testdata/captured/08-outlook-post-known-domain.request @@ -1,4 +1,4 @@ -POST https://autodiscover.novox.be/autodiscover/autodiscover.xml +POST https://autodiscover.node-c.be/autodiscover/autodiscover.xml User-Agent: Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.14326; Pro) Content-Type: text/xml Accept: */* @@ -6,7 +6,7 @@ Accept: */* - jochen@novox.be + jochen@node-c.be http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a diff --git a/modules/mailu/cmd/automx/testdata/captured/09-outlook-post-unknown-domain.request b/modules/mailu/cmd/automx/testdata/captured/09-outlook-post-unknown-domain.request index 990a009c..588a5777 100644 --- a/modules/mailu/cmd/automx/testdata/captured/09-outlook-post-unknown-domain.request +++ b/modules/mailu/cmd/automx/testdata/captured/09-outlook-post-unknown-domain.request @@ -1,4 +1,4 @@ -POST https://autodiscover.novox.be/autodiscover/autodiscover.xml +POST https://autodiscover.node-c.be/autodiscover/autodiscover.xml User-Agent: Microsoft Office/16.0 Content-Type: text/xml diff --git a/modules/mailu/cmd/automx/testdata/captured/10-outlook-post-malformed-body.request b/modules/mailu/cmd/automx/testdata/captured/10-outlook-post-malformed-body.request index 7467eeee..429c7cb8 100644 --- a/modules/mailu/cmd/automx/testdata/captured/10-outlook-post-malformed-body.request +++ b/modules/mailu/cmd/automx/testdata/captured/10-outlook-post-malformed-body.request @@ -1,4 +1,4 @@ -POST https://autodiscover.novox.be/autodiscover/autodiscover.xml +POST https://autodiscover.node-c.be/autodiscover/autodiscover.xml User-Agent: Microsoft Office/16.0 Content-Type: text/xml diff --git a/modules/mailu/cmd/automx/testdata/captured/11-outlook-post-missing-emailaddress.request b/modules/mailu/cmd/automx/testdata/captured/11-outlook-post-missing-emailaddress.request index abea016e..2b47b3aa 100644 --- a/modules/mailu/cmd/automx/testdata/captured/11-outlook-post-missing-emailaddress.request +++ b/modules/mailu/cmd/automx/testdata/captured/11-outlook-post-missing-emailaddress.request @@ -1,4 +1,4 @@ -POST https://autodiscover.novox.be/autodiscover/autodiscover.xml +POST https://autodiscover.node-c.be/autodiscover/autodiscover.xml User-Agent: Microsoft Office/16.0 Content-Type: text/xml diff --git a/modules/mailu/cmd/automx/testdata/captured/12-outlook-get-not-allowed.request b/modules/mailu/cmd/automx/testdata/captured/12-outlook-get-not-allowed.request index 11530419..c10f6124 100644 --- a/modules/mailu/cmd/automx/testdata/captured/12-outlook-get-not-allowed.request +++ b/modules/mailu/cmd/automx/testdata/captured/12-outlook-get-not-allowed.request @@ -1,2 +1,2 @@ -GET https://autodiscover.novox.be/autodiscover/autodiscover.xml +GET https://autodiscover.node-c.be/autodiscover/autodiscover.xml User-Agent: Microsoft Office/16.0 diff --git a/modules/mailu/cmd/automx/testdata/captured/13-outlook-post-capitalised-path.request b/modules/mailu/cmd/automx/testdata/captured/13-outlook-post-capitalised-path.request index ff129abe..40623338 100644 --- a/modules/mailu/cmd/automx/testdata/captured/13-outlook-post-capitalised-path.request +++ b/modules/mailu/cmd/automx/testdata/captured/13-outlook-post-capitalised-path.request @@ -1,6 +1,6 @@ -POST https://autodiscover.novox.be/Autodiscover/Autodiscover.xml +POST https://autodiscover.node-c.be/Autodiscover/Autodiscover.xml User-Agent: Microsoft Office/16.0 Content-Type: text/xml -jochen@novox.behttp://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a +jochen@node-c.behttp://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a diff --git a/modules/mailu/cmd/automx/testdata/captured/14-mobileconfig-no-slash.body b/modules/mailu/cmd/automx/testdata/captured/14-mobileconfig-no-slash.body index bc384fc9..2554bff8 100644 --- a/modules/mailu/cmd/automx/testdata/captured/14-mobileconfig-no-slash.body +++ b/modules/mailu/cmd/automx/testdata/captured/14-mobileconfig-no-slash.body @@ -2,4 +2,4 @@ Redirecting...

Redirecting...

-

You should be redirected automatically to the target URL: https://automx.novox.be/mobileconfig/?emailaddress=jochen@novox.be. If not, click the link. +

You should be redirected automatically to the target URL: https://automx.node-c.be/mobileconfig/?emailaddress=jochen@node-c.be. If not, click the link. diff --git a/modules/mailu/cmd/automx/testdata/captured/14-mobileconfig-no-slash.headers b/modules/mailu/cmd/automx/testdata/captured/14-mobileconfig-no-slash.headers index 75822817..a8f4e9c2 100644 --- a/modules/mailu/cmd/automx/testdata/captured/14-mobileconfig-no-slash.headers +++ b/modules/mailu/cmd/automx/testdata/captured/14-mobileconfig-no-slash.headers @@ -1,4 +1,4 @@ -Content-Length: 319 +Content-Length: 323 Content-Type: text/html; charset=utf-8 -Location: https://automx.novox.be/mobileconfig/?emailaddress=jochen@novox.be +Location: https://automx.node-c.be/mobileconfig/?emailaddress=jochen@node-c.be Server: Werkzeug/3.1.9 Python/3.9.5 diff --git a/modules/mailu/cmd/automx/testdata/captured/14-mobileconfig-no-slash.request b/modules/mailu/cmd/automx/testdata/captured/14-mobileconfig-no-slash.request index ee86c5ba..8a495267 100644 --- a/modules/mailu/cmd/automx/testdata/captured/14-mobileconfig-no-slash.request +++ b/modules/mailu/cmd/automx/testdata/captured/14-mobileconfig-no-slash.request @@ -1,3 +1,3 @@ -GET https://automx.novox.be/mobileconfig?emailaddress=jochen@novox.be +GET https://automx.node-c.be/mobileconfig?emailaddress=jochen@node-c.be User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) Safari Accept: */* diff --git a/modules/mailu/cmd/automx/testdata/captured/15-mobileconfig-known-domain.request b/modules/mailu/cmd/automx/testdata/captured/15-mobileconfig-known-domain.request index 47197a20..4edbe6df 100644 --- a/modules/mailu/cmd/automx/testdata/captured/15-mobileconfig-known-domain.request +++ b/modules/mailu/cmd/automx/testdata/captured/15-mobileconfig-known-domain.request @@ -1,3 +1,3 @@ -GET https://automx.novox.be/mobileconfig/?emailaddress=jochen@novox.be +GET https://automx.node-c.be/mobileconfig/?emailaddress=jochen@node-c.be User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) Safari Accept: */* diff --git a/modules/mailu/cmd/automx/testdata/captured/16-mobileconfig-unknown-domain.request b/modules/mailu/cmd/automx/testdata/captured/16-mobileconfig-unknown-domain.request index b38acb38..26bfdf3d 100644 --- a/modules/mailu/cmd/automx/testdata/captured/16-mobileconfig-unknown-domain.request +++ b/modules/mailu/cmd/automx/testdata/captured/16-mobileconfig-unknown-domain.request @@ -1,2 +1,2 @@ -GET https://automx.novox.be/mobileconfig/?emailaddress=nobody@unknown.example +GET https://automx.node-c.be/mobileconfig/?emailaddress=nobody@unknown.example User-Agent: Mozilla/5.0 (iPhone) diff --git a/modules/mailu/cmd/automx/testdata/captured/17-mobileconfig-missing-emailaddress.request b/modules/mailu/cmd/automx/testdata/captured/17-mobileconfig-missing-emailaddress.request index a7f84362..cc4f35b6 100644 --- a/modules/mailu/cmd/automx/testdata/captured/17-mobileconfig-missing-emailaddress.request +++ b/modules/mailu/cmd/automx/testdata/captured/17-mobileconfig-missing-emailaddress.request @@ -1,2 +1,2 @@ -GET https://automx.novox.be/mobileconfig/ +GET https://automx.node-c.be/mobileconfig/ User-Agent: Mozilla/5.0 (iPhone) diff --git a/modules/mailu/cmd/automx/testdata/captured/CAPTURED b/modules/mailu/cmd/automx/testdata/captured/CAPTURED index 01a9be83..f80f81f1 100644 --- a/modules/mailu/cmd/automx/testdata/captured/CAPTURED +++ b/modules/mailu/cmd/automx/testdata/captured/CAPTURED @@ -1,10 +1,10 @@ -What mailu's autoconfiguration module (automx2 2021.6, container mailu-automx on novox, Werkzeug/3.1.9 Python/3.9.5) +What mailu's autoconfiguration module (automx2 2021.6, container mailu-automx on node-c, Werkzeug/3.1.9 Python/3.9.5) answers to the requests mail clients make (R4d step AMX-1, issue 1630, ADR 0480). Captured 2026-10-21 between 13:58:25 and 13:58:52 (CEST; the Date headers said 11:58 GMT) with the mesh tool -shanks/netcheck.netcheck_request, called from shanks, through the names clients use (autoconfig.novox.be, -autodiscover.novox.be, automx.novox.be: HTTPS, the mesh's route), no ssh. A redirect is reported, never followed. -Mail domain served: novox.be. Mailbox used: jochen@novox.be; unknown domain: nobody@unknown.example. +node-d/netcheck.netcheck_request, called from node-d, through the names clients use (autoconfig.node-c.be, +autodiscover.node-c.be, automx.node-c.be: HTTPS, the mesh's route), no ssh. A redirect is reported, never followed. +Mail domain served: node-c.be. Mailbox used: jochen@node-c.be; unknown domain: nobody@unknown.example. Each capture is four files with the same stem: .request method and URL, then the request headers sent, then (after a blank line) the body sent @@ -24,7 +24,7 @@ A fixture is not the bytes on the wire in four ways (issue 1701): What the answers show (read, not guessed): - GET /mail/config-v1.1.xml?emailaddress=... answers 200 application/xml on all three names; same body on each. - The incoming (IMAP) server has an EMPTY hostname (), port 143, STARTTLS. The outgoing server is - mail.novox.be:587 STARTTLS. Cause (from reading the module, not from the database): automx/files/add-domains:35 + mail.node-c.be:587 STARTTLS. Cause (from reading the module, not from the database): automx/files/add-domains:35 reads AMX_IMAP_SERVER, files/mailu.env:58 sets AMX_IMAP_ADDRESS, so the IMAP name was never written. A client given this answer cannot find its IMAP server. - POST /autodiscover/autodiscover.xml with a valid request for the served domain answers 500 (the Outlook diff --git a/modules/mailu/cmd/automx/testdata/captured/DIFFERENCES b/modules/mailu/cmd/automx/testdata/captured/DIFFERENCES index 8274fdd9..f162a76c 100644 --- a/modules/mailu/cmd/automx/testdata/captured/DIFFERENCES +++ b/modules/mailu/cmd/automx/testdata/captured/DIFFERENCES @@ -6,7 +6,7 @@ whole list of where the two differ. server because its setup script read AMX_IMAP_SERVER, which mailu's environment does not set (it sets AMX_IMAP_ADDRESS). The program names it from AMX_IMAP_ADDRESS (and the port from AMX_IMAP_PORT). Fixtures 01, 02 and 03 each have a .corrected.body: the capture with replaced by - mail.novox.be and nothing else (a test checks that). Their Content-Length is that file's + mail.node-c.be and nothing else (a test checks that). Their Content-Length is that file's size, 634, not the captured 612. 2. The Server header. The capture has "Server: Werkzeug/3.1.9 Python/3.9.5". The program sends no Server header, and diff --git a/modules/minio/cmd/object-store/server_test.go b/modules/minio/cmd/object-store/server_test.go index 2f944a27..61795806 100644 --- a/modules/minio/cmd/object-store/server_test.go +++ b/modules/minio/cmd/object-store/server_test.go @@ -18,19 +18,19 @@ const grantFile = `{ "contributions": 1, "requirement": "s3-bucket", "given": [ - {"from": "brother", "node": "shanks", "as": "brother-key", + {"from": "brother", "node": "node-d", "as": "brother-key", "values": {"shares": [{"to": "seat:node-files", "methods": ["put"]}, {"to": "print-and-scan", "methods": ["get"]}]}, - "derived": {"bucket": "mesh-shanks-brother"}}, - {"from": "nextcloud", "node": "novox", "as": "nextcloud-key", "derived": {"bucket": "mesh-novox-nextcloud"}} + "derived": {"bucket": "mesh-node-d-brother"}}, + {"from": "nextcloud", "node": "node-c", "as": "nextcloud-key", "derived": {"bucket": "mesh-node-c-nextcloud"}} ] }` // The seats answer is the controller's (mesh-controller.seats read on 2026-10-21): seats[].holders[] of {node, module}, // and outside[] of {Claim, Node, Module}. const seatsAnswer = `{"answer": {"seats": [ - {"seat": "node-files", "scope": "node", "holders": [{"node": "g14", "module": "mesh-files"}, {"node": "shanks", "module": "mesh-files"}]}, - {"seat": "node-backup", "scope": "node", "holders": [{"node": "g14", "module": "restic"}]} - ], "outside": [{"Claim": "printer", "Scope": "mesh", "Node": "shanks", "Module": "brother", "Site": "home", "Kind": ""}]}}` + {"seat": "node-files", "scope": "node", "holders": [{"node": "node-b", "module": "mesh-files"}, {"node": "node-d", "module": "mesh-files"}]}, + {"seat": "node-backup", "scope": "node", "holders": [{"node": "node-b", "module": "restic"}]} + ], "outside": [{"Claim": "printer", "Scope": "mesh", "Node": "node-d", "Module": "brother", "Site": "home", "Kind": ""}]}}` type rig struct { s *server @@ -54,10 +54,10 @@ func newRig(t *testing.T) *rig { } return p } - // What the mesh renders from files/object-store.json for a store on novox.internal, port 20001. - cfg := write("object-store.json", `{"scheme":"http","at":"novox.internal","port":"20001","region":"eu-west"}`) - write("links/mesh-shanks-brother.secret", "brother-link-secret\n") - write("links/mesh-novox-nextcloud.secret", "nextcloud-link-secret\n") + // What the mesh renders from files/object-store.json for a store on node-c.internal, port 20001. + cfg := write("object-store.json", `{"scheme":"http","at":"node-c.internal","port":"20001","region":"eu-west"}`) + write("links/mesh-node-d-brother.secret", "brother-link-secret\n") + write("links/mesh-node-c-nextcloud.secret", "nextcloud-link-secret\n") grants := write("grants/mesh.json", grantFile) s, err := newServer(cfg, filepath.Join(dir, "links"), grants) if err != nil { @@ -96,16 +96,16 @@ func linkOf(t *testing.T, got any) *url.URL { // 1516/AC1: brother's own ask gets a link signed with the bucket's link key, for the store's host and port, 300 s. func TestLinkIsSignedWithTheBucketsLinkKey(t *testing.T) { r := newRig(t) - got, err := r.s.link("shanks.brother", ask("mesh-shanks-brother", "get", float64(300))) + got, err := r.s.link("node-d.brother", ask("mesh-node-d-brother", "get", float64(300))) if err != nil { t.Fatal(err) } u := linkOf(t, got) - if u.Host != "novox.internal:20001" || u.Scheme != "http" || u.Path != "/mesh-shanks-brother/doc.pdf" { + if u.Host != "node-c.internal:20001" || u.Scheme != "http" || u.Path != "/mesh-node-d-brother/doc.pdf" { t.Fatalf("link goes to %s", u) } q := u.Query() - if cred := q.Get("X-Amz-Credential"); !strings.HasPrefix(cred, linkKeyID("mesh-shanks-brother")+"/20261021/eu-west/s3/") { + if cred := q.Get("X-Amz-Credential"); !strings.HasPrefix(cred, linkKeyID("mesh-node-d-brother")+"/20261021/eu-west/s3/") { t.Fatalf("credential %q is not the bucket's link key", cred) } if strings.Contains(u.String(), "meshroot") { @@ -124,18 +124,18 @@ func TestLinkKeyIDMatchesTheProvisioners(t *testing.T) { } } -// 1516/AC2: a share to seat:node-files for put, mesh-files holding node-files on g14: put given, get refused naming the method. +// 1516/AC2: a share to seat:node-files for put, mesh-files holding node-files on node-b: put given, get refused naming the method. func TestSeatShareGivesTheHoldersTheSharedMethodOnly(t *testing.T) { r := newRig(t) - if _, err := r.s.link("g14.mesh-files", ask("mesh-shanks-brother", "put", nil)); err != nil { + if _, err := r.s.link("node-b.mesh-files", ask("mesh-node-d-brother", "put", nil)); err != nil { t.Fatalf("put: %v", err) } - _, err := r.s.link("g14.mesh-files", ask("mesh-shanks-brother", "get", nil)) + _, err := r.s.link("node-b.mesh-files", ask("mesh-node-d-brother", "get", nil)) if err == nil || !strings.Contains(err.Error(), "put, not get") { t.Fatalf("get was not refused naming the method: %v", err) } // A module share is judged by name alone. - if _, err := r.s.link("novox.print-and-scan", ask("mesh-shanks-brother", "get", nil)); err != nil { + if _, err := r.s.link("node-c.print-and-scan", ask("mesh-node-d-brother", "get", nil)); err != nil { t.Fatalf("print-and-scan get: %v", err) } } @@ -148,14 +148,14 @@ func TestRefusals(t *testing.T) { args map[string]any want string }{ - {"a stranger", "g14.restic", ask("mesh-shanks-brother", "get", nil), "not the bucket's consumer"}, - {"a seat it does not hold", "g14.restic", ask("mesh-shanks-brother", "put", nil), "not the bucket's consumer"}, - {"unproven", "unproven", ask("mesh-shanks-brother", "get", nil), "did not prove"}, - {"no grant", "shanks.brother", ask("no-such-bucket", "get", nil), "no grant names bucket"}, - {"seconds over 600", "shanks.brother", ask("mesh-shanks-brother", "get", float64(601)), "at most ten minutes"}, - {"seconds zero", "shanks.brother", ask("mesh-shanks-brother", "get", float64(0)), "outside 1 to 600"}, - {"method delete", "shanks.brother", ask("mesh-shanks-brother", "delete", nil), "not get or put"}, - {"another consumer's bucket", "shanks.brother", ask("mesh-novox-nextcloud", "get", nil), "not the bucket's consumer"}, + {"a stranger", "node-b.restic", ask("mesh-node-d-brother", "get", nil), "not the bucket's consumer"}, + {"a seat it does not hold", "node-b.restic", ask("mesh-node-d-brother", "put", nil), "not the bucket's consumer"}, + {"unproven", "unproven", ask("mesh-node-d-brother", "get", nil), "did not prove"}, + {"no grant", "node-d.brother", ask("no-such-bucket", "get", nil), "no grant names bucket"}, + {"seconds over 600", "node-d.brother", ask("mesh-node-d-brother", "get", float64(601)), "at most ten minutes"}, + {"seconds zero", "node-d.brother", ask("mesh-node-d-brother", "get", float64(0)), "outside 1 to 600"}, + {"method delete", "node-d.brother", ask("mesh-node-d-brother", "delete", nil), "not get or put"}, + {"another consumer's bucket", "node-d.brother", ask("mesh-node-c-nextcloud", "get", nil), "not the bucket's consumer"}, } for _, c := range cases { _, err := r.s.link(c.caller, c.args) @@ -170,14 +170,14 @@ func TestRefusals(t *testing.T) { func TestSeatsUnreadableAndCached(t *testing.T) { r := newRig(t) r.seatsErr = errors.New("the controller did not answer") - _, err := r.s.link("g14.mesh-files", ask("mesh-shanks-brother", "put", nil)) + _, err := r.s.link("node-b.mesh-files", ask("mesh-node-d-brother", "put", nil)) if err == nil || !strings.Contains(err.Error(), "the controller did not answer") || !strings.Contains(err.Error(), "node-files") { t.Fatalf("not refused naming why: %v", err) } r.seatsErr = nil put := func() { t.Helper() - if _, err := r.s.link("g14.mesh-files", ask("mesh-shanks-brother", "put", nil)); err != nil { + if _, err := r.s.link("node-b.mesh-files", ask("mesh-node-d-brother", "put", nil)); err != nil { t.Fatal(err) } } @@ -201,17 +201,17 @@ func TestSeatsUnreadableAndCached(t *testing.T) { // 1516/AC5: the grant file is read at each call. func TestGrantFileIsReadAtEachCall(t *testing.T) { r := newRig(t) - if _, err := r.s.link("novox.print-and-scan", ask("mesh-shanks-brother", "get", nil)); err != nil { + if _, err := r.s.link("node-c.print-and-scan", ask("mesh-node-d-brother", "get", nil)); err != nil { t.Fatal(err) } changed := strings.Replace(grantFile, `{"to": "print-and-scan", "methods": ["get"]}`, `{"to": "someone-else", "methods": ["get"]}`, 1) if err := os.WriteFile(r.s.receives, []byte(changed), 0o600); err != nil { t.Fatal(err) } - if _, err := r.s.link("novox.print-and-scan", ask("mesh-shanks-brother", "get", nil)); err == nil { + if _, err := r.s.link("node-c.print-and-scan", ask("mesh-node-d-brother", "get", nil)); err == nil { t.Fatal("the second call judged by the old shares") } - if _, err := r.s.link("novox.someone-else", ask("mesh-shanks-brother", "get", nil)); err != nil { + if _, err := r.s.link("node-c.someone-else", ask("mesh-node-d-brother", "get", nil)); err != nil { t.Fatal(err) } }