From 4b9558f19591ee46611d93f52114a94660f8ec9b Mon Sep 17 00:00:00 2001 From: jochen Date: Sat, 10 Oct 2026 14:24:15 +0200 Subject: [PATCH] rofi: the desk's secret prompt names who asked (hq ADR 0277) The controller's secret-ask verb opens the launcher's hidden prompt from anywhere on the mesh, so the operator must know whose ask they are typing into. The prompt takes an optional asked_by, the controller's word on the bus's caller held to a name's characters and spaces, and says it; a sentence, markup or a line break is refused, so the prompt's words stay the launcher's. --- modules/rofi/cmd/rofi-tools/secret.go | 28 ++++++++++++++++-- modules/rofi/cmd/rofi-tools/secret_test.go | 34 ++++++++++++++++++---- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/modules/rofi/cmd/rofi-tools/secret.go b/modules/rofi/cmd/rofi-tools/secret.go index 535bd681..d6fe7164 100644 --- a/modules/rofi/cmd/rofi-tools/secret.go +++ b/modules/rofi/cmd/rofi-tools/secret.go @@ -41,6 +41,11 @@ type SecretAnswer struct { // aName is a module's, a secret's or a machine's name as the mesh writes them: nothing else reaches the prompt. 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 +// 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}$`) + // secretQuestion reads the call. The prompt is this holder's words, written from the module, the secret and the // machine (the review of 2026-10-09, M4): it says the mesh's controller asks, which the bus makes true — it // denies these subjects to every principal but the controller — and a caller's own words are refused, so @@ -63,10 +68,27 @@ func secretQuestion(args map[string]any) (SecretQuestion, error) { } names[key] = v } + // Who asked the controller, when it says (novox/hq ADR 0277): the controller's word on the bus's caller, held to a + // name's characters here, so the operator knows whose ask they are typing into — and refuses one they did not start. + askedBy := "" + if raw, there := args["asked_by"]; there { + v, err := text(args, "asked_by", true) + if err != nil { + return q, err + } + if !aCaller.MatchString(v) || strings.Contains(v, " ") { + return q, fmt.Errorf("asked_by %q is not a caller's name as the mesh writes it", raw) + } + askedBy = v + } q.Prompt = names["secret"] + " for " + names["module"] - q.Message = fmt.Sprintf("The mesh's controller asks for %s, the own secret of %s on %s. What you type is not "+ - "shown, and is sealed before it leaves this machine. Type it only if you started this with give.", - names["secret"], names["module"], names["node"]) + q.Message = fmt.Sprintf("The mesh's controller asks for %s, the own secret of %s on %s.", names["secret"], + names["module"], names["node"]) + if askedBy != "" { + q.Message += fmt.Sprintf(" It was asked for by %s.", askedBy) + } + q.Message += " What you type is not shown, and is sealed before it leaves this machine. Type it only if you " + + "expect this ask." key, err := text(args, "seal_to", true) if err != nil { return q, err diff --git a/modules/rofi/cmd/rofi-tools/secret_test.go b/modules/rofi/cmd/rofi-tools/secret_test.go index 15cb2838..3aeaf2de 100644 --- a/modules/rofi/cmd/rofi-tools/secret_test.go +++ b/modules/rofi/cmd/rofi-tools/secret_test.go @@ -108,15 +108,31 @@ func TestThePromptIsWrittenHereFromNamesAndSaysTheControllerAsks(t *testing.T) { if err != nil { t.Fatal(err) } - if q.Prompt != "telegram-token for telegram" || !strings.HasPrefix(q.Message, "The mesh's controller asks for telegram-token") { + if q.Prompt != "telegram-token for telegram" || !strings.HasPrefix(q.Message, "The mesh's controller asks for telegram-token") || + strings.Contains(q.Message, "asked for by") { t.Errorf("prompt %q, message %q", q.Prompt, q.Message) } + // And who asked the controller, when it says so (novox/hq ADR 0277): a caller's name, in a name's characters. + withAsker := map[string]any{} + for k, v := range base { + withAsker[k] = v + } + withAsker["asked_by"] = "g14/claude-code" + q, err = secretQuestion(withAsker) + if err != nil || !strings.Contains(q.Message, "It was asked for by g14/claude-code.") { + t.Errorf("asked_by: %q %v", q.Message, err) + } + withAsker["asked_by"] = "jochen at a shell on novox" + if q, err = secretQuestion(withAsker); err != nil || !strings.Contains(q.Message, "It was asked for by jochen at a shell on novox.") { + t.Errorf("asked_by at a shell: %q %v", q.Message, err) + } for key, value := range map[string]any{ - "prompt": "Your bank's PIN", - "message": "Your bank asks", - "module": "telegram\nYour bank asks", - "secret": "a token", - "node": "anchor", + "prompt": "Your bank's PIN", + "message": "Your bank asks", + "module": "telegram\nYour bank asks", + "secret": "a token", + "node": "anchor", + "asked_by": "the operator. Type your bank's PIN:", } { args := map[string]any{} for k, v := range base { @@ -127,4 +143,10 @@ func TestThePromptIsWrittenHereFromNamesAndSaysTheControllerAsks(t *testing.T) { t.Errorf("%s=%q was taken", key, value) } } + for _, bad := range []string{"", "a\nb", "ac", "a,b", strings.Repeat("a", 81), "a b", "a:b", "a'b"} { + withAsker["asked_by"] = bad + if _, err := secretQuestion(withAsker); err == nil { + t.Errorf("asked_by=%q was taken", bad) + } + } }