BLD14: a run's input is asked of the verb the asker's ask names

The Go build module asks the input verb in the ask (the checker's, the
indexer's mesh-catalog input or the assigner's mesh-wants input) and its
manifest invokes the two seats' verbs. The bus refuses the other accounts
(grants of the contract's callers). The step key keeps the contract's form
<node>.<id>: no asker part is named there (question to the lead).

Builds: design 47 G §125, §206, §338, §354

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
2026-11-11 11:02:03 +01:00
parent 357967308f
commit dfb682fa33
3 changed files with 48 additions and 2 deletions
@@ -63,8 +63,10 @@ func (m *Module) inputOf(in sdkstep.RunInput) ([]byte, error) {
}
// A verb that does not answer fails the step; an answer that is not the input named refuses the ask.
var askErr error
raw, err := checkerclient.ReadInput(func(key string, body any) (json.RawMessage, error) {
out, err := m.AskInput(key, body)
// The verb is the one the asker's ask names: the runner's, the indexer's (mesh-catalog's input) or the assigner's
// (mesh-wants' input) own, each serving the input by its digest alike (design 47 G §125, §206, §338, §354).
raw, err := checkerclient.ReadInput(func(_ string, body any) (json.RawMessage, error) {
out, err := m.AskInput(in.Verb, body)
askErr = err
return out, err
}, in.Digest)
@@ -10,6 +10,7 @@ import (
"fmt"
"os"
"path/filepath"
"slices"
"strings"
"testing"
"time"
@@ -154,3 +155,44 @@ func TestAComposeAskKeepsItsSeats(t *testing.T) {
t.Fatalf("the composer did not receive the seats: %+v %v", v, err)
}
}
// Design 47 G §125, §206, §338, §354 (BLD14): a run's input is asked of the verb the ask names, so the indexer's and the
// assigner's runs read their own seat's input, and the manifest invokes both.
func TestARunsInputIsAskedOfTheVerbTheAskNames(t *testing.T) {
for _, verb := range []string{"seat:mesh-catalog.input", "seat:mesh-wants.input", runInputVerb} {
m := composeModule(t)
body := `{"v":1}`
var asked []string
m.AskInput = func(key string, b any) (json.RawMessage, error) {
asked = append(asked, key)
return answersInputOn(verb, body)(key, b)
}
a := runAskOf(t, body)
in, err := sdkstep.RunInputOf(verb, []byte(body))
if err != nil {
t.Fatal(err)
}
a.Run.Input = in
got, err := m.inputOf(a.Run.Input)
if err != nil || string(got) != body || len(asked) != 1 || asked[0] != verb {
t.Errorf("%s: input %q, err %v, asked %v", verb, got, err, asked)
}
}
doc := readManifest(t)
for _, verb := range []string{"seat:mesh-catalog.input", "seat:mesh-wants.input"} {
if !slices.Contains(doc.Invokes, verb) {
t.Errorf("the manifest does not invoke %s: %v", verb, doc.Invokes)
}
}
}
// answersInputOn is answersInput for the seat verb wanted.
func answersInputOn(wanted, body string) func(key string, b any) (json.RawMessage, error) {
return func(key string, b any) (json.RawMessage, error) {
ask, _ := b.(checker.InputInput)
if sum := sha256.Sum256([]byte(body)); key != wanted || ask.Digest != hex.EncodeToString(sum[:]) {
return nil, fmt.Errorf("%s keeps no input %s", key, ask.Digest)
}
return json.Marshal(checkerclient.InputAnswerOf([]byte(body)))
}
}
+2
View File
@@ -34,6 +34,8 @@
"seat:go-package-registry.publish",
"seat:go-package-registry.publish-part",
"seat:mesh-delivery-checker.input",
"seat:mesh-catalog.input",
"seat:mesh-wants.input",
"seat:mesh-module-assigner.assignments"
],
"config": {