mesh-sdk holds neither asks nor asker, nor the vault's answer types, and mesh-delivery's sdk/views is mesh-sdk's go/views (a1-progress.md, the rewrite map for the join): thirteen modules switch to the operatorchannel contract and client, mesh-sdk's channel package and meshvault, with go.mod requiring each at the group pin (nats: meshbroker too). The gate holds the checks mesh-sdk dropped (an ask's id is its key's asking, at least one option), with a row that fails without them; claude-code refuses a router record whose times do not parse, as its JSON decode did, with a row. Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
72 lines
2.8 KiB
Go
72 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
occ "git.novox.be/novox/mesh-contracts/go/clients/operatorchannelclient"
|
|
oc "git.novox.be/novox/mesh-contracts/go/seats/operatorchannel"
|
|
stdio "git.novox.be/novox/mesh-sdk/go"
|
|
|
|
"nats-tools/internal/keeper"
|
|
)
|
|
|
|
// A person's acting tools hand their request to the keeper (design 25 § 12.3; CAT-N8): stamped with the caller the
|
|
// tool runner proved, whatever name the arguments give; a create's end read back; a drop raises the operator's ask
|
|
// first, binding exactly that act, and is not acted on by the tool.
|
|
func TestAPersonsRequestIsHandedToTheKeeperAsTheProvedCaller(t *testing.T) {
|
|
held := map[string]keeper.Request{}
|
|
var raised []oc.Ask
|
|
rs := requestStore{
|
|
Put: func(key string, r keeper.Request) error {
|
|
if r.Verb == keeper.VerbCreate {
|
|
// The keeper's end, as its watch writes it.
|
|
r.Done, r.Outcome = time.Unix(1, 0), "created"
|
|
}
|
|
held[key] = r
|
|
return nil
|
|
},
|
|
Get: func(key string) (*keeper.Request, error) {
|
|
r, ok := held[key]
|
|
if !ok {
|
|
return nil, nil
|
|
}
|
|
return &r, nil
|
|
},
|
|
Ask: func(a oc.Ask) error { raised = append(raised, a); return nil },
|
|
Now: func() time.Time { return time.Date(2026, 11, 4, 12, 0, 0, 0, time.UTC) },
|
|
Wait: func(time.Duration) {},
|
|
}
|
|
tools := map[string]stdio.Tool{}
|
|
for _, tl := range requestTools(rs) {
|
|
tools[tl.Name] = tl
|
|
}
|
|
out, err := tools["nats_create"].Run(map[string]any{"module": "m", "local": "log", "why": "a test", "caller": "person.mallory"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if r := out.(*keeper.Request); r.Caller != stdio.Unproven || r.Outcome != "created" {
|
|
t.Errorf("answered %+v: acted for the caller the runtime proved (here none, %q), never person.mallory", r, stdio.Unproven)
|
|
}
|
|
out, err = tools["nats_drop"].Run(map[string]any{"module": "m", "local": "old", "why": "no manifest asks for it"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
answer := out.(map[string]any)
|
|
r := held[answer["request"].(string)]
|
|
if len(raised) != 1 || r.Ask != raised[0].ID || !r.Done.IsZero() {
|
|
t.Fatalf("raised %+v, held %+v: the ask raised, the request waiting for it", raised, r)
|
|
}
|
|
binds, _ := occ.ActDigest(occ.Act{"verb": "drop", "module": "m", "local": "old"})
|
|
if o, _ := occ.OptionOf(raised[0], "go"); o.Level != occ.Destroy || o.Binds != binds || !strings.Contains(raised[0].Explanation, "snapshot") {
|
|
t.Errorf("the ask is %+v: its option destroys exactly this drop, after a snapshot", raised[0])
|
|
}
|
|
if _, err := tools["nats_drop"].Run(map[string]any{"module": "m", "local": "old"}); err == nil || !strings.Contains(err.Error(), "says why") {
|
|
t.Errorf("a drop without why: %v", err)
|
|
}
|
|
if got, _ := tools["nats_drop"].Run(map[string]any{"request": r.ID}); got.(*keeper.Request).ID != r.ID {
|
|
t.Errorf("reading the request back answered %+v", got)
|
|
}
|
|
}
|