Files
mesh-delivery/contracts/go/clients/meshdeliverycheckerclient/input.go
T
jschoubben d5d9f0c258 The domain SDK carries the run ask's rules and the checker's client asks a program's input (issue 1921, milestone 47/G D2)
B0's mesh-sdk go/delivery run lines move to their registry homes: the
run job, the one-job rule, the Go check stream alone, the input's bound,
digest and key in sdk/buildstep; AskWhat's run case in sdk/buildrun; the
ask of the verb input and the check of a verdict's judged-by in
meshdeliverycheckerclient. B0's tests come in as rows of the existing
tables.

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
2026-11-07 02:35:31 +01:00

54 lines
2.2 KiB
Go

package meshdeliverycheckerclient
import (
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
checker "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshdeliverychecker"
)
// InputVerb is the seat's verb input as a manifest's `invokes` names it and a run ask's input names it: asked of the
// seat, on no one machine (novox/hq ADR 0644, ADR 0656; issue 1921). A checking program's input is kept by the checker
// by the sha256 of its exact bytes, and asked of it by the build module that runs the program (ADR 0596 §2).
const InputVerb = "seat:" + checker.Seat + "." + checker.VerbInput
// InputAnswerOf is the verb input's answer for body: its digest and its exact bytes, base64.
func InputAnswerOf(body []byte) checker.InputAnswer {
return checker.InputAnswer{Digest: DigestOf(body), Input: base64.StdEncoding.EncodeToString(body)}
}
// DigestOf is the digest a checking program's input is kept and asked by: the sha256 of its bytes, 64 lowercase hex
// digits.
func DigestOf(body []byte) string {
sum := sha256.Sum256(body)
return hex.EncodeToString(sum[:])
}
// ReadInput asks the verb input, with ask (a tools bundle's stdio.Ask, a process's Conn.Call), for the input kept by
// digest and answers its bytes, refusing an answer for another digest and bytes whose sha256 is not the digest.
func ReadInput(ask func(key string, body any) (json.RawMessage, error), digest string) ([]byte, error) {
const who = "meshdeliverycheckerclient: "
raw, err := ask(InputVerb, checker.InputInput{Digest: digest})
if err != nil {
return nil, fmt.Errorf(who+"asking %s for the input %s: %w", InputVerb, digest, err)
}
var a checker.InputAnswer
if err := json.Unmarshal(raw, &a); err != nil {
return nil, fmt.Errorf(who+"%s answered no input for %s: %w", InputVerb, digest, err)
}
if a.Digest != digest {
return nil, fmt.Errorf(who+"%s answered the input %q, asked %s", InputVerb, a.Digest, digest)
}
body, err := base64.StdEncoding.DecodeString(a.Input)
if err != nil {
return nil, fmt.Errorf(who+"%s answered the input %s in no base64: %w", InputVerb, digest, err)
}
if got := DigestOf(body); got != digest {
return nil, fmt.Errorf(who+"the input %s answered %d bytes whose digest is %s", digest, len(body), got)
}
return body, nil
}