Judge machines with the node-engine that knows unknown and knows (issue 1024, ADR 0422)
mesh/merge-gate head 34197afa0181 merged into trunk c43772fd94eb — pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus…
mesh/repo-check head 34197afa0181 merged into trunk c43772fd94eb — pass: its merge-check.sh passed
mesh/delivery delivered
mesh/merge-gate head 34197afa0181 merged into trunk c43772fd94eb — pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus…
mesh/repo-check head 34197afa0181 merged into trunk c43772fd94eb — pass: its merge-check.sh passed
mesh/delivery delivered
The gate composes every machine with the node-engine's own validator, vendored at mesh-host of 2026-10-15, which refuses the `unknown` and `knows` keys mesh-host #117 added; every catalogue manifest using them was refused on every machine (mesh-catalog #349). The pin moves to #117's merge, 6469e8238443, delivered; only the declaration validator changes in vendor/. A test holds the gate to taking such a directory.
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/novox/mesh-host/validate"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A directory or an archive that says how it reacts to files it does not know (novox/hq ADR 0422) is a
|
||||||
|
// declaration the node-engine takes, so the gate, which judges every machine with the node-engine's own
|
||||||
|
// validator, takes it too. Before the pin moved, every catalogue manifest using the words was refused
|
||||||
|
// on every machine (issue 1024).
|
||||||
|
func TestTheGateTakesADirectoryThatSaysHowItReacts(t *testing.T) {
|
||||||
|
decl := fmt.Sprintf(`{"declaration":%d,"resources":[
|
||||||
|
{"id":"xorg.config","type":"directory","path":"/home/a/.config/xorg","mode":"0755","owner":"a","unknown":"move-out","knows":["scripts/"]},
|
||||||
|
{"id":"p10k.theme","type":"archive","source":"https://example.invalid/a.tar","digest":"sha256:`+
|
||||||
|
"0000000000000000000000000000000000000000000000000000000000000000"+
|
||||||
|
`","path":"/home/a/.local/share/powerlevel10k","unknown":"move-out"}]}`, validate.Version)
|
||||||
|
if problems := validate.Declaration([]byte(decl)); len(problems) != 0 {
|
||||||
|
t.Fatalf("refused: %q", problems)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,4 +36,4 @@ require (
|
|||||||
// committed. Every build (the build agent's `go build`, the Dockerfile) compiles from vendor/ and
|
// committed. Every build (the build agent's `go build`, the Dockerfile) compiles from vendor/ and
|
||||||
// fetches nothing; go refuses to build when vendor/ and this file disagree, so a pin moved without
|
// fetches nothing; go refuses to build when vendor/ and this file disagree, so a pin moved without
|
||||||
// `go mod vendor` fails loudly, at once, everywhere.
|
// `go mod vendor` fails loudly, at once, everywhere.
|
||||||
replace github.com/novox/mesh-host => git.novox.be/novox/mesh-host v0.0.0-20261015211328-5a7ec3775b98
|
replace github.com/novox/mesh-host => git.novox.be/novox/mesh-host v0.0.0-20261017162006-6469e8238443
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
git.novox.be/novox/mesh-host v0.0.0-20261015211328-5a7ec3775b98 h1:27nPn3XO9yfrHoAOuTuuJPVZTA3Bdnbqlc2wRI7S/LY=
|
git.novox.be/novox/mesh-host v0.0.0-20261017162006-6469e8238443 h1:zUtpGbiH9DLjCPY+KJsm+PZ25yW6k/NmGVS3haGFfMM=
|
||||||
git.novox.be/novox/mesh-host v0.0.0-20261015211328-5a7ec3775b98/go.mod h1:5QOm3cIfu/k9fN6QqgDbKGCcDst7Ul1UlcfsiMVm9j4=
|
git.novox.be/novox/mesh-host v0.0.0-20261017162006-6469e8238443/go.mod h1:5QOm3cIfu/k9fN6QqgDbKGCcDst7Ul1UlcfsiMVm9j4=
|
||||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261015210729-d3e182503c19 h1:mAMt3KFmrHzDiBv4MLL94opWcG9y73ISMrBUyisapQE=
|
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261015210729-d3e182503c19 h1:mAMt3KFmrHzDiBv4MLL94opWcG9y73ISMrBUyisapQE=
|
||||||
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261015210729-d3e182503c19/go.mod h1:GFuZUElBZ9A++mxgIKo97aXXo+kV0uJ/UkbhQPPIbrY=
|
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261015210729-d3e182503c19/go.mod h1:GFuZUElBZ9A++mxgIKo97aXXo+kV0uJ/UkbhQPPIbrY=
|
||||||
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 h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=
|
||||||
|
|||||||
+59
@@ -124,6 +124,60 @@ type Directory struct {
|
|||||||
// Owner is the user this belongs to, by name. Absent means root, which is what everything
|
// Owner is the user this belongs to, by name. Absent means root, which is what everything
|
||||||
// managed was until users existed.
|
// managed was until users existed.
|
||||||
Owner string `json:"owner,omitempty"`
|
Owner string `json:"owner,omitempty"`
|
||||||
|
// Unknown says how the directory treats a path inside it that nothing declared (issue 1024, novox/hq ADR 0422):
|
||||||
|
// move-out, module or program. Empty means not said, and nothing moves.
|
||||||
|
Unknown string `json:"unknown,omitempty"`
|
||||||
|
// Knows names paths relative to Path that are not declared but belong here; a trailing "/" names a folder and
|
||||||
|
// everything in it.
|
||||||
|
Knows []string `json:"knows,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// How a directory or archive treats what it did not write (issue 1024, ADR 0422).
|
||||||
|
const (
|
||||||
|
UnknownMoveOut = "move-out"
|
||||||
|
UnknownModule = "module"
|
||||||
|
UnknownProgram = "program"
|
||||||
|
)
|
||||||
|
|
||||||
|
// checkUnknown judges the unknown and knows fields of a directory or an archive.
|
||||||
|
func checkUnknown(where, kind, unknown string, knows []string) []string {
|
||||||
|
var problems []string
|
||||||
|
switch unknown {
|
||||||
|
case "", UnknownMoveOut, UnknownModule, UnknownProgram:
|
||||||
|
default:
|
||||||
|
problems = append(problems, fmt.Sprintf(
|
||||||
|
"%s: a %s's unknown is %q; it is %q, %q or %q (issue 1024)", where, kind, unknown,
|
||||||
|
UnknownMoveOut, UnknownModule, UnknownProgram))
|
||||||
|
}
|
||||||
|
if len(knows) > 0 && unknown == "" {
|
||||||
|
problems = append(problems, where+": knows is given without unknown, and says nothing without it")
|
||||||
|
}
|
||||||
|
seen := map[string]bool{}
|
||||||
|
for _, k := range knows {
|
||||||
|
switch {
|
||||||
|
case k == "":
|
||||||
|
problems = append(problems, where+": knows holds an empty entry")
|
||||||
|
continue
|
||||||
|
case strings.HasPrefix(k, "/"):
|
||||||
|
problems = append(problems, fmt.Sprintf("%s: knows entry %q is absolute; it is relative to the path", where, k))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
bad := false
|
||||||
|
for _, c := range strings.Split(strings.TrimSuffix(k, "/"), "/") {
|
||||||
|
if c == "" || c == "." || c == ".." {
|
||||||
|
bad = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if bad {
|
||||||
|
problems = append(problems, fmt.Sprintf("%s: knows entry %q holds an empty, . or .. component", where, k))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if seen[k] {
|
||||||
|
problems = append(problems, fmt.Sprintf("%s: knows entry %q is repeated", where, k))
|
||||||
|
}
|
||||||
|
seen[k] = true
|
||||||
|
}
|
||||||
|
return problems
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Directory) Identity() string { return d.ID }
|
func (d *Directory) Identity() string { return d.ID }
|
||||||
@@ -141,6 +195,7 @@ func (d *Directory) validate(where string, _ bool) []string {
|
|||||||
if len(mode) == 4 && mode[0] == '2' {
|
if len(mode) == 4 && mode[0] == '2' {
|
||||||
mode = "0" + mode[1:]
|
mode = "0" + mode[1:]
|
||||||
}
|
}
|
||||||
|
problems = append(problems, checkUnknown(where, "directory", d.Unknown, d.Knows)...)
|
||||||
return append(problems, checkMode(where, mode)...)
|
return append(problems, checkMode(where, mode)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,6 +751,9 @@ type Archive struct {
|
|||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
// Owner is the user the unpacked files belong to. Absent means root.
|
// Owner is the user the unpacked files belong to. Absent means root.
|
||||||
Owner string `json:"owner,omitempty"`
|
Owner string `json:"owner,omitempty"`
|
||||||
|
// Unknown and Knows are as a directory's (issue 1024, ADR 0422).
|
||||||
|
Unknown string `json:"unknown,omitempty"`
|
||||||
|
Knows []string `json:"knows,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Archive) Identity() string { return a.ID }
|
func (a *Archive) Identity() string { return a.ID }
|
||||||
@@ -716,6 +774,7 @@ func (a *Archive) validate(where string, _ bool) []string {
|
|||||||
problems = append(problems, where+
|
problems = append(problems, where+
|
||||||
": an archive is pinned by digest, as sha256:<64 hex characters>")
|
": an archive is pinned by digest, as sha256:<64 hex characters>")
|
||||||
}
|
}
|
||||||
|
problems = append(problems, checkUnknown(where, "archive", a.Unknown, a.Knows)...)
|
||||||
return problems
|
return problems
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+2
-2
@@ -79,7 +79,7 @@ github.com/nats-io/nkeys
|
|||||||
# github.com/nats-io/nuid v1.0.1
|
# github.com/nats-io/nuid v1.0.1
|
||||||
## explicit
|
## explicit
|
||||||
github.com/nats-io/nuid
|
github.com/nats-io/nuid
|
||||||
# github.com/novox/mesh-host v0.0.0 => git.novox.be/novox/mesh-host v0.0.0-20261015211328-5a7ec3775b98
|
# github.com/novox/mesh-host v0.0.0 => git.novox.be/novox/mesh-host v0.0.0-20261017162006-6469e8238443
|
||||||
## explicit; go 1.26.0
|
## explicit; go 1.26.0
|
||||||
github.com/novox/mesh-host/internal/declaration
|
github.com/novox/mesh-host/internal/declaration
|
||||||
github.com/novox/mesh-host/rootsearch
|
github.com/novox/mesh-host/rootsearch
|
||||||
@@ -139,4 +139,4 @@ golang.org/x/text/width
|
|||||||
# golang.org/x/time v0.15.0
|
# golang.org/x/time v0.15.0
|
||||||
## explicit; go 1.25.0
|
## explicit; go 1.25.0
|
||||||
golang.org/x/time/rate
|
golang.org/x/time/rate
|
||||||
# github.com/novox/mesh-host => git.novox.be/novox/mesh-host v0.0.0-20261015211328-5a7ec3775b98
|
# github.com/novox/mesh-host => git.novox.be/novox/mesh-host v0.0.0-20261017162006-6469e8238443
|
||||||
|
|||||||
Reference in New Issue
Block a user