Skip to content

Harden account departure and purge flows - #28

Merged
jonasehrlich merged 10 commits into
mainfrom
claude/issue-26-commit-coverage-61959f
Aug 16, 2026
Merged

jonasehrlich merged 10 commits into
mainfrom
claude/issue-26-commit-coverage-61959f

Conversation

@jonasehrlich

Copy link
Copy Markdown
Owner

Summary

  • verify account identity before writing SSH keys and pin the home and .ssh directories during updates
  • remove all authorized keys on departure, report crontab read failures, and tolerate a missing optional atrm
  • run membership safety guards before system mutations and avoid disabling a rejoining member after a partial sync failure
  • make purge crash-safe with a persisted deletion marker and per-account result saves
  • defer the v1 store backup until the first real save and read shadow expiry with getspnam_r
  • align lifecycle naming and documentation around departed, disabled, and deleted accounts

Why

The departure and purge flow still had error, race, and interruption paths that could modify the wrong account, leave access material behind, disable a member who was rejoining, or leave the users database inconsistent with the machine.

Impact

Departures remain reversible during retention while removing active access. Purge only permanently deletes eligible accounts, resumes interrupted octosync deletions safely, and preserves account IDs for a later rejoin. Dry runs no longer create migration artifacts.

Validation

  • cargo test --all-targets with 115 tests passing
  • Linux cross-build with cargo zigbuild --all-targets --target x86_64-unknown-linux-gnu
  • formatting, check, lint, and Markdown commit hooks

Closes #26

Abort before mutation when fetched membership contains no stored users, refuse purges on empty membership, and avoid repeating unfinished account removal for current members.

Refs #26
Persist an in-progress marker before userdel and retain it after ambiguous failures. A later run can finish the store update when the account is already gone without treating independent removal as success.

Refs #26
Delete the complete authorized_keys file when an account expires, including manually configured entries. Resolve and remove it through pinned directory descriptors so symlink or replacement races cannot redirect the operation.

Refs #26
Report crontab listing failures that are not an absent crontab. Attempt cron and at cleanup independently, and treat a missing atrm like the optional atq command.

Refs #26
Use getspnam_r with caller-owned storage and grow the buffer on ERANGE. Propagate lookup errors instead of relying on libc static storage.

Refs #26
Use disabled for accounts retained after departure and deleted for accounts removed by purge. Apply the same names to actor messages, store fields, v2 JSON keys, logs, comments, and tests.

Refs #26
Describe disabled and deleted accounts consistently in the README. Reorganize the unreleased changelog into focused lifecycle, synchronization, identity, SSH key, and store sections.

Refs #26
@jonasehrlich
jonasehrlich marked this pull request as ready for review August 16, 2026 21:42
@jonasehrlich
jonasehrlich merged commit 61354d7 into main Aug 16, 2026
10 checks passed
@jonasehrlich
jonasehrlich deleted the claude/issue-26-commit-coverage-61959f branch August 16, 2026 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Harden the departure and purge flow after the expiry rework

1 participant