// Package holder is distribution's holding of the two image seats, `container-image-registry` and // `oci-artifact-registry`, and of the old seat `mesh-artifact-store` until its window closes (novox/hq design 51 *The // four registry seats*, ADR 0605, ADR 0611, ADR 0617 §2). A build module publishes into a seat through `publish` and // `publish-part`: the parts land in distribution's own object store `incoming`, are hashed, checked against the // builder's `builder_versions` and stored in the artifact store, which listens on its node's loopback; the store's port // is the program's, reads open, writes from its own process alone (front.go). package holder import ( "fmt" "slices" "sort" stdio "git.novox.be/novox/mesh-sdk/go" ) // The seats distribution holds, and the old one it holds until its window closes. const ( ImageSeat = "container-image-registry" ArtifactSeat = "oci-artifact-registry" OldSeat = "mesh-artifact-store" ) // The verbs of the seats (design 26 *A seat's definition*; design 51 *One contract*). const ( VerbPublish = "publish" VerbPublishPart = "publish-part" VerbVersions = "versions" VerbRemove = "remove" VerbMirror = "mirror" VerbTags = "tags" VerbHold = "hold" VerbRelease = "release" ) // Seats are the seats distribution answers verbs on. var Seats = []string{ImageSeat, ArtifactSeat} // VerbsOf are a seat's verbs: mirror and tags on the image seat alone; hold, release and list on both of distribution's. func VerbsOf(seat string) []string { v := []string{VerbPublish, VerbPublishPart, VerbVersions, VerbRemove, VerbHold, VerbRelease, VerbList} if seat == ImageSeat { v = append(v, VerbMirror, VerbTags) } sort.Strings(v) return v } // 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 // artifact sweep's holder alone; release that holder, and the operator's session only through registry_holds (Operator // below). versions, tags and list are read by anyone on the mesh, as the store's reads are. func DefaultCallers() Callers { builds := []string{"mesh-build-go", "mesh-build-image", "mesh-build-node"} return Callers{ VerbPublish: builds, VerbPublishPart: builds, VerbMirror: {"mesh-build-image"}, VerbRemove: {"mesh-delivery-builder", SweepHolder}, VerbHold: {SweepHolder}, VerbRelease: {SweepHolder, Operator}, VerbVersions: {Anyone}, VerbTags: {Anyone}, VerbList: {Anyone}, } } // SweepHolder is the module holding the seat `mesh-artifact-sweep`, the artifact sweep. const SweepHolder = "artifact-store-tools" // 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" // 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) { c, err := stdio.ParseVerbCallers(raw, VerbsOf(ImageSeat), DefaultCallers()) if err != nil { return nil, err } return selfNotReleasing(c) } // ConfiguredCallers is the config value `callers` as mesh-config resolved it for this machine, read through the tools // runtime's stdio.Config on each call (never an environment variable: nothing renders a config value into a // program's environment); unset is DefaultCallers, and Self on release's list is refused as ParseCallers refuses it. func ConfiguredCallers() (Callers, error) { c, err := stdio.ConfiguredVerbCallers(CallersConfig, VerbsOf(ImageSeat), DefaultCallers()) if err != nil { return nil, err } return selfNotReleasing(c) } // CallersConfig is the config value's key, and CallersTool the tools bundle's tool answering it as resolved: the // program, which has no tools runtime, asks that tool over the bus (manifest invokes). const ( CallersConfig = "callers" CallersTool = "registry_callers" ) // WithCallers is v with the caller list c: a copy for one call, so a list read on that call never changes another's. func (v *Verbs) WithCallers(c Callers) *Verbs { h := *v.Holder h.Callers = c out := *v out.Holder = &h return &out } func selfNotReleasing(c Callers) (Callers, error) { 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 } // CallerModule is the module of a proved module caller, which the runtime stamps `.`. func CallerModule(proved string) string { return stdio.ModuleOf(proved) }