nox records the hand act a sensitive vault verb is warranted by

Each sensitive vault verb judges its own caller, and nox reaches the vault
as its machine's runtime, never as a person, so it could use none of them.
Before rotate, retire approve, cleanup delete and secret export nox records
the act through mesh-hand-acts (the vault verb as its verb, what it acts on
as its what) and names it as act; a refused recording calls the vault not at
all (ADR 0590 §8, issue 1126 review 1).

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
2026-11-02 12:29:56 +01:00
parent 344fc6f6bf
commit 0f0ec66e9a
4 changed files with 128 additions and 10 deletions
@@ -70,3 +70,26 @@ func TestTheSensitiveToolsRefuseACallerTheyDoNotJudgeTheirs(t *testing.T) {
t.Errorf("a listing without sealed copies was refused: %v", err)
}
}
// Review 1 of issue 1126: nox reaches the vault as its machine's runtime (`<node>.node-tools`), never as a person; it
// records the hand act first and names it, and so the export answers it, and refuses it without.
func TestNoxsRuntimeExportsWithItsHandActAndIsRefusedWithout(t *testing.T) {
v := newVault(t, nil)
if _, err := v.Put("pair/postgres/gitea", "x", "the test"); err != nil {
t.Fatal(err)
}
v.ReadAct = func(id string) (*HandActSeen, error) {
if id != "nox-1" {
return nil, nil
}
return &HandActSeen{ID: id, By: "shanks.node-tools", At: v.Now(), Verb: "mesh-vault." + SensitiveVaultExport,
Args: []string{"the vault's sealed copies"}}, nil
}
export := toolNamed(t, definitions(&Env{Vault: v.Vault}), SensitiveVaultExport)
if _, err := export.runAs("shanks.node-tools", map[string]any{}); err == nil || !strings.Contains(err.Error(), "named none") {
t.Errorf("an export with no act: %v", err)
}
if _, err := export.runAs("shanks.node-tools", map[string]any{"act": "nox-1"}); err != nil {
t.Errorf("an export with nox's act: %v", err)
}
}