From b4584b0313cb20fe8d24f4fb6aad6a3fc3afc47e Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 4 Nov 2026 13:32:55 +0100 Subject: [PATCH] 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 --- .../cmd/distribution-tools/main.go | 21 +----- .../distribution/internal/holder/callers.go | 68 +++++-------------- 2 files changed, 20 insertions(+), 69 deletions(-) diff --git a/modules/distribution/cmd/distribution-tools/main.go b/modules/distribution/cmd/distribution-tools/main.go index 44216a29..4c216f21 100644 --- a/modules/distribution/cmd/distribution-tools/main.go +++ b/modules/distribution/cmd/distribution-tools/main.go @@ -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) diff --git a/modules/distribution/internal/holder/callers.go b/modules/distribution/internal/holder/callers.go index 1078d6eb..4c6dfc2f 100644 --- a/modules/distribution/internal/holder/callers.go +++ b/modules/distribution/internal/holder/callers.go @@ -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.` (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 `.`. -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) }