From 1390836b734baeddf051802b985230bbe79df64a Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 11 Oct 2026 00:53:37 +0200 Subject: [PATCH] A kept call holds a command's first word, never the line (issue 397) kept() withheld the arguments line, values, secret and stdin, and kept the command argument of the generic command verb verbatim. A line such as `settings set '' --node ` therefore put the value into the calls record, which answers anyone who may call the seat. It is now kept as a mesh-cli line is: its first word, with the rest said to have been given. A command of one word is kept whole, since there is nothing after it to withhold, and one that is not a string is kept as "(given, not kept)". The record as it stands holds no such line: its whole answer, read at 2026-10-10 22:52 UTC, carries no call of the command verb. That says nothing of calls older than its window. --- internal/link/calls.go | 14 ++++++++++++++ internal/link/calls_test.go | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/internal/link/calls.go b/internal/link/calls.go index 1698df15..47896445 100644 --- a/internal/link/calls.go +++ b/internal/link/calls.go @@ -468,6 +468,20 @@ func kept(args json.RawMessage) json.RawMessage { if words, ok := v.([]any); ok && len(words) > 0 { out[k] = []any{words[0], "(the rest given, not kept)"} } + case k == "command": + // The controller's own command line, kept as `line` is: its first word, never the rest. + // `settings set '' --node ` through the `command` verb put the value + // itself in this record, which answers anyone who may call the seat (novox/hq issue 397). + if !isString { + out[k] = "(given, not kept)" + break + } + first, rest, _ := strings.Cut(strings.TrimSpace(s), " ") + if strings.TrimSpace(rest) == "" { + out[k] = first + break + } + out[k] = first + " (the rest given, not kept)" case isString && len(s) <= 120: out[k] = s case isString: diff --git a/internal/link/calls_test.go b/internal/link/calls_test.go index 9c2d83fd..2488e88b 100644 --- a/internal/link/calls_test.go +++ b/internal/link/calls_test.go @@ -166,6 +166,43 @@ func TestACallKeepsNoSettingsOrSecrets(t *testing.T) { } } +// A command line's own words may carry a setting's value or a secret, so only its first word is kept +// — as a mesh-cli line's is (novox/hq issue 397). +func TestACallKeepsNoCommandLine(t *testing.T) { + for _, line := range []string{ + `settings set notes 'the operator's own passphrase' --node laptop`, + `settings set notes --values {"token":"s3cret"}`, + ` node show laptop`, + } { + raw, err := json.Marshal(map[string]any{"command": line}) + if err != nil { + t.Fatal(err) + } + got := string(kept(raw)) + // "set" is left out: it is a part of "settings", the word that is kept. + for _, never := range []string{"passphrase", "s3cret", "notes", "laptop", "show"} { + if strings.Contains(got, never) { + t.Errorf("kept %s of %q: it carries %q", got, line, never) + } + } + if !strings.Contains(got, "(the rest given, not kept)") { + t.Errorf("kept %s of %q: it does not say the rest was given", got, line) + } + } + + // A command of one word is the whole of it: a reading command with no arguments stays readable. + raw, _ := json.Marshal(map[string]any{"command": "builds"}) + if got := string(kept(raw)); got != `{"command":"builds"}` { + t.Errorf("kept %s; a command of one word carries no value to withhold", got) + } + + // Not a string, so its first word cannot be taken: none of it is kept. + raw, _ = json.Marshal(map[string]any{"command": []string{"settings", "set", "notes", "s3cret"}}) + if got := string(kept(raw)); strings.Contains(got, "s3cret") { + t.Errorf("kept %s", got) + } +} + // Only the newest KeptCalls are kept. func TestTheLogKeepsTheNewest(t *testing.T) { l := NewCallLog()