Archived
mesh/merge-gate pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it…
mesh/repo-check fail: its merge-check.sh failed: --- FAIL: TestTheInstallersFirstUserListIsWhatTheControllerWouldCompose (0.74s)
mesh/delivery superseded: a newer head of the same pull request
Restacked on #157, which carries #164's rule that no verb runs secret accept. give's line carries no value: the operator types it into the desk's hidden prompt, sealed to the call and then to the module's machine. Only that exact line passes: a value, a file, a provider or any extra word stays the terminal's.
248 lines
10 KiB
Go
248 lines
10 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/novox/mesh-controller/internal/broker"
|
|
"github.com/novox/mesh-controller/internal/conditions"
|
|
"github.com/novox/mesh-controller/internal/link"
|
|
"github.com/novox/mesh-controller/internal/secrets"
|
|
)
|
|
|
|
const typed = "123456789:AAEhBP0av28P4XFQnIuR-o-7Xnz1kkUzW3g"
|
|
|
|
// aDesk is the desk path with a prompt the test answers as the operator would, and what it was asked kept.
|
|
func aDesk(t *testing.T, answer func(args map[string]any) (json.RawMessage, error)) (deskGive, *[]string, *[]link.HandAct, *[]map[string]any) {
|
|
t.Helper()
|
|
var accepted []string
|
|
var acts []link.HandAct
|
|
var asked []map[string]any
|
|
return deskGive{
|
|
declares: func(module, name string) error {
|
|
if module != "telegram" || name != "telegram-token" {
|
|
return errors.New(module + " does not declare " + name + " as an own secret")
|
|
}
|
|
return nil
|
|
},
|
|
ask: func(machine string, args map[string]any) (json.RawMessage, error) {
|
|
asked = append(asked, args)
|
|
return answer(args)
|
|
},
|
|
accept: func(value string) (bool, error) { accepted = append(accepted, value); return false, nil },
|
|
record: func(a link.HandAct) error { acts = append(acts, a); return nil },
|
|
}, &accepted, &acts, &asked
|
|
}
|
|
|
|
func sealedTo(t *testing.T, value string) func(args map[string]any) (json.RawMessage, error) {
|
|
return func(args map[string]any) (json.RawMessage, error) {
|
|
sealed, err := secrets.Seal(args["seal_to"].(string), []byte(value+"\n"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
raw, _ := json.Marshal(map[string]any{"sealed": sealed})
|
|
return raw, nil
|
|
}
|
|
}
|
|
|
|
// novox/hq ADR 0259 §10: the value typed at the desk is sealed as `secret accept` seals it, and is in no
|
|
// answer, no prompt argument and no act recorded.
|
|
func TestASecretGivenAtTheDeskIsSealedAndSaidNowhere(t *testing.T) {
|
|
d, accepted, acts, asked := aDesk(t, sealedTo(t, typed))
|
|
words, err := d.give("anchor", "telegram", "telegram-token", "laptop")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(*accepted) != 1 || (*accepted)[0] != typed {
|
|
t.Fatalf("the value sealed is not what was typed, its line ending taken off")
|
|
}
|
|
if len(*acts) != 1 || (*acts)[0].Verb != "secret accept" || (*acts)[0].Cause != "given-at-the-desk" ||
|
|
!strings.Contains((*acts)[0].Why, "at the desk on laptop") {
|
|
t.Errorf("the act: %+v", *acts)
|
|
}
|
|
raw, _ := json.Marshal(struct {
|
|
Words string
|
|
Acts []link.HandAct
|
|
Asked []map[string]any
|
|
}{words, *acts, *asked})
|
|
if strings.Contains(string(raw), typed) || strings.Contains(string(raw), "AAEhBP0") {
|
|
t.Fatal("the value appears in what was said, asked or recorded")
|
|
}
|
|
if !strings.Contains(words, "push anchor") || !strings.Contains(words, "given at the desk on laptop") {
|
|
t.Errorf("%q", words)
|
|
}
|
|
if p := (*asked)[0]; p["seal_to"] == "" || p["timeout_seconds"] != deskPromptWithin {
|
|
t.Errorf("the prompt was asked %v", p)
|
|
}
|
|
}
|
|
|
|
func TestNothingIsAskedForASecretTheMeshWouldRefuse(t *testing.T) {
|
|
for _, c := range [][2]string{{"telegram", "chat-id"}, {"nobody", "telegram-token"}} {
|
|
d, accepted, _, asked := aDesk(t, sealedTo(t, typed))
|
|
if _, err := d.give("anchor", c[0], c[1], "laptop"); err == nil || !strings.Contains(err.Error(), "nobody was asked") {
|
|
t.Errorf("%v: %v", c, err)
|
|
}
|
|
if len(*asked) != 0 || len(*accepted) != 0 {
|
|
t.Errorf("%v: the operator was asked anyway", c)
|
|
}
|
|
}
|
|
d, _, _, _ := aDesk(t, sealedTo(t, typed))
|
|
if _, err := d.give("anchor", "telegram", "telegram-token", ""); err == nil {
|
|
t.Error("no desk was refused nowhere")
|
|
}
|
|
}
|
|
|
|
func TestADismissedEmptyLateOrForeignAnswerTakesNothing(t *testing.T) {
|
|
for want, answer := range map[string]func(map[string]any) (json.RawMessage, error){
|
|
"not answered within 25 seconds": func(map[string]any) (json.RawMessage, error) {
|
|
return json.RawMessage(`{"cancelled":true,"timed_out":true}`), nil
|
|
},
|
|
"was dismissed": func(map[string]any) (json.RawMessage, error) { return json.RawMessage(`{"cancelled":true}`), nil },
|
|
"answered empty": sealedTo(t, " "),
|
|
"not sealed to this call": func(map[string]any) (json.RawMessage, error) {
|
|
other, _, _ := secrets.Keypair()
|
|
sealed, _ := secrets.Seal(other, []byte(typed))
|
|
raw, _ := json.Marshal(map[string]any{"sealed": sealed})
|
|
return raw, nil
|
|
},
|
|
"could not be asked": func(map[string]any) (json.RawMessage, error) { return nil, errors.New("no session answers") },
|
|
} {
|
|
d, accepted, acts, _ := aDesk(t, answer)
|
|
_, err := d.give("anchor", "telegram", "telegram-token", "laptop")
|
|
if err == nil || !strings.Contains(err.Error(), want) || strings.Contains(err.Error(), typed) {
|
|
t.Errorf("want %q, got %v", want, err)
|
|
}
|
|
if len(*accepted) != 0 || len(*acts) != 0 {
|
|
t.Errorf("%s: something was taken or recorded", want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTheGiveVerbRunsTheDeskPathAndTheControllerMayAskTheDesk(t *testing.T) {
|
|
argv, err := argvFor("give", map[string]any{"node": "anchor", "module": "telegram", "secret": "telegram-token", "at": "laptop"})
|
|
if err != nil || strings.Join(argv, " ") != "secret accept anchor telegram telegram-token --at-desk laptop" {
|
|
t.Fatalf("%v %v", argv, err)
|
|
}
|
|
if _, err := argvFor("give", map[string]any{"node": "anchor", "module": "telegram", "secret": "telegram-token"}); err == nil {
|
|
t.Error("give without a desk was taken")
|
|
}
|
|
perms, err := broker.PermissionsFor(broker.Principal{Kind: broker.KindController})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
found := false
|
|
for _, p := range perms.Publish {
|
|
found = found || p == "mesh.seat.node-launcher.tool.secret.*"
|
|
}
|
|
if !found {
|
|
t.Error("the controller may not ask the desk's prompt")
|
|
}
|
|
}
|
|
|
|
// The review of 2026-10-09 (M4): the desk's prompt says who asks in words the caller does not choose — the
|
|
// controller, which the bus alone lets ask it — and what for, from names the controller checked; the prompt
|
|
// carries no free text of the caller's.
|
|
func TestThePromptIsAskedByNameNeverByWordsTheCallerChose(t *testing.T) {
|
|
d, _, _, asked := aDesk(t, sealedTo(t, typed))
|
|
if _, err := d.give("anchor", "telegram", "telegram-token", "laptop"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
p := (*asked)[0]
|
|
if p["module"] != "telegram" || p["secret"] != "telegram-token" || p["node"] != "anchor" {
|
|
t.Errorf("the prompt was not asked by name: %v", p)
|
|
}
|
|
for _, free := range []string{"prompt", "message"} {
|
|
if _, there := p[free]; there {
|
|
t.Errorf("the prompt carries the caller's %s: %v", free, p)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Every value given for a module's own secret is announced as a condition, on every channel (the review of
|
|
// 2026-10-09, M4): a bot token changed by somebody else is a channel that now answers for them.
|
|
func TestAValueGivenAtTheDeskIsAnnounced(t *testing.T) {
|
|
d, _, _, _ := aDesk(t, sealedTo(t, typed))
|
|
var said []string
|
|
d.announce = func(node, module, name, how string) error {
|
|
said = append(said, node+" "+module+" "+name+" "+how)
|
|
return nil
|
|
}
|
|
if _, err := d.give("anchor", "telegram", "telegram-token", "laptop"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(said) != 1 || !strings.Contains(said[0], "anchor telegram telegram-token") || !strings.Contains(said[0], "laptop") {
|
|
t.Fatalf("announced %v", said)
|
|
}
|
|
o := secretGivenObservation("anchor", "telegram", "telegram-token", "at the desk on laptop", time.Date(2026, 10, 9, 12, 3, 0, 0, time.UTC))
|
|
if o.Severity != conditions.Urgent || !strings.Contains(o.Explanation, "telegram-token") ||
|
|
len(o.Actions) == 0 || o.Key() == "" {
|
|
t.Errorf("the announcement %+v", o)
|
|
}
|
|
if strings.Contains(o.Summary+o.Explanation+o.Said, typed) {
|
|
t.Error("the announcement carries the value")
|
|
}
|
|
}
|
|
|
|
// The bus lets the controller alone ask the desk's prompt (the review of 2026-10-09, M4): the runtime, which
|
|
// carries every agent's calls, and a person granted every tool are denied it, however wide their grant.
|
|
func TestOnlyTheControllerMayAskTheDesksPrompt(t *testing.T) {
|
|
for _, p := range []broker.Principal{
|
|
{Kind: broker.KindNodeTools, Node: "laptop"},
|
|
{Kind: broker.KindPerson, Module: "operator", Invokes: []string{"*"}},
|
|
{Kind: broker.KindModule, Node: "laptop", Module: "lab", Invokes: []string{"seat:node-launcher.secret"}},
|
|
} {
|
|
perms, err := broker.PermissionsFor(p)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, subject := range []string{"mesh.seat.node-launcher.tool.secret.laptop", "mesh.seat.node-launcher.tool.secret",
|
|
"mesh.mod.rofi.tool.node-launcher.secret", "mesh.mod.rofi.tool.node-launcher.secret.laptop"} {
|
|
if broker.MayPublish(perms, subject) {
|
|
t.Errorf("%s may publish %s", p.Username(), subject)
|
|
}
|
|
}
|
|
}
|
|
perms, _ := broker.PermissionsFor(broker.Principal{Kind: broker.KindController})
|
|
if !broker.MayPublish(perms, "mesh.seat.node-launcher.tool.secret.laptop") {
|
|
t.Error("the controller may not ask the desk's prompt")
|
|
}
|
|
}
|
|
|
|
// A value for a secret comes from the terminal or the desk, never through a verb (the review of 2026-10-09,
|
|
// M4): `secret accept` with a value, run for a verb, is refused before anything is read.
|
|
func TestASecretValueIsNeverAcceptedThroughAVerb(t *testing.T) {
|
|
t.Setenv(verbVar, "mesh-controller.command")
|
|
for _, args := range [][]string{
|
|
{"accept", "anchor", "telegram", "telegram-token", "--from", "/dev/null"},
|
|
{"accept", "anchor", "app", "db", "--from", "/dev/null", "--provider", "store"},
|
|
} {
|
|
err := secretCommand(context.Background(), args)
|
|
if err == nil || !strings.Contains(err.Error(), "never through a verb") {
|
|
t.Errorf("%v: %v", args, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The `give` verb's own line passes the terminal-only rule of ADR 0266, and no other `secret accept` does: a
|
|
// value, a file, a provider or an extra word is still the terminal's alone.
|
|
func TestOnlyTheGiveLinePassesTheTerminalRuleForSecrets(t *testing.T) {
|
|
if err := terminalOnly([]string{"secret", "accept", "anchor", "telegram", "telegram-token", "--at-desk", "laptop"}); err != nil {
|
|
t.Errorf("give's line refused: %v", err)
|
|
}
|
|
for _, argv := range [][]string{
|
|
{"secret", "accept", "anchor", "telegram", "telegram-token"},
|
|
{"secret", "accept", "anchor", "telegram", "telegram-token", "--from", "/tmp/x"},
|
|
{"secret", "accept", "anchor", "telegram", "telegram-token", "--at-desk", "laptop", "--local"},
|
|
{"secret", "accept", "anchor", "telegram", "--provider", "--at-desk", "laptop"},
|
|
{"secret", "export", "anchor", "telegram", "telegram-token", "--at-desk", "laptop"},
|
|
} {
|
|
if err := terminalOnly(argv); err == nil {
|
|
t.Errorf("%v passed the terminal rule", argv)
|
|
}
|
|
}
|
|
}
|