From 231566eba80456adb60e7328883d7becf9618c63 Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 4 Nov 2026 12:21:48 +0100 Subject: [PATCH] DLV-B2 sdk: a build ask names each artifact's seat and the version the builder gave it (design 51, A3's request) AskArtifact.Seat, one of the four registry seats, and AskArtifact.Version, which names a seat; an older reader ignores both. Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig --- go/delivery/builder_reference_test.go | 1 - go/delivery/stepasks.go | 24 ++++++++++++++++++++++++ go/delivery/stepasks_test.go | 16 +++++++++++++--- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/go/delivery/builder_reference_test.go b/go/delivery/builder_reference_test.go index 86d6bba..d810b16 100644 --- a/go/delivery/builder_reference_test.go +++ b/go/delivery/builder_reference_test.go @@ -148,4 +148,3 @@ func TestADoneKeyWithNoArtifactIsReferenced(t *testing.T) { t.Fatalf("Referenced = %v, %v; want true", ok, missing) } } - diff --git a/go/delivery/stepasks.go b/go/delivery/stepasks.go index bf8aa49..327e87d 100644 --- a/go/delivery/stepasks.go +++ b/go/delivery/stepasks.go @@ -7,9 +7,12 @@ import ( "fmt" "path" "regexp" + "slices" "sort" "strings" "time" + + contractseats "git.novox.be/novox/mesh-contracts/go/seats" ) // **Asks: a build or a check step is a message a build node pulls when it has a free slot** (novox/hq ADR 0525, as @@ -340,6 +343,15 @@ type BuildJob struct { type AskArtifact struct { Artifact string `json:"artifact"` From string `json:"from,omitempty"` + // Seat is the registry seat the artifact is published through (design 51 *Publishing*): npm-package-registry or + // go-package-registry for a package, container-image-registry for an image or an upstream copy, + // oci-artifact-registry for a bundle or an archive. Absent for an ask written before the registry milestone, which + // its build module pushes as before. + Seat string `json:"seat,omitempty"` + // Version is the version the builder gave the artifact at the trunk's claim (design 51 *The versions*), which the + // build module names in the seat's publish; absent for a candidate's build and for a bundle or an archive published + // by its digest alone (ADR 0617 §1). + Version string `json:"version,omitempty"` } // CheckJob is a check ask's job, the levels of one check (ADR 0525 §3): fetch the head merged onto its trunk once, then @@ -453,6 +465,10 @@ func (c ComposeJob) check(id string) error { return nil } +// registrySeats are the seats an artifact is published through (ADR 0605 §1). +var registrySeats = []string{contractseats.NpmPackageRegistry, contractseats.GoPackageRegistry, + contractseats.ContainerImageRegistry, contractseats.OciArtifactRegistry} + func (b BuildJob) check(id string) error { if err := checkName("module", b.Module); err != nil { return err @@ -465,6 +481,14 @@ func (b BuildJob) check(id string) error { if err := checkName("artifact", a.Artifact); err != nil { return err } + if a.Seat != "" && !slices.Contains(registrySeats, a.Seat) { + return fmt.Errorf("delivery: the build ask %s publishes %s through %q, which is no registry seat (%s)", id, + a.Artifact, a.Seat, strings.Join(registrySeats, ", ")) + } + if a.Version != "" && a.Seat == "" { + return fmt.Errorf("delivery: the build ask %s gives %s the version %s and names no seat to publish it through", + id, a.Artifact, a.Version) + } fetch = fetch || a.From == "" } if fetch { diff --git a/go/delivery/stepasks_test.go b/go/delivery/stepasks_test.go index 6f1acd1..0dcc50f 100644 --- a/go/delivery/stepasks_test.go +++ b/go/delivery/stepasks_test.go @@ -15,9 +15,10 @@ func buildAsk() StepAsk { return StepAsk{ID: "mh3k2x9qa1b2c3", Kind: AskDelivery, Language: AskGo, Asker: "mesh-delivery-builder", At: time.Date(2026, 10, 23, 13, 0, 0, 0, time.UTC), Build: &BuildJob{Module: "mesh-delivery-view", Path: "modules/mesh-delivery-view", FP: "ab12", - Fetch: map[string]any{"repository": "novox/mesh-delivery", "commit": askCommit, "dir": "modules/mesh-delivery-view", "paths": []any{"cmd"}}, - Artifacts: []AskArtifact{{Artifact: "bundle"}, {Artifact: "base", From: "registry/x@sha256:00"}}, - Publish: true, Toolchain: &ToolchainUsed{Version: "go1.26.0", Recipe: "3"}}, + Fetch: map[string]any{"repository": "novox/mesh-delivery", "commit": askCommit, "dir": "modules/mesh-delivery-view", "paths": []any{"cmd"}}, + Artifacts: []AskArtifact{{Artifact: "bundle", Seat: "oci-artifact-registry", Version: "0.1.4"}, + {Artifact: "base", From: "registry/x@sha256:00"}}, + Publish: true, Toolchain: &ToolchainUsed{Version: "go1.26.0", Recipe: "3"}}, Packages: PackageVersions{"git.novox.be/novox/mesh-sdk/go": askCommit}} } @@ -83,6 +84,15 @@ func TestAskRefusesUnknownKindAndLanguage(t *testing.T) { t.Errorf("the node names %q: encoded", names) } } + // An artifact is published through a registry seat, and a version names the seat it is published through + // (design 51). + for _, art := range []AskArtifact{{Artifact: "bundle", Seat: "mesh-artifact-store"}, {Artifact: "bundle", Version: "0.1.4"}} { + a := buildAsk() + a.Build.Artifacts = []AskArtifact{art} + if _, err := EncodeStepAsk(a); err == nil { + t.Errorf("the artifact %+v: encoded", art) + } + } // A copy alone fetches nothing and needs no path. a := buildAsk() a.Build.Fetch, a.Build.Path, a.Build.Artifacts = nil, "", []AskArtifact{{Artifact: "base", From: "registry/x@sha256:00"}}