Skip to main content

Module cleanup

Module cleanup 

Source
Expand description

On-disk / keychain credential cleanup for a deleted identity account.

Layer 1 of the account-delete auth-lifecycle remediation (docs/analysis/ANALYSIS_ACCOUNT_DELETE_AUTH_LIFECYCLE_GAP_2026_07_14.md §4 option 1): deleting an account row must not leave its credential material behind. Two secret backends carry on-host state:

  • SecretRef::Keychain — delete the OS-keychain entry (moved here from the inline block in the deleteidentityaccount handler).
  • SecretRef::OAuthConfigDir { dir } — the CLI’s live access + refresh tokens sit in that directory; remove the tree, except the provider’s conversation history (ProviderConfig::history_native_subdir, e.g. Claude’s projects/), which lives in the same directory when auth is shared. History and credentials are separate persistence categories (SPEC_AGENT_IDENTITY_HISTORY_PERSISTENCE_PROTOCOL_2026_08_16.md P1); deleting a login must not delete the conversations (SPEC_ARMORY_ACCOUNTS_DELETE_AND_INLINE_DETAIL_2026_10_04.md H1). This is best-effort and containment-guarded: the dir is only removed when it resolves INSIDE the agentmux identities root (~/.agentmux/shared/identities/). The legacy ~/.claude migration case (and any other ambient/global CLI dir) is the user’s own login — log and skip, never delete.

Other variants (Env, SecretsManager, PlaintextDev) hold no agentmux-owned on-host state → no-op.

All log lines use the identity.delete: prefix so they land in the muxlog auth vocabulary (regex identity\.(unlink|delete|self\.|account)), and use info!/warn! — the production filter is “agentmuxsrv=info,info”, so debug! would be invisible (reagent P1, PR #2143). Provider-side token revocation (running the CLI’s own logout against the dir before deleting) is an explicit follow-up — it needs per-provider subprocess plumbing this module doesn’t have.

Enums§

PruneOutcome 🔒
SecretCleanup
What cleanup_account_secrets did, for callers/tests to assert on. Logging already happened inside the function.

Functions§

cleanup_account_secrets
Best-effort removal of the on-host credential material behind acct.secret_ref. Never returns Err — account deletion must not be blocked by cleanup trouble; every outcome is logged.
cleanup_oauth_dir 🔒
history_subdir_for 🔒
The conversation-history subdirectory name for an OAuth config dir: from the account’s provider, or else from the dir’s own name, which is the provider’s auth_dir_name (identities/<account>/<auth_dir_name>/).
history_subdir_for_auth_dir 🔒
prune_orphan_keeping_history 🔒
Removes an orphaned account dir (<root>/<account_id>/), only if it resolves strictly inside root (the same escape guard cleanup_oauth_dir uses), except that each provider subdir’s conversation history is kept, the same rule account delete follows (remove_credentials_keep_history). Without this, the sweep would delete, a few minutes later, the history that deleting the account kept.
remove_credentials_keep_history 🔒
Remove dir, keeping its history child when that child is a real, non-empty directory. Returns the kept path, or None when the whole tree was removed.
sweep_orphaned_account_dirs
Sweep identities_root’s direct children for orphaned per-account dirs: compute_and_ensure_account_dir mints a fresh <account_id>/ dir and writes real credential files into it BEFORE the login that dir belongs to ever completes, so no IdentityAccount row exists yet to reference it. A login that’s abandoned, times out, or crashes the app mid-flow leaves that directory behind forever — reagent’s finding on #2260: “abandoned/failed attempts leave orphaned directories with no cleanup path.”