CAT-BG1: the build step answers the reference in the form the artifact seat answers

ADR 0605 §9: a done key names the seat's reference, oci-artifact-registry/<module>/<artifact>@<digest>,
not the store's older artifact-store:// form; the builder keeps the older form beside it while a counted
node-engine reads only that (ADR 0624). The whole test reads it back as a node-engine routes it.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-04 14:30:46 +01:00
parent d7ffc9cca0
commit 57a18a4783
4 changed files with 15 additions and 13 deletions
+2 -1
View File
@@ -139,7 +139,8 @@ the reference of the archive: once the build ended, this process publishes it th
(design 51 *Publishing*; `publish.go`): its verbs `publish` and `publish-part`, which the manifest `invokes`, with mesh-sdk's
sender (`publish.Publish`), under `<module>/<artifact>` by its digest and of kind `bundle` or `archive`, a candidate's as a
trunk build's, in chunks, only what the holder lacks; the holder asks the builder and says `published` or `refused` on the
seat's events. The step answers `artifact-store://<module>/<artifact>/blobs/<digest>`; a publish the holder refuses, or a
seat's events. The step answers the seat's form `oci-artifact-registry/<module>/<artifact>@<digest>` (ADR 0605 §9); the
builder writes the older form beside it while a counted node-engine reads only that (ADR 0624); a publish the holder refuses, or a
seat nothing holds, fails the step `not stored: <artifact>: <the holder's words>`. The packed bytes never stay on the node.
The module writes into no store itself and requires no `artifact-store`. The go build runs shut off in bubblewrap (ADR 0448, `isolate.go`): no
network, none of the account, the caches beneath a throwaway layer unless the step is told `publish` (a trunk build). An artifact that is neither a Go
@@ -34,8 +34,9 @@ type BuildResult struct {
Binary string `json:"binary"`
Digest string `json:"digest"`
Size int `json:"size"`
// Reference is where the archive is in the artifact store (novox/hq ADR 0498 §1):
// artifact-store://<module>/<artifact>/blobs/<digest>.
// Reference is where the archive is, in the form the seat it was published through answers (novox/hq ADR 0605
// §9): oci-artifact-registry/<module>/<artifact>@<digest>. The builder writes the older form beside it while a
// counted node-engine reads only that (ADR 0624 §1, §3).
Reference string `json:"reference"`
}
@@ -170,7 +171,7 @@ func (m *Module) packInto(ctx context.Context, workspace, module, name, artifact
if err := m.publishArchive(ctx, name, artifact, kind, digest, archive); err != nil {
return BuildResult{}, fmt.Errorf("%s%s: %v", delivery.NotStored, artifact, err)
}
return BuildResult{Artifact: artifact, Digest: digest, Size: len(archive), Reference: buildstep.BlobReference(name, artifact, digest)}, nil
return BuildResult{Artifact: artifact, Digest: digest, Size: len(archive), Reference: catalogue.SeatReference(ArtifactSeat, name, artifact, digest)}, nil
}
// buildEnv is the environment of the compile: the build agent's (CGO_ENABLED=0, GOFLAGS) with the installed go
@@ -94,7 +94,7 @@ func TestADoneBuildAnswersTheReferenceOfTheArchiveItPushed(t *testing.T) {
if st.State != delivery.StepPassed {
t.Fatalf("the step ended %s: %s", st.State, st.Reason)
}
if want := "artifact-store://demo/tools/blobs/" + res.Digest; res.Reference != want {
if want := "oci-artifact-registry/demo/tools@" + res.Digest; res.Reference != want {
t.Errorf("reference %q, want %q", res.Reference, want)
}
if store.blobs["demo/tools@"+res.Digest] == nil || store.asked[0] != "seat:oci-artifact-registry.publish" {
@@ -103,7 +103,7 @@ func TestADoneBuildAnswersTheReferenceOfTheArchiveItPushed(t *testing.T) {
a, states2, _ := archiveModule(t, "")
withStore(t, a)
arch, st := runBuild(t, a, states2, "files")
if st.State != delivery.StepPassed || arch.Reference != "artifact-store://demo/files/blobs/"+arch.Digest {
if st.State != delivery.StepPassed || arch.Reference != "oci-artifact-registry/demo/files@"+arch.Digest {
t.Errorf("the archive artifact: %s %q, reference %q", st.State, st.Reason, arch.Reference)
}
}
@@ -21,6 +21,7 @@ import (
_ "github.com/distribution/distribution/v3/registry/storage/driver/inmemory"
registry "git.novox.be/novox/mesh-contracts/go/seats/containerimageregistry"
"git.novox.be/novox/mesh-sdk/go/catalogue"
"git.novox.be/novox/mesh-sdk/go/delivery"
"git.novox.be/novox/mesh-catalog/modules/mesh-build-go/buildstep"
@@ -62,15 +63,14 @@ func realStore(t *testing.T, m *Module) string {
return addr
}
// resolve reads a done artifact's reference from the store, as the controller will: artifact-store://<module>/
// <artifact>/blobs/<digest> is <store>/v2/<module>/<artifact>/blobs/<digest>.
// resolve reads a done artifact's reference from the store as a node-engine does (catalogue.Routed): the seat's form
// oci-artifact-registry/<module>/<artifact>@<digest> is <store>/v2/<module>/<artifact>/blobs/<digest> (ADR 0605 §9).
func resolve(t *testing.T, addr string, a delivery.BuiltArtifact) []byte {
t.Helper()
path, ok := strings.CutPrefix(a.Reference, "artifact-store://")
if !ok {
t.Fatalf("%s's reference %q is not the artifact store's", a.Name, a.Reference)
if _, _, ok := catalogue.InRegistrySeat(a.Reference); !ok {
t.Fatalf("%s's reference %q is not in the form a registry seat answers", a.Name, a.Reference)
}
resp, err := http.Get("http://" + addr + "/v2/" + path)
resp, err := http.Get(catalogue.Routed(a.Reference, addr))
if err != nil {
t.Fatal(err)
}
@@ -121,7 +121,7 @@ func TestADoneBuildsArtifactsResolveInARealArtifactStore(t *testing.T) {
t.Errorf("the done key is not deliverable, missing %v", missing)
}
for _, a := range done.Artifacts {
if !strings.HasSuffix(a.Reference, "/blobs/"+a.Digest) {
if !strings.HasSuffix(a.Reference, "@"+a.Digest) {
t.Errorf("%s: the reference %q does not end in its digest %s", a.Name, a.Reference, a.Digest)
}
sum := sha256.Sum256(resolve(t, addr, a))