CAT-D2: distribution's caller list and its question to the builder are mesh-sdk's shared parts

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-04 13:32:55 +01:00
parent c6c046283d
commit b4584b0313
2 changed files with 20 additions and 69 deletions
@@ -19,6 +19,7 @@ import (
reg "git.novox.be/novox/mesh-contracts/go/seats/containerimageregistry"
stdio "git.novox.be/novox/mesh-sdk/go"
"git.novox.be/novox/mesh-sdk/go/delivery"
"git.novox.be/novox/mesh-sdk/go/health"
"git.novox.be/novox/mesh-sdk/go/parts"
@@ -60,24 +61,6 @@ func (k kept[T]) List() ([]T, error) {
return out, nil
}
// builderVersions asks the builder's builder_versions (ADR 0605 §4).
type builderVersions struct{}
func (builderVersions) Recorded(name, version, digest string) (bool, string, error) {
raw, err := stdio.Ask("mesh-delivery-builder.builder_versions", map[string]any{"name": name, "version": version, "digest": digest})
if err != nil {
return false, "", err
}
var a struct {
Recorded *bool `json:"recorded"`
Why string `json:"why"`
}
if err := json.Unmarshal(raw, &a); err != nil || a.Recorded == nil {
return false, "", fmt.Errorf("builder_versions answered no recorded: %s", raw)
}
return *a.Recorded, a.Why, nil
}
func say(seat, event string, body holder.Event) error {
return stdio.SeatPublish("mesh.seat."+seat+".event."+event, eventBody(event, body), body.ID)
}
@@ -438,7 +421,7 @@ func main() {
}
base, _ := url.Parse("http://127.0.0.1:5001")
store := &holder.OCI{Base: base, Registry: os.Getenv("MESH_REGISTRY_REACH"), Upstream: &holder.Upstream{}}
h := &holder.Holder{Callers: callers, Objects: parts.BusObjects(holder.IncomingObjects), Builder: builderVersions{}, Store: store, Say: say, Finding: finding,
h := &holder.Holder{Callers: callers, Objects: parts.BusObjects(holder.IncomingObjects), Builder: delivery.BuilderVersions{Ask: stdio.Ask}, Store: store, Say: say, Finding: finding,
Transfers: parts.BusTransfers[holder.Opening](holder.TransfersState)}
v := &holder.Verbs{Holder: h, Catalog: store, Holds: kept[holder.Hold]{state: "holds", key: holder.Hold.Key}, Mirrors: mirrors{}}
go followMirrors(v)
+18 -50
View File
@@ -7,11 +7,11 @@
package holder
import (
"encoding/json"
"fmt"
"slices"
"sort"
"strings"
stdio "git.novox.be/novox/mesh-sdk/go"
)
// The seats distribution holds, and the old one it holds until its window closes.
@@ -46,10 +46,10 @@ func VerbsOf(seat string) []string {
return v
}
// Callers is the holder's trusted config value `callers` (the form ADR 0363 gives a restricted family): per verb, the
// modules that may call it. The holder checks the caller the tool runner proved and stamped on the request (design 25
// § 12.4), never a name in the request's body.
type Callers map[string][]string
// Callers is the holder's trusted config value `callers`: per verb, the callers that may call it, read as mesh-sdk's
// seat-neutral list per verb reads it (ADR 0627 §2). The holder checks the caller the tool runner proved and stamped on
// the request (design 25 § 12.4), never a name in the request's body.
type Callers = stdio.VerbCallers
// DefaultCallers is the list design 51 *Who may call which verb* names: publish and publish-part the build modules;
// mirror mesh-build-image; remove the builder (a tagged version) and the artifact sweep's holder (retention); hold the
@@ -72,15 +72,12 @@ func DefaultCallers() Callers {
// SweepHolder is the module holding the seat `mesh-artifact-sweep`, the artifact sweep.
const SweepHolder = "artifact-store-tools"
// Anyone on a verb's list lets every proved caller call it.
const Anyone = "*"
// Operator on a list stands for the operator's session, the caller the tool runner proves as `person.<name>` (ADR 0386
// §7): a release by hand through registry_holds carries it on, never distribution's own account.
const Operator = "operator"
// Unproven is the caller the runtime names for a call it could not prove (mesh-sdk stdio.Unproven).
const Unproven = "unproven"
// The entries of a list that stand for a class, and the caller the runtime names for a call it could not prove.
const (
Anyone = stdio.AnyCaller
Operator = stdio.AnyPerson
Unproven = stdio.Unproven
)
// Self is distribution's own account: never on release's list, so registry_holds cannot release in its own name.
const Self = "distribution"
@@ -88,44 +85,15 @@ const Self = "distribution"
// ParseCallers reads the config value; an empty value is DefaultCallers. A verb no seat has is refused, and Self on
// release's list is refused (design 51).
func ParseCallers(raw string) (Callers, error) {
if strings.TrimSpace(raw) == "" {
return DefaultCallers(), nil
c, err := stdio.ParseVerbCallers(raw, VerbsOf(ImageSeat), DefaultCallers())
if err != nil {
return nil, err
}
var c Callers
if err := json.Unmarshal([]byte(raw), &c); err != nil {
return nil, fmt.Errorf("callers is not a JSON object of verb to modules: %w", err)
}
known := VerbsOf(ImageSeat)
for verb, mods := range c {
if !slices.Contains(known, verb) {
return nil, fmt.Errorf("callers names the verb %q, which no seat of distribution's has", verb)
}
if verb == VerbRelease && slices.Contains(mods, Self) {
return nil, fmt.Errorf("callers puts %s on release's list: registry_holds would release in its own name", Self)
}
if slices.Contains(c[VerbRelease], Self) {
return nil, fmt.Errorf("callers puts %s on release's list: registry_holds would release in its own name", Self)
}
return c, nil
}
// Allowed answers nil when caller may call verb, else the refusal naming the verb and the caller.
func (c Callers) Allowed(verb, caller string) error {
if caller == "" || caller == Unproven {
return fmt.Errorf("%s: refused: the request carries no caller the tool runner proved", verb)
}
person := strings.HasPrefix(caller, "person.")
for _, m := range c[verb] {
switch {
case m == Anyone, m == Operator && person, !person && m == CallerModule(caller):
return nil
}
}
return fmt.Errorf("%s: refused for %s: not on the holder's caller list for %s", verb, caller, verb)
}
// CallerModule is the module of a proved module caller, which the runtime stamps `<node>.<module>`.
func CallerModule(proved string) string {
if i := strings.LastIndexByte(proved, '.'); i >= 0 {
return proved[i+1:]
}
return proved
}
func CallerModule(proved string) string { return stdio.ModuleOf(proved) }