From 25e5d00aba9896d51f8c615d0b0bc10304ee00f9 Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 4 Nov 2026 12:12:54 +0100 Subject: [PATCH] CAT-V1: retire takes ask beside warrant, as the seat definition now has it Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig --- .../mesh-config/cmd/mesh-config/delivery.go | 2 +- .../cmd/mesh-vault/enrolment_tools.go | 5 ++-- .../cmd/mesh-vault/mint_integration_test.go | 2 +- .../mesh-vault/cmd/mesh-vault/ownretire.go | 15 ++++++---- .../mesh-vault/cmd/mesh-vault/retire_test.go | 28 ++++++++++--------- 5 files changed, 29 insertions(+), 23 deletions(-) diff --git a/modules/mesh-config/cmd/mesh-config/delivery.go b/modules/mesh-config/cmd/mesh-config/delivery.go index 2698bbe2..a2c3a5cd 100644 --- a/modules/mesh-config/cmd/mesh-config/delivery.go +++ b/modules/mesh-config/cmd/mesh-config/delivery.go @@ -127,6 +127,6 @@ func (v toolVault) Retire(r RetireRequest) error { if json.Unmarshal(answer, &rec) != nil || rec.Act.ID == "" { return fmt.Errorf("mesh-hand-acts recorded the warrant and named no act") } - _, err = v.ask(VaultRetireAsk, map[string]any{"node": r.Node, "module": r.Module, "name": r.Name, "warrant": rec.Act.ID}) + _, err = v.ask(VaultRetireAsk, map[string]any{"node": r.Node, "module": r.Module, "name": r.Name, "warrant": rec.Act.ID, "ask": r.Ask}) return err } diff --git a/modules/mesh-vault/cmd/mesh-vault/enrolment_tools.go b/modules/mesh-vault/cmd/mesh-vault/enrolment_tools.go index 3eda041d..a976eb3b 100644 --- a/modules/mesh-vault/cmd/mesh-vault/enrolment_tools.go +++ b/modules/mesh-vault/cmd/mesh-vault/enrolment_tools.go @@ -135,14 +135,15 @@ func enrolmentTools(env *Env) []toolDef { "through mesh-hand-acts for this verb naming exactly this node, module and name and the ask of the operator's Approve " + "(`warrant`, the act's id), read back here.", Input: map[string]any{"node": node, "module": str("the module whose secret it is"), "name": str("the secret's name"), - "warrant": str("the operator's warrant for this node, module and name: the id of the hand act recorded through mesh-hand-acts")}, + "warrant": str("the operator's warrant for this node, module and name: the id of the hand act recorded through mesh-hand-acts"), + "ask": str("the id of the operator's ask the warrant answers")}, run: func(caller string, a map[string]any) (any, error) { v, err := env.ready() if err != nil { return nil, err } return v.RetireOwn(caller, RetireArgs{Node: arg(a, "node"), Module: arg(a, "module"), Name: arg(a, "name"), - Warrant: arg(a, "warrant")}) + Warrant: arg(a, "warrant"), Ask: arg(a, "ask")}) }}, {Name: "node_logins", Description: "Every node's key of the vault's state node-logins: the login its node-engine dials as and, while a rotation " + diff --git a/modules/mesh-vault/cmd/mesh-vault/mint_integration_test.go b/modules/mesh-vault/cmd/mesh-vault/mint_integration_test.go index cad6ea00..1ec93240 100644 --- a/modules/mesh-vault/cmd/mesh-vault/mint_integration_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/mint_integration_test.go @@ -547,7 +547,7 @@ func TestTheVaultWholeMintsOnTheBusWhoeverHoldsTheLease(t *testing.T) { t.Fatalf("a refused retire said %s", m.Subject) } // The call is the definition's input, the answer its answer, and the event its body on its subject (CAT-V4). - input, _ := json.Marshal(meshvault.RetireInput{Node: "g14", Module: "dunst", Name: "token", Warrant: "act-ok"}) + input, _ := json.Marshal(meshvault.RetireInput{Node: "g14", Module: "dunst", Name: "token", Warrant: "act-ok", Ask: "ret-1"}) var args map[string]any _ = json.Unmarshal(input, &args) raw, err = p.call(Seat+"."+meshvault.VerbRetire, "novox.mesh-config", args) diff --git a/modules/mesh-vault/cmd/mesh-vault/ownretire.go b/modules/mesh-vault/cmd/mesh-vault/ownretire.go index ce265be6..b85d1936 100644 --- a/modules/mesh-vault/cmd/mesh-vault/ownretire.go +++ b/modules/mesh-vault/cmd/mesh-vault/ownretire.go @@ -27,10 +27,10 @@ const OwnRetiredEvent = "own-retired" // RetireVerb is the seat's verb, and the verb of the hand act that warrants it (`mesh-vault.retire`). const RetireVerb = "retire" -// RetireArgs are `retire`'s arguments, as the seat's definition names them: the secret by node, module and name, and the -// warrant, the id of the hand act that warrants it. +// RetireArgs are `retire`'s arguments, as the seat's definition names them: the secret by node, module and name, the +// warrant (the id of the hand act that warrants it) and the ask of the operator's Approve it answers. type RetireArgs struct { - Node, Module, Name, Warrant string + Node, Module, Name, Warrant, Ask string } // OwnRetiredBody is the body of own-retired, exactly the seat definition's (node, module, name, ask, caller). @@ -62,6 +62,9 @@ func (v *Vault) fromRetireCallers(caller string) error { // warrantsRetire reads the hand act back and refuses what it does not warrant for exactly this secret; it answers the // ask the act names. func (v *Vault) warrantsRetire(caller string, a RetireArgs) (ask string, err error) { + if strings.TrimSpace(a.Ask) == "" { + return "", fmt.Errorf("retire names the ask of the operator's Approve it answers (`ask`)") + } if strings.TrimSpace(a.Warrant) == "" { return "", fmt.Errorf("retire carries the hand act that warrants it (`warrant`): record it through mesh-hand-acts first (design 32)") } @@ -87,9 +90,9 @@ func (v *Vault) warrantsRetire(caller string, a RetireArgs) (ask string, err err named = append(named, strings.Fields(arg)...) } // The warrant is bound to the node, module and name it was asked for, and names the ask: those four words, no others. - if len(named) != 4 || named[0] != a.Node || named[1] != a.Module || named[2] != a.Name { - return "", fmt.Errorf("the hand act %s names %q, not %s %s %s and its ask: a warrant retires nothing else", - a.Warrant, strings.Join(named, " "), a.Node, a.Module, a.Name) + if len(named) != 4 || named[0] != a.Node || named[1] != a.Module || named[2] != a.Name || named[3] != a.Ask { + return "", fmt.Errorf("the hand act %s names %q, not %s %s %s and ask %s: a warrant retires nothing else", + a.Warrant, strings.Join(named, " "), a.Node, a.Module, a.Name, a.Ask) } return named[3], nil } diff --git a/modules/mesh-vault/cmd/mesh-vault/retire_test.go b/modules/mesh-vault/cmd/mesh-vault/retire_test.go index 7dd42b7d..61376480 100644 --- a/modules/mesh-vault/cmd/mesh-vault/retire_test.go +++ b/modules/mesh-vault/cmd/mesh-vault/retire_test.go @@ -115,17 +115,19 @@ func TestRetireRemovesAnOwnSecretOnlyOnTheWarrantOfTheListedCaller(t *testing.T) args RetireArgs want string }{ - {"no act", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token"}, "carries the hand act"}, - {"an act that does not exist", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "nope"}, "holds no hand act"}, - {"an act for another name", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "other-name"}, "a warrant retires nothing else"}, - {"an act for another node", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "other-node"}, "a warrant retires nothing else"}, - {"an act of another caller", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "other-caller"}, "was recorded by g14.claude-code"}, - {"an act for another verb", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "other-verb"}, "warrants no retirement"}, - {"an act that names no ask", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "no-ask"}, "a warrant retires nothing else"}, - {"an act older than a day", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "old"}, "older than"}, - {"a caller not on the list", "g14.claude-code", RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "other-caller"}, "retire-callers"}, - {"an unproven caller", stdio.Unproven, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "ok"}, "retire-callers"}, - {"the tool runner's ledgers", caller, RetireArgs{Node: "g14", Module: "node-tools", Name: "ledgers", Warrant: "ledgers"}, "bus account or the tool runner's ledgers"}, + {"no act", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Ask: "ret-1"}, "carries the hand act"}, + {"an act that does not exist", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "nope", Ask: "ret-1"}, "holds no hand act"}, + {"an act for another name", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "other-name", Ask: "ret-1"}, "a warrant retires nothing else"}, + {"an act for another node", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "other-node", Ask: "ret-1"}, "a warrant retires nothing else"}, + {"an act of another caller", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "other-caller", Ask: "ret-1"}, "was recorded by g14.claude-code"}, + {"an act for another verb", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "other-verb", Ask: "ret-1"}, "warrants no retirement"}, + {"an ask other than the act's", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "ok", Ask: "ret-2"}, "a warrant retires nothing else"}, + {"no ask", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "ok"}, "names the ask"}, + {"an act that names no ask", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "no-ask", Ask: "ret-1"}, "a warrant retires nothing else"}, + {"an act older than a day", caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "old", Ask: "ret-1"}, "older than"}, + {"a caller not on the list", "g14.claude-code", RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "other-caller", Ask: "ret-1"}, "retire-callers"}, + {"an unproven caller", stdio.Unproven, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "ok", Ask: "ret-1"}, "retire-callers"}, + {"the tool runner's ledgers", caller, RetireArgs{Node: "g14", Module: "node-tools", Name: "ledgers", Warrant: "ledgers", Ask: "ret-1"}, "bus account or the tool runner's ledgers"}, } { t.Run(tc.name, func(t *testing.T) { before := len(v.bus.events) @@ -141,7 +143,7 @@ func TestRetireRemovesAnOwnSecretOnlyOnTheWarrantOfTheListedCaller(t *testing.T) }) } before := len(v.bus.events) - got, err := v.RetireOwn(caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "ok"}) + got, err := v.RetireOwn(caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "ok", Ask: "ret-1"}) if err != nil || !got.Retired { t.Fatalf("retire answered %+v, %v", got, err) } @@ -162,7 +164,7 @@ func TestRetireRemovesAnOwnSecretOnlyOnTheWarrantOfTheListedCaller(t *testing.T) t.Error("own-retired shares a name with an event a waiter hears") } // Asked again for what is gone: nothing to retire. - if _, err := v.RetireOwn(caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "ok"}); err == nil || + if _, err := v.RetireOwn(caller, RetireArgs{Node: "g14", Module: "dunst", Name: "token", Warrant: "ok", Ask: "ret-1"}); err == nil || !strings.Contains(err.Error(), "nothing to retire") { t.Errorf("a second retire answered %v", err) }