From c3a20baecee8f7d7596ea0462ed6f4da4e382c9d Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 8 Oct 2026 17:21:16 +0200 Subject: [PATCH] Issue 332: the service manager could neither clear a failed unit nor say what wants it A leftover user unit stayed raised on the workstation: no seat verb showed the dangling enable link that keeps asking for it, or reset its failed record, so the only step left was a shell. Lands per ADR 0246. --- .../00-report.md | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 04-ISSUES/332-the-service-manager-cannot-clear-or-explain-a-failed-unit/00-report.md diff --git a/04-ISSUES/332-the-service-manager-cannot-clear-or-explain-a-failed-unit/00-report.md b/04-ISSUES/332-the-service-manager-cannot-clear-or-explain-a-failed-unit/00-report.md new file mode 100644 index 00000000..2233bfa1 --- /dev/null +++ b/04-ISSUES/332-the-service-manager-cannot-clear-or-explain-a-failed-unit/00-report.md @@ -0,0 +1,61 @@ +--- +status: located +opened: 2026-10-08 +located-in: [mesh-controller internal/catalogue (seats.go, the node-service-manager seat's verbs), mesh-catalog modules/systemd (the seat's holder)] +fixed-by: +amended-design: +--- + +# 332. The service manager cannot clear or explain a failed unit + +## Symptom + +On 2026-10-08 the workstation's machine finding (`machine..units`, from +[issue 315](../315-a-failed-unit-of-a-module-was-never-raised/00-report.md)) listed a user unit of a +clipboard tool that a module had replaced: load state `not-found`, active state `failed`, no unit file. +The operator approved removing it. Two steps were needed, and the `node-service-manager` seat had a verb +for neither: + +1. **Find what still asks for the unit.** The seat's `status` says the file is gone, and its `journal` + says when the unit last failed. Neither says which unit wants it, or whether an enable link in a + `*.wants` directory still names it and dangles. Issue 315's diagnosis found the link from the module's + README, not from a tool. +2. **Clear the failed record.** A manager keeps a unit's failed state and start-limit count until they + are reset. The seat had no verb for `systemctl reset-failed`, so the finding stays raised until the + account's manager restarts. + +Without either verb, the step left is a shell on the machine, which +[ADR 0245](../../02-DECISIONS/0245-a-verb-says-what-it-replaces-and-the-agent-is-guarded-from-working-round-the-mesh.md) rules out: the missing +tool is built in the module that owns the area, on its seat. + +## Fix + +Two verbs on the seat, each saying the command it replaces: + +- **`reset-failed {unit, scope}`** clears one unit's failed record. A unit is required, so the verb never + resets every failed unit at once. It replaces `systemctl reset-failed`. +- **`wanted-by {unit, scope}`** is read-only. It answers what wants, requires or triggers one unit: the + manager's reverse dependencies (`WantedBy`, `RequiredBy`, `UpheldBy`, `BoundBy`, `TriggeredBy` and the + rest, and the units that pull those in), and every enable link naming the unit in the scope's + configuration directories. In user scope that includes the account's own. Each link is given with where + it points, whether it dangles and whose directory it is in. It replaces `systemctl list-dependencies + --reverse` and reading the `*.wants` directories by hand. + +They land in the three steps of +[ADR 0246](../../02-DECISIONS/0246-a-seats-new-verb-is-promised-before-it-is-required.md): + +1. The controller promises both verbs as optional (mesh-controller, this issue's first pull request). +2. The `systemd` module serves both (mesh-catalog). Its check passes only against a controller that + already promises them, so it merges after step 1 is delivered. +3. The controller requires both, in a later pull request, once every holder serves them. + +## How it is checked + +- mesh-controller: `TestResetFailedAndWantedByAreOptionalVerbsOfTheServiceManager` (both promised, + optional, read back optional from the store's row, each naming the command it replaces), and the seat's + verb list in `TestTheServiceManagerSeatServesTheUnitVerbs`. +- mesh-catalog `modules/systemd`: the `wanted_test.go` tests (a dangling enable link in the account's own + configuration found and named, a link matched by its target, an unreadable directory and an unreachable + manager said rather than read as nothing, read-only), and the manifest test that the module serves exactly + the verbs it claims. +- Step 3 is not checked by anything yet, as ADR 0246 says of every optional verb.