mesh-build-go decodes the manifest it builds from and judges none (ADR 0578 §3)
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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"`) {
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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=
|
||||
|
||||
Reference in New Issue
Block a user