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
54 lines
2.2 KiB
Go
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
|
|
}
|