From 9b12dfaf211efff5a7f4b680902fe69fde9cc258 Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 1 Nov 2026 02:29:48 +0100 Subject: [PATCH] =?UTF-8?q?mesh-build-go=20decodes=20the=20manifest=20it?= =?UTF-8?q?=20builds=20from=20and=20judges=20none=20(ADR=200578=20=C2=A73)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL --- .../mesh-build-go/cmd/mesh-build-go/build.go | 2 +- .../cmd/mesh-build-go/build_test.go | 4 +- .../cmd/mesh-build-go/manifest_test.go | 50 +++++++++---------- .../cmd/mesh-build-go/node_toolchains_test.go | 4 -- .../cmd/mesh-build-go/reads-outside | 3 +- .../cmd/mesh-build-go/shares_test.go | 6 +-- modules/mesh-build-go/go.mod | 2 +- modules/mesh-build-go/go.sum | 2 + 8 files changed, 33 insertions(+), 40 deletions(-) diff --git a/modules/mesh-build-go/cmd/mesh-build-go/build.go b/modules/mesh-build-go/cmd/mesh-build-go/build.go index 40eec5bf..d7f39939 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/build.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/build.go @@ -92,7 +92,7 @@ func (m *Module) build(ctx context.Context, args map[string]any) (any, error) { if err != nil { return nil, fmt.Errorf("no module in %q of workspace %s: %w", module, workspace, err) } - manifest, err := catalogue.ParseManifestForInputs(raw) + manifest, err := catalogue.Decode(raw) if err != nil { return nil, fmt.Errorf("the manifest in %q: %w", module, err) } diff --git a/modules/mesh-build-go/cmd/mesh-build-go/build_test.go b/modules/mesh-build-go/cmd/mesh-build-go/build_test.go index 704db9d6..2583dfc4 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/build_test.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/build_test.go @@ -239,8 +239,8 @@ func TestABuildOutputDirectoryLinkedOutsideTheModuleIsRefused(t *testing.T) { } // Issue 1751 (ADR 0514 §2, the review's K2): a manifest whose config value falls back to a predefined key builds. The -// builder holds no published list of the keys, so it reads the manifest for its inputs (ParseManifestForInputs), not -// as a judge of config values; claude-code's real manifest (capturedClaudeCodeManifest) is the fixture. +// builder holds no published list of the keys, so it decodes the manifest for its inputs (catalogue.Decode), and judges +// no config value (ADR 0578 §3); claude-code's real manifest (capturedClaudeCodeManifest) is the fixture. func TestAManifestFallingBackToAPredefinedKeyBuilds(t *testing.T) { raw := []byte(capturedClaudeCodeManifest) if !strings.Contains(string(raw), `"predefined": "agent-managed-settings"`) { diff --git a/modules/mesh-build-go/cmd/mesh-build-go/manifest_test.go b/modules/mesh-build-go/cmd/mesh-build-go/manifest_test.go index dcf6fd8b..8e3790b9 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/manifest_test.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/manifest_test.go @@ -16,15 +16,26 @@ const ( moduleDir = "../.." ) -func readManifest(t *testing.T) catalogue.Manifest { +// decodeTree is the manifest in a module's directory, decoded and judged by nothing: the checker judges every change's +// manifests (novox/hq ADR 0578 §2), and a module's own tests read what it declares. +func decodeTree(t *testing.T, dir string) catalogue.Manifest { t.Helper() - m, err := catalogue.ReadTreeManifest(catalogueRoot, moduleDir) + raw, err := os.ReadFile(filepath.Join(dir, "module.json")) if err != nil { - t.Fatalf("mesh-sdk's validator refuses module.json: %v", err) + t.Fatal(err) + } + m, err := catalogue.Decode(raw) + if err != nil { + t.Fatalf("module.json does not decode: %v", err) } return m } +func readManifest(t *testing.T) catalogue.Manifest { + t.Helper() + return decodeTree(t, moduleDir) +} + func resource(t *testing.T, m catalogue.Manifest, id string) map[string]any { t.Helper() for _, r := range m.Resources { @@ -36,13 +47,10 @@ func resource(t *testing.T, m catalogue.Manifest, id string) map[string]any { return nil } -// 1483/AC1: mesh-sdk's validator accepts the module (alone on a shelf too), and it runs as mesh-build-go with its -// home at mode 0700, requires user-namespaces and declares the four packages. -func TestManifestIsValidAndDeclaresTheAccountTheCapabilityAndThePackages(t *testing.T) { +// 1483/AC1: the module runs as mesh-build-go with its home at mode 0700, requires user-namespaces and declares the four +// packages. +func TestManifestDeclaresTheAccountTheCapabilityAndThePackages(t *testing.T) { m := readManifest(t) - if problems := catalogue.CatalogueProblems(catalogue.Shelf{m.Module: m}); len(problems) > 0 { - t.Errorf("the catalogue's rules refuse it: %v", problems) - } if m.Module != "mesh-build-go" || m.RunsAs != "mesh-build-go" { t.Errorf("module %q runs as %q, want mesh-build-go as itself", m.Module, m.RunsAs) } @@ -128,22 +136,10 @@ func TestTheToolsServedAreTheToolsTheManifestNames(t *testing.T) { } } -// 1482/AC4: gitea's manifest reads the keys state of both build modules, and the catalogue's validator accepts it with the -// build modules beside it: each owner present declares the state read (a read of a state its owner does not keep is -// refused). -func TestGiteaReadsTheBuildModulesKeysAndTheCatalogueAcceptsThemTogether(t *testing.T) { - var all []catalogue.Manifest - var gitea catalogue.Manifest - for _, name := range []string{"gitea", "mesh-build-go", "mesh-build-node"} { - m, err := catalogue.ReadTreeManifest(catalogueRoot, filepath.Join(catalogueRoot, "modules", name)) - if err != nil { - t.Fatalf("mesh-sdk's validator refuses modules/%s/module.json: %v", name, err) - } - all = append(all, m) - if name == "gitea" { - gitea = m - } - } +// 1482/AC4: gitea's manifest reads the keys state of both build modules (whether a read names a state its owner keeps is +// the judge's, ADR 0578 §2). +func TestGiteaReadsTheBuildModulesKeys(t *testing.T) { + gitea := decodeTree(t, filepath.Join(catalogueRoot, "modules", "gitea")) for _, want := range []string{"mesh-build-go.keys", "mesh-build-node.keys", "ssh-client.keys"} { if !slices.Contains(gitea.Reads, want) { t.Errorf("gitea reads %v, lacks %s", gitea.Reads, want) @@ -171,8 +167,8 @@ func TestTheModuleRequiresTheArtifactStoreAndIsToldItsAddress(t *testing.T) { t.Errorf("requires %v lack artifact-store", m.Requires) } r := resource(t, m, "registry") - // The validator reads the template (files/registry) into the resource's content. - if content, _ := r["content"].(string); r["type"] != "file" || r["path"] != "${dir:state}/registry" || !strings.Contains(content, "${seat:mesh-artifact-store:reach}") { + // The template (files/registry) is read below; decoding leaves it unread in the resource. + if r["type"] != "file" || r["path"] != "${dir:state}/registry" || r["template"] != "files/registry" { t.Errorf("the registry resource is %v", r) } raw, err := os.ReadFile(filepath.Join(moduleDir, "files", "registry")) diff --git a/modules/mesh-build-go/cmd/mesh-build-go/node_toolchains_test.go b/modules/mesh-build-go/cmd/mesh-build-go/node_toolchains_test.go index b1ecbe7c..efd415cf 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/node_toolchains_test.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/node_toolchains_test.go @@ -9,7 +9,6 @@ import ( "strconv" "testing" - "git.novox.be/novox/mesh-sdk/go/catalogue" "git.novox.be/novox/mesh-sdk/go/delivery" "git.novox.be/novox/mesh-sdk/go/forgekey" ) @@ -134,9 +133,6 @@ func TestTheUnitLevelIsNotGivenTheNodeToolchains(t *testing.T) { // 1891 (ADR 0533 §1, §2): the place bound is the Node build module's own: its manifest's cache directory joined with // toolchain, and that cache directory lets other accounts enter it without listing it (0711). func TestTheNodeToolchainsAreTheNodeBuildModulesCache(t *testing.T) { - if _, err := catalogue.ReadTreeManifest(catalogueRoot, filepath.Join(catalogueRoot, "modules", "mesh-build-node")); err != nil { - t.Fatalf("mesh-sdk's validator refuses mesh-build-node's manifest: %v", err) - } raw, err := os.ReadFile(filepath.Join(catalogueRoot, "modules", "mesh-build-node", "module.json")) if err != nil { t.Fatal(err) diff --git a/modules/mesh-build-go/cmd/mesh-build-go/reads-outside b/modules/mesh-build-go/cmd/mesh-build-go/reads-outside index ea239b40..2315df35 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/reads-outside +++ b/modules/mesh-build-go/cmd/mesh-build-go/reads-outside @@ -1,7 +1,6 @@ # What these tests read outside their package, as paths from the repository's root (a glob, or a directory read whole; # ? before a path whose absence is read). mesh-build-go hashes them into the package's digest, so its verdict is kept # until one of them changes (issue 1936). An empty list, or a line matching nothing, keeps nothing. -# the manifests through mesh-sdk's validator (the predefined keys), gitea's and mesh-build-node's. -predefined.json +# the manifests gitea's and mesh-build-node's, decoded. modules/gitea modules/mesh-build-node diff --git a/modules/mesh-build-go/cmd/mesh-build-go/shares_test.go b/modules/mesh-build-go/cmd/mesh-build-go/shares_test.go index 0fa5ab02..35d28e25 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/shares_test.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/shares_test.go @@ -8,15 +8,15 @@ import ( "git.novox.be/novox/mesh-sdk/go/catalogue" ) -// Issue 1657/AC1 unit: the manifest parse build.go uses reads a requires entry that names shares. The fixture is +// Issue 1657/AC1 unit: the manifest decode build.go uses reads a requires entry that names shares. The fixture is // the shape of mesh-sdk's go/catalogue/bucket_shares_test.go (filesWithShares). The shares are checked through the // manifest's stored form, so the test compiles against a pin that predates them and fails on the assertion. func TestBuildReadsManifestWithShares(t *testing.T) { raw := []byte(`{"module":"files","version":"1","requires":["shell", {"name":"s3-bucket","shares":[{"to":"seat:node-files","methods":["put"]}]}]}`) - m, err := catalogue.ParseManifest(raw) + m, err := catalogue.Decode(raw) if err != nil { - t.Fatalf("the manifest is refused: %v", err) + t.Fatalf("the manifest does not decode: %v", err) } stored, err := json.Marshal(m) if err != nil { diff --git a/modules/mesh-build-go/go.mod b/modules/mesh-build-go/go.mod index 18b896e0..29a24fd7 100644 --- a/modules/mesh-build-go/go.mod +++ b/modules/mesh-build-go/go.mod @@ -3,7 +3,7 @@ module meshbuildgo go 1.26.0 require ( - git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031084708-acbf80ad910a + git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101012031-7cab079e2ec3 github.com/distribution/distribution/v3 v3.1.2 github.com/nats-io/nats-server/v2 v2.11.17 github.com/nats-io/nats.go v1.54.0 diff --git a/modules/mesh-build-go/go.sum b/modules/mesh-build-go/go.sum index fc784332..c6c93a1a 100644 --- a/modules/mesh-build-go/go.sum +++ b/modules/mesh-build-go/go.sum @@ -1,5 +1,7 @@ git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031084708-acbf80ad910a h1:DcSvfEmdPBKqCg5OmXRNb269EkkPe7BsEp+RykEhkgE= git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031084708-acbf80ad910a/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101012031-7cab079e2ec3 h1:an2f0MLx9OhaDLu5i51OMPBbuGwX+aoTzqOkFLMpVfE= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101012031-7cab079e2ec3/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= github.com/alicebob/miniredis/v2 v2.35.0 h1:QwLphYqCEAo1eu1TqPRN2jgVMPBweeQcR21jeqDCONI= github.com/alicebob/miniredis/v2 v2.35.0/go.mod h1:TcL7YfarKPGDAthEtl5NBeHZfeUQj6OXMm/+iu5cLMM= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=