Skip to content

[feature] Persist and surface token-invalidation state before the 3-strike auto-removal #655

Description

@choa712

Problem Statement

When the upstream provider permanently revokes an account's OAuth token (e.g. the one-time refresh token was consumed elsewhere — the scenario behind #495-style incidents), the runtime handles it with a cooldown: applyMonotonicAuthCooldown(tokenInvalidationCooldownMs) (default 5 min) plus recordFailure (lib/runtime-rotation-proxy.ts, upstream-401 invalidation path). Removal only happens after MAX_AUTH_FAILURES_BEFORE_REMOVAL = 3 consecutive auth failures (lib/request/failure-policy.ts, lib/constants.ts).

Between revocation and eventual removal, the operator has no persisted signal that the account is dead:

  • status / list show the account as normal (or just generic [rate-limited] flags); only a live check probe reveals "authentication token has been invalidated".
  • Selection diagnostics show health=100 for the revoked account.
  • Nothing marks "this account needs re-login" until the account silently disappears via the 3-strike removal.

In our incident we only understood the state after running live probes per account, and worked around it by manually account pause-ing the revoked account.

Proposed Solution

Persist an invalidation marker on the account when the invalidation path fires — e.g. authInvalidatedAt (+ optional last error code) stored alongside consecutiveAuthFailures:

  • cleared on the next successful refresh or login;
  • rendered as a badge in list / status / check (e.g. [token-invalid — re-login needed]);
  • exposed to selection diagnostics (why-selected) so the account shows as unavailable-with-reason instead of health=100;
  • optionally, while the marker is set, selection treats the account like paused (candidate-excluded) instead of retrying it every cooldown expiry — this removes the 401-flap loop for permanently revoked tokens while keeping the anti-cascade cooldown rationale intact.

Expected impact: operators can see at a glance which account needs re-login, and revoked accounts stop periodically re-entering selection until a human fixes them.

Alternatives Considered

  • Rely on the 3-strike auto-removal alone: works eventually, but the removal is silent, the pre-removal window is invisible, and removal deletes the stored account (heavier UX than "flagged, waiting for re-login").
  • Longer tokenInvalidationCooldownMs: reduces flapping but still invisible to the operator and delays legitimate recovery after a re-login.
  • Manual account pause (our current workaround): effective but requires the operator to have already diagnosed the problem.

Scope

In scope: persisting/clearing the marker on the existing invalidation code paths, surfacing it in list/status/check/why-selected, optional candidate exclusion while set. Out of scope: any change to OAuth flows, refresh lease behavior, or the 3-strike removal policy itself.

Validation Plan

  • Unit: simulate the upstream-401 invalidation path → marker persisted; successful refresh/login → marker cleared.
  • Command-level: with a revoked account, codex-multi-auth list and status show the badge without a live probe; why-selected shows the account as unavailable with reason; after login, badge clears and the account rejoins selection.

Compliance Confirmation

  • This proposal is for legitimate personal development workflows.
  • This proposal does not request bypassing OpenAI controls or policies.
  • This proposal does not introduce multi-tenant resale behavior.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions