A-342 judge-node-env: a resource's own MESH_NODE is refused
mesh/delivery-group group feat/47-G-join11 checking: composed again for its members' new heads
mesh/delivery closed: the pull request closed unmerged
mesh/check checking 8899b62cd430 on 7c0492b06c37 | novox/mesh-delivery#209 in group feat/47-G-join11

The node-engine sets MESH_NODE to its node's name in every process it runs; the judge refuses a resource whose env sets it, so the mesh's value is the only one.

Builds: design 47 G A-342

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
2026-11-13 09:20:46 +01:00
parent 7044bf5024
commit 8899b62cd4
2 changed files with 25 additions and 0 deletions
@@ -2845,6 +2845,8 @@ func parseManifest(raw []byte, predefined catalogue.PredefinedList) (catalogue.M
// And the config values its resources are declared under (design 42 zfs-owns-zfs §2).
problems = append(problems, IfConfigProblems(m)...)
problems = append(problems, ConfigLinesProblems(m)...)
// And the node's name, which the node-engine sets in every process's env itself (design 47 G A-342).
problems = append(problems, NodeEnvProblems(m)...)
// And what it requires optionally, and the files it delivers only while bound (novox/hq ADR 0330).
problems = append(problems, OptionalProblems(m)...)
// And which setting keys each mergeable file takes (setting_takes.go, novox/hq ADR 0326).
@@ -4125,6 +4127,24 @@ func ProcessBusProblems(m catalogue.Manifest) []string {
return problems
}
// NodeEnv is the variable the node-engine sets to its node's name in the env of every process it runs (design 47 G
// A-342): a resource's own value of it is refused, so the mesh's is the only one.
const NodeEnv = "MESH_NODE"
// NodeEnvProblems are the resources whose env sets NodeEnv themselves.
func NodeEnvProblems(m catalogue.Manifest) []string {
var problems []string
for _, r := range m.Resources {
if env, ok := r["env"].(map[string]any); ok {
if _, sets := env[NodeEnv]; sets {
problems = append(problems, fmt.Sprintf("%s's resource %v sets %s in its env, which the node-engine sets to "+
"its node's name in every process it runs (design 47 G A-342)", m.Module, r["id"], NodeEnv))
}
}
}
return problems
}
func filepathDir(p string) string {
if i := strings.LastIndex(p, "/"); i > 0 {
return p[:i]
@@ -2456,6 +2456,11 @@ func caseAProcessBusNamesOnlyTheModulesOwn(t *testing.T) {
t.Errorf("%s: %v; want a refusal naming %q", name, err, c.says)
}
}
// Design 47 G A-342: a resource setting the node's name in its own env is refused naming it.
ownNode := strings.Replace(mailSenderProcessManifest(t, ""), `"user":"mesh-mail-send"}`, `"user":"mesh-mail-send","env":{"MESH_NODE":"ace"}}`, 1)
if _, err := ParseManifest([]byte(ownNode)); err == nil || !strings.Contains(err.Error(), "MESH_NODE") {
t.Errorf("a process setting MESH_NODE itself: %v; want a refusal naming MESH_NODE", err)
}
// Design 47 G A-340: an event the module consumes, its process may hear.
consumed := strings.Replace(mailSenderProcessManifest(t, `{"consumes":["billing.paid"]}`), `"resources"`, `"consumes":["billing.paid"],"resources"`, 1)
if _, err := ParseManifest([]byte(consumed)); err != nil {