Let the give verb's exact line past the terminal rule for secrets, and nothing else (hq ADR 0259 §10, ADR 0266)

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.
This commit is contained in:
2026-10-09 16:22:47 +02:00
parent be59f29f46
commit ed331eb972
2 changed files with 37 additions and 2 deletions
+19
View File
@@ -226,3 +226,22 @@ func TestASecretValueIsNeverAcceptedThroughAVerb(t *testing.T) {
}
}
}
// 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)
}
}
}
+18 -2
View File
@@ -1500,6 +1500,20 @@ var terminalOnlyCommands = map[string]string{
"licence": "the licences' secrets",
}
// givenAtTheDesk is exactly the line the `give` verb composes, and nothing beside it: `secret accept <node>
// <module> <secret> --at-desk <machine>`, with no other word — no value, no file, no provider.
func givenAtTheDesk(argv []string) bool {
if len(argv) != 7 || argv[0] != "secret" || argv[1] != "accept" || argv[5] != "--at-desk" {
return false
}
for _, w := range argv[2:5] {
if w == "" || strings.HasPrefix(w, "-") {
return false
}
}
return argv[6] != "" && !strings.HasPrefix(argv[6], "-")
}
// terminalOnly refuses, through any verb, a command that is the operator's at the controller's terminal
// alone (novox/hq ADR 0266). **Every `node` subcommand that is not a read**: `node account` and
// `node agent-account` above all. Whoever may call a verb includes agents, and an agent that named itself
@@ -1513,8 +1527,10 @@ func terminalOnly(argv []string) error {
return terminalRefusal("%s is run at the controller's terminal only, never through a verb: it holds %s, and "+
"whoever may call a verb includes agents (novox/hq ADR 0266). Nothing was done", argv[0], what)
}
// Of a secret's commands only rotation, which seals the new value to the machine that uses it.
if argv[0] == "secret" && (len(argv) < 2 || argv[1] != "rotate") {
// Of a secret's commands only rotation, which seals the new value to the machine that uses it, and the
// `give` verb's own line: an own secret typed by the operator into the desk's hidden prompt, sealed to this
// call and then to the module's machine, so no value travels in the verb or its answer (hq ADR 0259 §10).
if argv[0] == "secret" && (len(argv) < 2 || argv[1] != "rotate") && !givenAtTheDesk(argv) {
return terminalRefusal("secret %s is run at the controller's terminal only, never through a verb: accepting, "+
"recovering or exporting a secret hands it to whoever asks, and that includes agents (novox/hq ADR "+
"0266). Nothing was done", strings.Join(argv[1:], " "))