Place pacman's state outside the package manager's own directory, and refuse a module directory in a system package's (issue 1841)
mesh/merge-gate head 098c6d3ec70f merged into trunk 2f05e70734cd — pass: builds pacman → ace, g14, novox, shanks; no bus step; every machine composes with …
mesh/repo-check head 098c6d3ec70f merged into trunk 2f05e70734cd — pass: THE CHANGE ALTERS ITS OWN CHECK (merge-check.sh): main's version judged it; the ch…
mesh/delivery delivered
mesh/check failed: unit: clipmenu/cmd/clipmenu-tools.TestTheLauncherWaitsQuietlyWhileAnotherClipmenudHoldsTheLock: manifest_test.go:199: the launcher …

pacman's state directory said place ".", which resolves to /var/lib/pacman: the
package manager's database directory. The node-engine used it as found and
reported it unhealthy on every machine, and wrote keeper.json into it. It is now
the mesh's directory for the module (place "mesh", /var/lib/mesh/pacman), as
docker's is; keeper.json, the keeper's bus secret and the root helper's socket
follow through ${dir:state}.

checks/owned rule 5 refuses a directory that is, lies in or holds a /var/lib
directory a system package owns (checks/owned/system, read from shanks through
pacman_owns and tmpfiles.d), and any resource inside one. systemd and postgres
collide today and are listed in checks/owned/system-known under issue 1873; that
list only shrinks.
This commit is contained in:
2026-10-22 21:19:15 +02:00
parent 2f05e70734
commit 098c6d3ec7
7 changed files with 364 additions and 19 deletions
@@ -83,7 +83,7 @@ func TestTheKeeperIsAProcessUnderItsOwnAccountWithABusAccountOfItsOwn(t *testing
t.Errorf("the bus account is the keeper's own secret, owned by its account: %v", secrets)
}
state := m.resource(t, "state")
if state["type"] != "directory" || state["place"] != "." || state["unknown"] == nil {
if state["type"] != "directory" || state["place"] != "mesh" || state["unknown"] == nil {
t.Errorf("the state directory: %v", state)
}
order := map[string]int{}
@@ -211,3 +211,37 @@ func TestUpgradeOrderIsATrustedListOfTheMesh(t *testing.T) {
t.Error("a value falls back only to a key of its own type (ADR 0348 §4)")
}
}
// 1841/AC17: the keeper's state directory is the mesh's directory for the module (place "mesh", <data root>/mesh/pacman),
// never place "." or a placement by default: for this module both resolve under /var/lib/pacman, the package manager's
// own database directory (issue 1841: the node-engine used it as found and reported it unhealthy, and wrote keeper.json
// into it). What the keeper and its root helper keep there is still named through ${dir:state}.
func TestTheStateDirectoryIsOutsideThePackageManagersOwn(t *testing.T) {
m := rawManifest(t)
resources, _ := m["resources"].([]any)
var state map[string]any
for _, x := range resources {
if r, _ := x.(map[string]any); r["id"] == "state" {
state = r
}
}
if state == nil || state["type"] != "directory" {
t.Fatalf("no state directory: %v", state)
}
if state["place"] != "mesh" || state["path"] != nil {
t.Fatalf("the state directory says place %v and path %v; it is placed \"mesh\" with no path, so it resolves to "+
"/var/lib/mesh/pacman and not into /var/lib/pacman", state["place"], state["path"])
}
raw, err := os.ReadFile(filepath.Join(moduleDir, "module.json"))
if err != nil {
t.Fatal(err)
}
if bytes.Contains(raw, []byte("/var/lib/pacman")) {
t.Fatal("the manifest names /var/lib/pacman")
}
for _, want := range []string{"${dir:state}/keeper.json", "${dir:state}/broker-keeper.secret", RootSocketPath} {
if !bytes.Contains(raw, []byte(want)) {
t.Errorf("the manifest no longer names %s", want)
}
}
}
+1 -1
View File
@@ -147,7 +147,7 @@
"id": "state",
"type": "directory",
"mode": "0711",
"place": ".",
"place": "mesh",
"unknown": "program"
},
{