The judge knows the tool runner by what its manifest says and keeps the kept streams itself, and this repository's check that no manifest names the ended controller reads them as text: mesh-sdk names no module (ADR 0601 §4)
This commit is contained in:
@@ -136,7 +136,7 @@ func spokenSystems() string {
|
||||
// and was simply absent — seven modules' tools went missing that way on 2026-10-03. Refused here,
|
||||
// naming the field that would deliver it.
|
||||
func undeliveredBundles(m catalogue.Manifest) []string {
|
||||
if m.Build == nil || m.Module == catalogue.RuntimeModule {
|
||||
if m.Build == nil || catalogue.IsToolRunner(m) {
|
||||
return nil
|
||||
}
|
||||
named := runByAResource(m)
|
||||
@@ -3306,9 +3306,9 @@ func waitProblems(m catalogue.Manifest) []string {
|
||||
if len(m.Waits) == 0 {
|
||||
return nil
|
||||
}
|
||||
if m.Module != catalogue.RuntimeModule {
|
||||
return []string{fmt.Sprintf("%s says what a session waits on; only %s, the tool runner's module, "+
|
||||
"declares waits (novox/hq ADR 0367 §2)", m.Module, catalogue.RuntimeModule)}
|
||||
if !catalogue.IsToolRunner(m) {
|
||||
return []string{fmt.Sprintf("%s says what a session waits on; only the tool runner's module (it says "+
|
||||
"\"tool-runner\": true) declares waits (novox/hq ADR 0367 §2)", m.Module)}
|
||||
}
|
||||
var problems []string
|
||||
seen := map[string]bool{}
|
||||
@@ -5420,12 +5420,29 @@ func StateProblems(m catalogue.Manifest) []string {
|
||||
return problems
|
||||
}
|
||||
|
||||
// PredefinedFormProblems refuses each stream a module declares that StreamsKeptUntilMoved does not name for it.
|
||||
// **A module keeps its data in the bus's predefined forms** (the lead and the operator, 2026-10-29; the operator's rule of
|
||||
// 2026-10-22, "data storage is done using our predefined nats bus options"): a state, a log or an object store, which the
|
||||
// runtime reads and writes for its tools and other modules read by a declared `reads`. A stream of its own is outside
|
||||
// them and refused, naming it. streamsKeptUntilMoved are the streams declared before this check, each allowed by name
|
||||
// until its module moves it; the list only shrinks. The judge's own exception, kept here and no longer in mesh-sdk,
|
||||
// which names no module (issue 774, the operator 2026-11-03).
|
||||
var streamsKeptUntilMoved = map[string][]string{
|
||||
"brother": {"device-asks"},
|
||||
"mesh-build-go": {"toolchains-go"},
|
||||
"mesh-build-node": {"toolchains-node"},
|
||||
"mesh-mail": {"mail", "mail-sends"},
|
||||
"only-office": {"convert-asks"},
|
||||
"mesh-delivery-assigner": {"placement"},
|
||||
"mesh-delivery-checker": {"checks"},
|
||||
"mesh-delivery-forge-bridge": {"forge"},
|
||||
}
|
||||
|
||||
// PredefinedFormProblems refuses each stream a module declares that streamsKeptUntilMoved does not name for it.
|
||||
func PredefinedFormProblems(m catalogue.Manifest) []string {
|
||||
var out []string
|
||||
for _, s := range m.Streams {
|
||||
// A stream that keeps its history is one of the bus's predefined forms (novox/hq ADR 0592 §6).
|
||||
if !s.KeepsHistory() && !slices.Contains(catalogue.StreamsKeptUntilMoved[m.Module], s.Name) {
|
||||
if !s.KeepsHistory() && !slices.Contains(streamsKeptUntilMoved[m.Module], s.Name) {
|
||||
out = append(out, fmt.Sprintf("%s keeps the stream %q, outside the bus's predefined forms: keep it as a state, "+
|
||||
"a log or an object store, which the runtime reads for the module's tools and others read by `reads`", m.Module, s.Name))
|
||||
}
|
||||
|
||||
@@ -157,12 +157,18 @@ func TestABundleNothingDeliversIsRefused(t *testing.T) {
|
||||
run := base()
|
||||
run.Resources = []map[string]any{{"id": "daemon", "type": "process", "artifact": "tools", "run": []any{"node", "tools/index.js"}}}
|
||||
runtime := base()
|
||||
runtime.Module = catalogue.RuntimeModule
|
||||
runtime.Module, runtime.ToolRunner = "node-tools", true
|
||||
for name, m := range map[string]catalogue.Manifest{"loads": loads, "tools": tools, "a process": run, "the runtime": runtime} {
|
||||
if p := undeliveredBundles(m); len(p) != 0 {
|
||||
t.Errorf("a bundle delivered by %s was refused: %v", name, p)
|
||||
}
|
||||
}
|
||||
// The tool runner is what says it is one (issue 774): its name alone exempts nothing.
|
||||
named := base()
|
||||
named.Module = "node-tools"
|
||||
if p := undeliveredBundles(named); len(p) != 1 {
|
||||
t.Errorf("a bundle of a module named as the tool runner, which does not say it is one: %v", p)
|
||||
}
|
||||
}
|
||||
|
||||
func TestABundlesWordsAreRefusedWhenTheyAreNotPathsOrConstants(t *testing.T) {
|
||||
@@ -3108,15 +3114,16 @@ func TestAVerbWithAnUnknownKeyIsRefused(t *testing.T) {
|
||||
// each refusal is said in the manifest's words, at parse, rather than at the composition of the bus's users.
|
||||
func TestAWaitIsRefusedUnlessItNamesOneFamilyOfTheToolRunner(t *testing.T) {
|
||||
for manifest, want := range map[string]string{
|
||||
`{"module":"shop","version":"1","waits":["mesh-knowledge.reviewed"]}`: "only node-tools",
|
||||
`{"module":"node-tools","version":"1","waits":["mesh-knowledge.*"]}`: "never a wildcard",
|
||||
`{"module":"node-tools","version":"1","waits":["**"]}`: "never a wildcard",
|
||||
`{"module":"node-tools","version":"1","waits":["mesh-knowledge.>"]}`: "never a wildcard",
|
||||
`{"module":"node-tools","version":"1","waits":["*.reviewed"]}`: "never a wildcard",
|
||||
`{"module":"node-tools","version":"1","waits":["reviewed"]}`: "does not name an emitter and an event",
|
||||
`{"module":"node-tools","version":"1","waits":["mesh-knowledge..reviewed"]}`: "does not name an emitter and an event",
|
||||
`{"module":"node-tools","version":"1","waits":["Mesh-Knowledge.reviewed x"]}`: "does not name an emitter and an event",
|
||||
`{"module":"node-tools","version":"1","waits":["a.b","a.b"]}`: "twice",
|
||||
`{"module":"shop","version":"1","waits":["mesh-knowledge.reviewed"]}`: "only the tool runner's module",
|
||||
`{"module":"node-tools","version":"1","waits":["mesh-knowledge.reviewed"]}`: "only the tool runner's module", // its name says nothing (issue 774)
|
||||
`{"module":"node-tools","version":"1","tool-runner":true,"waits":["mesh-knowledge.*"]}`: "never a wildcard",
|
||||
`{"module":"node-tools","version":"1","tool-runner":true,"waits":["**"]}`: "never a wildcard",
|
||||
`{"module":"node-tools","version":"1","tool-runner":true,"waits":["mesh-knowledge.>"]}`: "never a wildcard",
|
||||
`{"module":"node-tools","version":"1","tool-runner":true,"waits":["*.reviewed"]}`: "never a wildcard",
|
||||
`{"module":"node-tools","version":"1","tool-runner":true,"waits":["reviewed"]}`: "does not name an emitter and an event",
|
||||
`{"module":"node-tools","version":"1","tool-runner":true,"waits":["mesh-knowledge..reviewed"]}`: "does not name an emitter and an event",
|
||||
`{"module":"node-tools","version":"1","tool-runner":true,"waits":["Mesh-Knowledge.reviewed x"]}`: "does not name an emitter and an event",
|
||||
`{"module":"node-tools","version":"1","tool-runner":true,"waits":["a.b","a.b"]}`: "twice",
|
||||
} {
|
||||
_, err := ParseManifest([]byte(manifest))
|
||||
if err == nil {
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"maps"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -2140,26 +2141,27 @@ func TestGrants(t *testing.T) {
|
||||
})
|
||||
|
||||
// ADR 0590 clause 5's test for this repository (issue 1126): no module.json here names mesh-controller, the lease
|
||||
// read and the builder's consume of artifacts-gone included (mesh-sdk catalogue.ManifestRefusals).
|
||||
// read and the builder's consume of artifacts-gone included. Read as text, as mesh-catalog's controllerdeps check reads
|
||||
// its own: mesh-sdk names no module, so it holds no such check (issue 774, the operator 2026-11-03).
|
||||
t.Run("no module of this repository names the controller", func(t *testing.T) {
|
||||
paths, _ := filepath.Glob("../*/module.json")
|
||||
manifests := map[string]catalogue.Manifest{}
|
||||
if len(paths) < 8 {
|
||||
t.Fatalf("read %d manifests, want every module of the repository", len(paths))
|
||||
}
|
||||
names := regexp.MustCompile(`(^|[^A-Za-z0-9_-])(seat:)?mesh-controller([._"]|$)`)
|
||||
for _, path := range paths {
|
||||
raw, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m, err := catalogue.Decode(raw)
|
||||
if err != nil {
|
||||
if _, err := catalogue.Decode(raw); err != nil {
|
||||
t.Fatalf("%s: %v", path, err)
|
||||
}
|
||||
manifests[m.Module] = m
|
||||
}
|
||||
if len(manifests) < 8 {
|
||||
t.Fatalf("read %d manifests, want every module of the repository", len(manifests))
|
||||
}
|
||||
for _, why := range catalogue.ManifestRefusals(manifests) {
|
||||
t.Error(why)
|
||||
for i, line := range strings.Split(string(raw), "\n") {
|
||||
if names.MatchString(line) {
|
||||
t.Errorf("%s:%d names the ended controller: %s", path, i+1, strings.TrimSpace(line))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -45,6 +45,9 @@ func ControllerLeftoverConsumersOn(nodes []string) []string {
|
||||
return out
|
||||
}
|
||||
|
||||
// endedController is the name the ended controller had as a module: its buckets are named for it (ADR 0590 §6).
|
||||
const endedController = "mesh-controller"
|
||||
|
||||
// ControllerLeftoverBuckets are the ended controller's buckets, each by its local name (`KV_mesh-controller_<name>`).
|
||||
var ControllerLeftoverBuckets = []string{"asked", "assignments", "builds", "calls", "checks-running", "composed",
|
||||
"condition-history", "conditions", "declared-config", "declared-packages", "delivery-merges", "grants", "hand-acts",
|
||||
@@ -55,7 +58,7 @@ var ControllerLeftoverBuckets = []string{"asked", "assignments", "builds", "call
|
||||
func ControllerLeftoverStreams(nodes []string) []string {
|
||||
out := []string{"CONTROL", AssignmentsStream}
|
||||
for _, b := range ControllerLeftoverBuckets {
|
||||
out = append(out, "KV_"+BucketName(catalogue.EndedControllerName, b))
|
||||
out = append(out, "KV_"+BucketName(endedController, b))
|
||||
}
|
||||
for _, n := range nodes {
|
||||
if safeSubject.MatchString(n) {
|
||||
|
||||
Reference in New Issue
Block a user