package catalogue import ( "testing" ) // Defends novox/hq ADR 0203 (the account's environment is one module's, and every module // contributes to it) and ADR 0204 (shell code in named slots, placed by the login shell's holder). // Sourcing twice changes nothing (ADR 0203 §3): a login shell that starts another reads the file // again, and a PATH that grew each time would be the symptom. Run by a real `sh`, because the claim // is about what a shell does with the file, not about what the file looks like. // The environment.d rendering, read by the service manager's own generator where this machine has // one — the same reader an account's user manager runs, so the PATH it composes is the one asserted. // // The generator also reads the machine's own environment.d (/etc, /run, /usr/lib, /usr/local/lib), and // no option points it elsewhere: a desktop whose snapd appends its bin directory failed this, on main, // for a file the mesh never wrote (novox/hq issue 432). So the generator is run twice, once without the // mesh's file, and what the machine's own files make of PATH and set is held out of the verdict. // // A machine without the generator — the build seat's toolchain image holds no systemd — cannot judge // this and says so: there the rendering is held byte for byte by // TestTheEnvironmentRendersForTheServiceManagerByteForByte, and this reading only where systemd runs. // ADR 0203 §1 and ADR 0204 §1: both seats are the mesh's own, held once per machine; the login // shell's contract is `execute`, described and with a schema an agent can call. func TestTheSeatTableCarriesTheEnvironmentAndTheLoginShell(t *testing.T) { env, ok := SeatNamed("node-environment") if !ok || env.Scope != ScopeNode || env.Decision != "novox/hq ADR 0203" || len(env.Serves)+len(env.Accepts)+len(env.Emits) != 0 || env.Delivers != "" { t.Fatalf("node-environment is not a node seat with no protocol: %+v (defined %v)", env, ok) } shell, ok := SeatNamed("node-login-shell") if !ok || shell.Scope != ScopeNode || shell.Decision != "novox/hq ADR 0204" { t.Fatalf("node-login-shell is not a node seat: %+v (defined %v)", shell, ok) } if len(shell.Serves) != 1 || shell.Serves[0].Name != "execute" || shell.Serves[0].Description == "" { t.Fatalf("the login shell serves %+v, not execute alone", shell.Serves) } props, _ := shell.Serves[0].Input["properties"].(map[string]any) required, _ := shell.Serves[0].Input["required"].([]string) if _, has := props["command"]; !has || len(required) != 1 || required[0] != "command" { t.Fatalf("execute does not require a command: %v", shell.Serves[0].Input) } if _, has := props["timeout_seconds"]; !has { t.Fatalf("execute takes no timeout: %v", props) } }