Files
mesh-host/internal/apply/access_test.go
T
jschoubben 51e97a8c14 Give every module an identity and keep shared folders through ACL entries (hq ADR 0325, issue 567)
A module's containers ran as whatever their image chose and shared folders were
made writable by putting accounts in the folder's group (ADR 0312), which ADR 0325
supersedes. The engine now makes each declared module identity as a system account
with the controller's numbers, runs a container declaring `identity` as it, and keeps
each placed shared folder usable through one POSIX ACL entry per user, set through
the kernel's xattrs on descriptors it opened itself. A folder holding data is kept
only after the operator's warrant (the take act); a missing folder is made where its
data lives and waits where its disk is not; root's data is never kept. A watch and a
bounded sweep put back what an app narrows. The group grant is removed, and what it
put an account in is taken back.

Reuses the descriptor walks, the create act, the missing-path wait and the warrant-
backed act message from the paused issue 567 branch.
2026-10-12 18:43:04 +02:00

76 lines
2.7 KiB
Go

package apply
import (
"context"
"os"
"testing"
"github.com/novox/mesh-host/internal/store"
)
// An operator-owned path the module reaches but does not own (novox/hq ADR 0051).
//
// The host confirms it is present and changes nothing: it does not create it, chown it or set its
// mode, because the media library and the download spool are the operator's and several modules
// share them. This is the opposite of a directory on every axis, and the whole reason the two are
// different shapes.
func TestAnAccessPresentIsConfirmedAndNothingIsChanged(t *testing.T) {
dir := t.TempDir() // the operator's directory, already there
d := declare(t, `{"id":"lib","type":"access","path":"`+dir+`","mode":"read-write"}`)
report, _, err := Apply(context.Background(), archHost(t), d, store.State{},
store.OriginDeclared, noServices, nil, nil)
if err != nil {
t.Fatalf("an operator-owned path that is present was refused: %v", err)
}
if report.Changed() {
t.Fatalf("confirming an access reported a change; the host owns nothing about it")
}
if _, statErr := os.Stat(dir); statErr != nil {
t.Fatalf("the operator's directory was disturbed: %v", statErr)
}
}
// Undeclaring an access never removes the path. Unassigning the module that reached the media
// library must not delete the library — that is the data loss ADR 0030 exists to prevent, on a
// directory the mesh never made. The record is dropped; the operator's data is left exactly as it
// is.
func TestAnUndeclaredAccessLeavesTheOperatorsPathAlone(t *testing.T) {
lib := t.TempDir() // the operator's library
keep := t.TempDir()
if err := os.WriteFile(lib+"/a-real-file", []byte("the operator's data"), 0o644); err != nil {
t.Fatal(err)
}
d := declare(t, `{"id":"lib","type":"access","path":"`+lib+`","mode":"read"}`)
_, state, err := Apply(context.Background(), archHost(t), d, store.State{},
store.OriginDeclared, noServices, nil, nil)
if err != nil {
t.Fatal(err)
}
// The module is unassigned: the mesh no longer declares the access.
empty := declare(t, `{"id":"unrelated","type":"directory","path":"`+keep+`"}`)
report, _, err := Apply(context.Background(), archHost(t), empty, state,
store.OriginDeclared, noServices, nil, nil)
if err != nil {
t.Fatal(err)
}
if _, statErr := os.Stat(lib); statErr != nil {
t.Fatalf("the operator's library was removed when the module stopped reaching it: %v", statErr)
}
if _, statErr := os.Stat(lib + "/a-real-file"); statErr != nil {
t.Fatalf("the operator's data was removed: %v", statErr)
}
var forgot bool
for _, o := range report.Outcomes {
if o.Type == "access" && o.Action == "forgotten" {
forgot = true
}
}
if !forgot {
t.Errorf("dropping an access was not reported as forgotten: %+v", report.Outcomes)
}
}