Declare the operator's account in the openrazer group (hq ADR 0252, issue 247)
mesh/merge-gate pass: builds openrazer → g14, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery covered: a later merge that contains it was delivered: novox/mesh-catalog@5d7d9020b8c7 (merged as bf542128 into main, walk plan-17914696454…
mesh/delivery-group group feat/module-groups delivered: every member is delivered

The daemon refuses to start outside the group, and the fix was a sudo step by hand that nothing
recorded. The module now declares it; the operator logs in again once.
This commit is contained in:
jochen
2026-10-08 12:04:08 +02:00
parent f7b1853b8b
commit da57051fa3
5 changed files with 61 additions and 24 deletions
@@ -90,21 +90,36 @@ func TestItInstallsTheStackAndStartsNothing(t *testing.T) {
t.Fatalf("%+v", m)
}
var pkgs []string
for _, r := range m.Resources {
if r["type"] != "package" {
t.Errorf("only packages: %v", r)
var accounts []map[string]any
for i, r := range m.Resources {
switch r["type"] {
case "package":
if len(accounts) > 0 {
t.Errorf("a package after the account: the group is the driver's package's to make first: %v", r)
}
pkgs = append(pkgs, r["package"].(string))
case "user":
accounts = append(accounts, m.Resources[i])
default:
t.Errorf("only packages and the account's group: %v", r)
}
pkgs = append(pkgs, r["package"].(string))
}
if !reflect.DeepEqual(pkgs, packages) {
t.Fatalf("%v", pkgs)
}
// The operator's account in the driver's group, and nothing else of the account: its shell and home
// are the login shell's module's (novox/hq ADR 0252). Written after the packages, so the group the
// driver's package makes exists when the account is put in it.
want := map[string]any{"id": "account", "type": "user", "name": "${machine:account}", "groups": []any{group}}
if len(accounts) != 1 || !reflect.DeepEqual(accounts[0], want) {
t.Fatalf("the account: %v, want %v", accounts, want)
}
if m.Claims != nil || m.Seats != nil || m.Environment != nil || m.Shell != nil || m.Contributions != nil {
t.Fatal("it holds no seat, sets no environment and adds no start")
}
// The tray is polychromatic's, from outside the official repositories; the kernel headers DKMS
// builds against are the kernel's; the account's groups are its user resource's (zsh's).
for _, never := range []string{"polychromatic", "linux-headers", "\"dkms\"", "\"user\"", "groups"} {
// builds against are the kernel's.
for _, never := range []string{"polychromatic", "linux-headers", "\"dkms\"", "\"shell\"", "\"home\""} {
if strings.Contains(raw, never) {
t.Errorf("module.json names %s", never)
}
@@ -445,7 +445,8 @@ func (m *Machine) Check() (CheckAnswer, error) {
add("the group openrazer does not exist", "it comes with openrazer-driver-dkms (sysusers): reinstall it, or `sudo systemd-sysusers`")
case !g.Account:
add("the account is not in the openrazer group: the daemon refuses to start, and the devices' files are the group's",
"`sudo gpasswd -a $USER openrazer`, then log out of every session (or reboot)")
"the module declares the account in the group (novox/hq ADR 0252): send this machine its declaration, "+
"then log out of every session (or reboot); the apply's outcome says why if it did not")
case g.Manager != nil && !*g.Manager:
add("the account is in the openrazer group, but its running service manager started before it was",
"log out of every session (or reboot), so the service manager starts again with the group")
@@ -133,7 +133,7 @@ func TestCheckPassesTheWholeStackAndNamesWhatIsMissing(t *testing.T) {
all = append(all, x.What+" => "+x.Do)
}
got := strings.Join(all, "\n")
for _, want := range []string{"not built for the running kernel 7.3.0-arch1-1", "not in the openrazer group", "gpasswd -a $USER openrazer",
for _, want := range []string{"not built for the running kernel 7.3.0-arch1-1", "not in the openrazer group", "the module declares the account in the group",
"a second start: ~/.config/i3/config:1", "failed at its last start: razer | CRITICAL | User is not a member"} {
if !strings.Contains(got, want) {
t.Errorf("no finding %q in\n%s", want, got)