4da82e7f913a968fb741c05fa90fc4afbd0224a1
Written in docs/ rather than COMMS because COMMS is deleted when per-user Claude lands and this describes a project that starts after it — a spec that gets deleted before it is implemented is not a spec. Everything measured on this host on 2026-08-11. The evidence for why it exists: after deleting a member through the UI, the row was gone and the Linux account, a working login shell, a healthy postgres container, 454MB of home and Docker storage, lingering, the runtime directory and the subuid ranges were all still there. Three things the spec carries that reading the code would not have produced. terminate-user is not a barrier. A member's /bin/zsh -i survived it by three hours, and userdel refuses while a process owned by the account is alive, so an implementation that trusts it works on a quiet account and fails on a member who left a shell open. The subuid half. Rootless Docker storage is owned by MAPPED ids, not the member's uid — postgres's data directory belonged to 231141, not 1002. userdel releases the range and a later account can be allocated it, so a check for "nothing owned by the freed uid" passes while hundreds of megabytes are still owned by the freed range. Verification has to scan the range. And a correction to the order I actually used: sever the data from the uid BEFORE releasing it. The teardown ran userdel first and removed data after, which leaves a window where the uid is free while files still carry it. The irreversible step goes last. Also specified: never userdel -r, preserve-by-chown as the default with destroy opt-in, refuse to release the uid if the sever failed, and do not run anything as the member after terminating — creating a session recreates the runtime directory the step just removed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Description
No description provided
42 MiB
Languages
TypeScript
90.9%
Shell
4.7%
JavaScript
4.1%
CSS
0.2%
HTML
0.1%