Let grants, builder and checker decode manifests, and the checker judge a change with the indexer's judge (ADR 0578 §2, §3)
Issue 1585, S12: grants, builder and checker read with catalogue.Decode and grants holds a module the indexer refused; the checker asks the Go build seat to run mesh-judge, built at mesh-delivery's trunk or at the group's mesh-delivery head when it changes the judge, over the catalogue as the change leaves it, and fails on a refusal. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
@@ -3,7 +3,7 @@ module mesh-grants
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031230538-c28c645ca406
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101005736-7b09de1e5502
|
||||
github.com/nats-io/nats.go v1.54.0
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031230538-c28c645ca406 h1:Z4RcH5Ft4OAAG3F538NXIHP9F3pkyk3j0LtP9mqu1qQ=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261031230538-c28c645ca406/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101005736-7b09de1e5502 h1:XndvkzyAFNde/821lEfYObqMTURzmve/w9Ks+QrBBJ8=
|
||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261101005736-7b09de1e5502/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=
|
||||
github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
|
||||
github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo=
|
||||
|
||||
@@ -307,6 +307,13 @@ func (b *fakeBus) manifestOf(module, raw string) {
|
||||
b.put(grants.ReadModules, module, delivery.Module{V: delivery.Version, FP2: "src2:" + strings.Repeat("ab", 32), Manifest: digest, Repository: "novox/x", Commit: "c"})
|
||||
}
|
||||
|
||||
// refuse marks the indexer's refusal of module's manifest in its value (novox/hq ADR 0578 §1).
|
||||
func (b *fakeBus) refuse(module, raw, problem string) {
|
||||
b.put(grants.ReadModules, module, delivery.Module{V: delivery.Version, FP2: "src2:" + strings.Repeat("ab", 32),
|
||||
Manifest: delivery.ManifestDigest([]byte(raw)), Repository: "novox/x", Commit: "c", Verdict: delivery.VerdictRefused,
|
||||
Problems: []string{problem}})
|
||||
}
|
||||
|
||||
func (b *fakeBus) assign(node, module string) {
|
||||
b.put(grants.ReadAssignments, node+"."+module, map[string]any{"node": node, "module": module, "assigned": "2026-10-25T20:00:00Z"})
|
||||
}
|
||||
@@ -728,13 +735,14 @@ func TestGrants(t *testing.T) {
|
||||
|
||||
t.Run("a predefined-key fallback is read with no list; every refused manifest listed", func(t *testing.T) {
|
||||
// mod-p's value falls back to a predefined key, as claude-code's managed_settings does, and no list is on the bus
|
||||
// (issue 1945); mod-z's manifest carries a key mesh-sdk's reader refuses, and mod-z is assigned nowhere.
|
||||
// (issue 1945); mod-z's manifest the indexer's judge refused (ADR 0578 §3), and mod-z is assigned nowhere.
|
||||
const pManifest = `{"module":"mod-p","version":"1","own-secrets":{"broker":"/var/lib/p/broker"},` +
|
||||
`"config":{"size":{"type":"number","description":"The size text shows in, in points.","predefined":"font-size","default":12,"runtime":true}}}`
|
||||
const zManifest = `{"module":"mod-z","version":"1","no-such-key":true}`
|
||||
b := fixture()
|
||||
b.manifestOf("mod-p", pManifest)
|
||||
b.manifestOf("mod-z", zManifest)
|
||||
b.refuse("mod-z", zManifest, "it carries no-such-key")
|
||||
b.assign("b", "mod-p")
|
||||
// mesh-wireguard is provided by the mesh, not read from a repository: no manifest in the indexer, none refused,
|
||||
// no gap, and its manifest is the one mesh-sdk provides (issue 1945).
|
||||
|
||||
@@ -10,6 +10,7 @@ package grants
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"sort"
|
||||
@@ -206,12 +207,11 @@ func (c *Manifests) get(r Reader, digest string) (catalogue.Manifest, error) {
|
||||
if err != nil {
|
||||
return catalogue.Manifest{}, err
|
||||
}
|
||||
// Read for its inputs, as every delivery part reads a manifest (issue 1751): the merge gate judged its config values,
|
||||
// and the part reads its seats, buckets, logs and streams, never a value; so a value falling back to a predefined key
|
||||
// is taken as it declares itself, where ParseManifest refused it with no list and placed its module nowhere (issue 1945).
|
||||
m, err = catalogue.ParseManifestForInputs([]byte(v.JSON))
|
||||
// Decoded, never judged (novox/hq ADR 0578 §3): the indexer's judge judged it, and its verdict is taken where the
|
||||
// module's value is read (Inputs); a field this part does not know is set aside.
|
||||
m, err = catalogue.Decode([]byte(v.JSON))
|
||||
if err != nil {
|
||||
return catalogue.Manifest{}, fmt.Errorf("the manifest %s is refused by mesh-sdk's reader: %w", digest, err)
|
||||
return catalogue.Manifest{}, fmt.Errorf("the manifest %s does not decode: %w", digest, err)
|
||||
}
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
@@ -384,6 +384,12 @@ func ReadInputs(r Reader, cache *Manifests) Inputs {
|
||||
in.NoFingerprint[module] = why
|
||||
}
|
||||
var m catalogue.Manifest
|
||||
if err == nil {
|
||||
// The indexer's refusal, carried in its value (ADR 0578 §3): held and named as a refused manifest.
|
||||
if verdict := v.VerdictOf(module); verdict != nil && verdict.Refused() {
|
||||
err = errors.New(verdict.Why())
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
m, err = cache.get(r, v.Manifest)
|
||||
}
|
||||
|
||||
@@ -70,9 +70,11 @@ func TestTheLeaseCheckJudgesEveryDependencyOnTheController(t *testing.T) {
|
||||
controllerHolds, want{reason: "manifest of mod-m could not be read", bothPhases: true}, func(b *fakeBus) {
|
||||
delete(b.states[grants.ReadManifests], delivery.ManifestDigest([]byte(mManifest)))
|
||||
}},
|
||||
{"a manifest mesh-sdk refuses fails both phases, named",
|
||||
{"a manifest the indexer's judge refuses fails both phases, named",
|
||||
map[string]string{"mod-l": `{"module":"mod-l","version":"1"}`, "mod-r": `{"module":"mod-r","version":"1","waits":["mesh-controller.checked"]}`},
|
||||
controllerHolds, want{reason: "manifest of mod-r could not be read", bothPhases: true}, nil},
|
||||
controllerHolds, want{reason: "manifest of mod-r could not be read", bothPhases: true}, func(b *fakeBus) {
|
||||
b.refuse("mod-r", `{"module":"mod-r","version":"1","waits":["mesh-controller.checked"]}`, "waits on what no record keeps")
|
||||
}},
|
||||
{"a lease already handed away leaves nothing to write",
|
||||
map[string]string{},
|
||||
handedAway, want{handedAway: true, reason: "there is nothing to write: the lease is handed to the operator's hand-over"}, nil},
|
||||
|
||||
Reference in New Issue
Block a user