close §4: officer_jg has no users row, and the adoption rule held

Queried the two rows the handoff asked for. There is no `users` row for `officer_jg`, and
ids 2-4 are absent, which tells the whole story: an earlier row for jg@pertento.ai under the
`officer_`-prefixed naming got a Linux account at uid 1001, the row was deleted without
`userdel`, and the re-created account correctly refused to adopt it and took uid 1002. The
home is derived from the email, which never changed — hence two accounts, one home.

So this is the delete path, not a bypassed adoption rule, and it is observed rather than
theorised. Inert today: the home belongs to green and its ACL names only pastilhas and green,
so officer_jg cannot read it. The live hazard is uid 1001 going to the next member, which is
what deprovisionOsAccount and its chown to the service user would close.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-11 21:43:48 +00:00
co-authored by Claude Opus 5
parent f09385c789
commit 6cd462caf6
@@ -124,12 +124,31 @@ Two accounts, one home. The home is owned by `green`, and its ACL names only `pa
created a second account rather than adopting the first, but I have not confirmed a mechanism and am not created a second account rather than adopting the first, but I have not confirmed a mechanism and am not
guessing at one. guessing at one.
I have **not** queried the `users` table for the rows you asked for. That is the owner's production **Answered — and the adoption rule is intact.** The `users` rows, since queried:
database and I did not want to touch it unasked. The `getent` lines are above; the rows are one query away
whenever the owner is happy for me to run it.
This is also an argument for `deprovisionOsAccount` (your §3) landing before any account deletion happens ```
in anger — uid reuse is already visible here, not hypothetical. id | email | username | os_user | role
1 | pastilhas@officer.dev | pastilhas | | Super Admin
5 | jg@pertento.ai | green | green | Developer
```
There is **no `users` row for `officer_jg` at all**, and note the id gap — 2, 3 and 4 are absent. So
`ensureOsUser` never adopted anything it should not have. What happened instead:
1. An earlier row for `jg@pertento.ai` used the `officer_`-prefixed naming, so it got Linux account
`officer_jg` at uid 1001, with its home derived from the **email**.
2. That row was deleted. `deleteUserHandler` removes the row and never runs `userdel`, so the Linux account,
its home and its uid survived — your §3, exactly.
3. The account was re-created as `green`. `ensureOsUser` correctly **refused** to adopt `officer_jg` (the
username no longer matched) and created a fresh account at uid 1002.
4. The home path is derived from the email, which never changed. Hence two Linux accounts, one home.
So this is not a hole in the adoption rule — it is the delete path, observed rather than theorised. Today it
is inert: the home is owned by `green` and its ACL names only `pastilhas` and `green`, so `officer_jg` has a
login shell into a directory it cannot read. The live hazard is uid 1001 being handed to the next member.
Which makes `deprovisionOsAccount` (your §3) the fix, and the `chown -R` to the service user the part that
actually closes it. Worth landing before any account is deleted in anger.
--- ---