A login the mesh set is given back, and undeclaring one no longer stops the apply (hq issue 225)

A user had no removal, so an undeclared one failed as an orphan and
aborted every apply after. Removal now keeps the account, gives back
the shell recorded when the mesh first changed it if it is still the
mesh's and still usable, and says why otherwise (hq ADR 0176 §2).
A shell is refused before it is set unless it is executable and listed
in /etc/shells, since usermod succeeds on a missing one.
This commit is contained in:
jochen
2026-10-04 03:57:34 +02:00
parent 27fb22fddb
commit 5d5dccdd55
5 changed files with 486 additions and 19 deletions
+21
View File
@@ -95,6 +95,13 @@ type Applied struct {
// file itself was — so undeclaring it gives the machine back exactly what it had.
Into *Into `json:"into,omitempty"`
// Shell is, for a user, the login shell the account had before the mesh first set one, and
// the shell the mesh set last (novox/hq ADR 0176 §2, issue 225). Removal gives the found shell
// back, and only while the account still has the one the mesh set: a shell a person chose since
// is theirs. Absent when the mesh never changed the shell, and on a record written before the
// host kept it — then the shell is left exactly as it is.
Shell *LoginShell `json:"shell,omitempty"`
// Reads is, for a container, the digest of each file it was created reading — its env-files
// and the files mounted into it — by path (novox/hq 04-ISSUES/103).
//
@@ -597,6 +604,20 @@ type FoundUnit struct {
Boot string `json:"boot,omitempty"`
}
// LoginShell is what the host knows about an account's login shell, to give it back.
type LoginShell struct {
// Found is the shell the account had when the mesh first changed it. Never overwritten by a
// later change: what is given back is what was there before the mesh, not the mesh's own
// previous choice. Empty for an account the mesh created, which had no shell before it.
Found string `json:"found,omitempty"`
// Set is the shell the mesh set last — what removal compares the account against, since the
// declaration that said so is gone by then.
Set string `json:"set"`
// Created is an account the mesh made. Kept only so removal can say why there is nothing to
// give back; the account itself is never deleted.
Created bool `json:"created,omitempty"`
}
// PendingFound is a unit as found by an apply of its service that has not yet been recorded, and
// who asked for that apply — so only a declaration from the same origin can say it is gone.
type PendingFound struct {