DLV-C3, DLV-C6 (tag-wanted): the checker's whole-module test hears tag-wanted at the definition's subject and builds on the published

A case of the existing group test (no new integration test): the bed's streams are the manifest's (checks with
preview.written, asks with verdict and tag-wanted at the mesh-delivery-checker definition's subjects) and the shared
events stream with the registry seats' published. A group whose mesh-sdk member has no preview yet is read at its head,
says tag-wanted whose body decodes strictly into the definition's type, is not judged before the Go seat's published,
and then builds mesh-delivery against v0.1.15-feat-x.1. The verdict half of DLV-C6 follows DLV-C2.

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-04 13:28:44 +01:00
parent 28ef5af2df
commit 8c3916bd7b
@@ -3,6 +3,7 @@
package main
import (
"bytes"
"context"
"encoding/json"
"errors"
@@ -22,6 +23,9 @@ import (
"github.com/nats-io/nats.go/jetstream"
gobuild "git.novox.be/novox/mesh-catalog/modules/mesh-build-go/buildstep"
"git.novox.be/novox/mesh-contracts/go/seats/gopackageregistry"
"git.novox.be/novox/mesh-contracts/go/seats/meshdeliverychecker"
"git.novox.be/novox/mesh-contracts/go/seats/npmpackageregistry"
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/buildrun"
"git.novox.be/novox/mesh-sdk/go/announce"
"git.novox.be/novox/mesh-sdk/go/delivery"
@@ -91,6 +95,8 @@ type fakeBuildModules struct {
beside map[string][]string
// names are the nodes' names the last check ask carried, for the names check (ADR 0567 §12).
names []string
// packages are, by repository, the package versions the last Go check ask of it carried (StepAsk.Packages).
packages map[string]delivery.PackageVersions
}
func (f *fakeBuildModules) count(tool string) int {
@@ -197,6 +203,12 @@ func (f *fakeBuildModules) serve(t *testing.T, module string, kept jetstream.Key
if a.Check != nil {
f.mu.Lock()
f.names = a.Check.NodeNames
if repository, _ := a.Check.Fetch["repository"].(string); a.Language == delivery.AskGo {
if f.packages == nil {
f.packages = map[string]delivery.PackageVersions{}
}
f.packages[repository] = a.Packages
}
f.mu.Unlock()
}
return gobuild.RunAsk(ctx, steps, a)
@@ -220,6 +232,15 @@ func (b *bed) serveForge(t *testing.T, nc *nats.Conn) {
var a map[string]string
_ = json.Unmarshal(m.Data, &a)
switch {
case tool == "gitea_get_file" && strings.HasSuffix(a["path"], "module.json"):
// A manifest at a member's head (design 51 *Tagged versions*): the bed's own, else the forge's 404.
if content, ok := b.heads.Load(a["owner"] + "/" + a["repo"] + " " + a["path"] + " " + a["ref"]); ok {
answer, _ := json.Marshal(map[string]any{"result": map[string]any{"file": map[string]any{"content": content}}, "error": "", "node": "n0"})
_ = m.Respond(answer)
return
}
answer, _ := json.Marshal(map[string]any{"result": nil, "error": "Gitea API /repos/x/contents/" + a["path"] + ": 404 Not Found", "node": "n0"})
_ = m.Respond(answer)
case tool == "gitea_get_file" && b.stalePin.Load():
content := strings.Replace(string(mustRead(t, "forge-get-file-go-mod")), "cb54756c3865", "9aaa5c80ac5c", 1)
var result map[string]any
@@ -252,6 +273,8 @@ func mustRead(t *testing.T, name string) []byte {
type bed struct {
stalePin atomic.Bool
// heads are the manifests the forge holds at a member's head, by "<repository> <path> <ref>".
heads sync.Map
ctx context.Context
js jetstream.JetStream
buckets map[string]jetstream.KeyValue
@@ -390,8 +413,20 @@ func startBed(t *testing.T) *bed {
if _, err := js.CreateStream(ctx, jetstream.StreamConfig{Name: buildrun.DeadLettersStream, Subjects: []string{"mesh.events.dead.>"}}); err != nil {
t.Fatal(err)
}
// The checker's stream of events, which the indexer and the forge bridge hear.
if _, err := js.CreateStream(ctx, jetstream.StreamConfig{Name: "CHECKS", Subjects: []string{"mesh.stream.mesh-delivery-checker.event.>"}}); err != nil {
// The checker's streams as its manifest declares them (ADR 0619, ADR 0620): checks, which the indexer and the forge
// bridge hear, and asks, with verdict and tag-wanted at the subjects the mesh-delivery-checker definition names.
if _, err := js.CreateStream(ctx, jetstream.StreamConfig{Name: "CHECKS", Subjects: []string{meshdeliverychecker.HolderSubjectPreviewWritten(delivery.CheckerModule)}}); err != nil {
t.Fatal(err)
}
if _, err := js.CreateStream(ctx, jetstream.StreamConfig{Name: "ASKS", Subjects: []string{meshdeliverychecker.HolderSubjectVerdict(delivery.CheckerModule),
meshdeliverychecker.HolderSubjectTagWanted(delivery.CheckerModule)}}); err != nil {
t.Fatal(err)
}
// The shared events stream with the package registry seats' published, and the checker's durable consumer of it.
if _, err := js.CreateStream(ctx, jetstream.StreamConfig{Name: process.EventsStream, Subjects: []string{gopackageregistry.SubjectPublished, npmpackageregistry.SubjectPublished}}); err != nil {
t.Fatal(err)
}
if _, err := js.CreateOrUpdateConsumer(ctx, process.EventsStream, jetstream.ConsumerConfig{Durable: "n1_mesh-delivery-checker", AckPolicy: jetstream.AckExplicitPolicy}); err != nil {
t.Fatal(err)
}
for name, history := range map[string]int{delivery.CheckerVerdictsBucket: delivery.CheckerVerdictsHistory, delivery.CheckerKeptBucket: delivery.CheckerKeptHistory,
@@ -830,6 +865,51 @@ func TestAMemberNamingAMeshSDKCommitOffTheTrunkIsJudgedAndNotRefused(t *testing.
if v := b.verdict(t, key, ended); v.State != delivery.VerdictPass {
t.Fatalf("verdict = %+v", v)
}
// DLV-C3, DLV-C6 (design 51 *Tagged versions*, ADR 0607 §3, §5, ADR 0620): a group whose mesh-sdk member declares a Go
// package, read at its head with no preview yet, says tag-wanted on the checker's stream asks, at the subject and in the body the mesh-delivery-checker
// definition names; once the Go seat's published of the tagged version is heard, the other member is built against it.
const sdkRepo = "novox/mesh-sdk"
b.setTrunk(t, map[string]string{repo: trunk, sdkRepo: trunk})
// The member carries no preview of its merge yet, so its manifest is read at its head (the package new in the group).
b.heads.Store(sdkRepo+" module.json "+head2, `{"module":"mesh-sdk","build":{"artifacts":[{"name":"go","kind":"package","language":"go","paths":["go"]}]}}`)
asks, err := b.js.OrderedConsumer(b.ctx, "ASKS", jetstream.OrderedConsumerConfig{FilterSubjects: []string{meshdeliverychecker.HolderSubjectTagWanted(delivery.CheckerModule)}})
if err != nil {
t.Fatal(err)
}
sdk := pull(sdkRepo, 12, head2)
sdk.Modules, sdk.Fps = []string{"mesh-sdk"}, map[string]delivery.CandidateModule{"mesh-sdk": {FP2: "src2:" + strings.Repeat("e", 64)}}
key = b.candidate(t, "feat/x", pull(repo, 8, head1), sdk)
msg, err := asks.Next(jetstream.FetchMaxWait(20 * time.Second))
if err != nil {
t.Fatalf("no tag-wanted on the stream asks: %v", err)
}
var wanted meshdeliverychecker.TagWantedHolderEvent
dec := json.NewDecoder(bytes.NewReader(msg.Data()))
dec.DisallowUnknownFields()
if err := dec.Decode(&wanted); err != nil {
t.Fatalf("tag-wanted %s is not the definition's body: %v", msg.Data(), err)
}
if want := (meshdeliverychecker.TagWantedHolderEvent{Repository: sdkRepo, Branch: "feat/x", Head: head2, Module: "mesh-sdk", Package: "go", Pull: 12}); wanted != want {
t.Errorf("tag-wanted = %+v, want %+v", wanted, want)
}
if v, err := b.buckets[delivery.CheckerVerdictsBucket].Get(b.ctx, key); err == nil && !strings.Contains(string(v.Value()), `"running"`) {
t.Fatalf("the group was judged before its tagged version was published: %s", v.Value())
}
published, _ := json.Marshal(gopackageregistry.PublishedEvent{Holder: "gitea", Kind: "package", Name: "mesh-sdk/go", Commit: head2, Tag: "feat-x", Version: "0.1.15-feat-x.1",
Digest: "sha256:" + strings.Repeat("0", 64)})
if _, err := b.js.Publish(b.ctx, gopackageregistry.SubjectPublished, published); err != nil {
t.Fatal(err)
}
if v := b.verdict(t, key, ended); v.State != delivery.VerdictPass {
t.Fatalf("the group's verdict = %+v", v)
}
b.fake.mu.Lock()
got := b.fake.packages[repo]
b.fake.mu.Unlock()
if got[check.SDKModulePath] != "v0.1.15-feat-x.1" {
t.Errorf("mesh-delivery was built against %v, want mesh-sdk's Go module at the group's tagged version v0.1.15-feat-x.1", got)
}
}
// triesStore is the tries bucket as the tools write it.
@@ -938,7 +1018,9 @@ func TestATryIsJudgedAndItsEndWrittenWithNoStatusOwed(t *testing.T) {
// the readable ones, which is what grants the forge module its read of owed (ADR 0495 §2-§3, ADR 0521; R4e finding R2-1).
func TestTheCheckerSaysOwedReadableOnTheBus(t *testing.T) { // R2-1
b := startBed(t)
if _, err := b.js.CreateStream(b.ctx, jetstream.StreamConfig{Name: "EVENTS", Subjects: []string{"mesh.mod.*.event.>"}}); err != nil {
// The bed's shared events stream carries the registry seats' published; the module events go on it too.
if _, err := b.js.UpdateStream(b.ctx, jetstream.StreamConfig{Name: process.EventsStream, Subjects: []string{"mesh.mod.*.event.>",
gopackageregistry.SubjectPublished, npmpackageregistry.SubjectPublished}}); err != nil {
t.Fatal(err)
}
b.start(t, nil)