Skip to content

fix: auto-clear a stale sign-in-wall pause on login/session recovery - #29

Merged
Multipixelone merged 1 commit into
mainfrom
fix/costco-login-pause-autoresume
Jul 24, 2026
Merged

fix: auto-clear a stale sign-in-wall pause on login/session recovery#29
Multipixelone merged 1 commit into
mainfrom
fix/costco-login-pause-autoresume

Conversation

@Multipixelone

Copy link
Copy Markdown
Owner

Problem

A reported "Costco login won't persist" turned out not to be a cookie/session bug. A transient Costco sign-in wall on 2026-07-06 latched worker_state.paused=1 with a reason string telling the operator to run roomieorder login — but nothing ever cleared that flag:

  • cli login re-authenticated, printed "session persisted", and returned without touching the pause.
  • main._session_check_tick only had a logged-out branch, so it could never un-pause.

Operator-visible loop: log in → "session persisted" → tap button → "Costco is logged out" again. The session was actually healthy (re-authing ~8×/day via the persistent kmsi/WC_PERSISTENT SSO chain); WC_AUTHENTICATION_<memberid> is a session cookie that is re-minted per launch by design, so a logged-out relaunch is expected and self-heals — only the stale pause flag kept ordering down.

Fix

Gated strictly to login/session pauses — captcha challenge, needs_review, worker crash, spend-cap and manual CLI pauses all stay operator-gated:

  • store.pyLOGIN_PAUSE_MARKER + is_login_pause(reason, provider): single source of truth for classifying a sign-in-wall pause from the only thing a pause persists (its reason string). Provider-scoped so a signed-in Amazon probe can't clear a still-walled Costco pause.
  • purchase.py_signin_required builds its message from LOGIN_PAUSE_MARKER, so the reason it latches always carries the marker. Renders identically to the existing live string, so this also recovers an already-latched pause.
  • main.py_session_check_tick now logs every probe outcome (a healthy probe was previously silent) and, on a signed-in probe, clears a matching login pause (Engine._resume_if_login_pause) — self-heals a transient latch.
  • cli.pylogin resumes a matching login pause after a confirmed verify_session(), closing the log-in-but-still-paused loop; doctor now prints resolved absolute cwd/db/profile/catalog paths (and the per-profile absolute path) so a triage run from the repo checkout — whose CWD-relative config defaults read a different, empty DB — can't mistake a stale repo jar for the live service's.

Safety

Auto-resume can re-arm real ordering when DRY_RUN is off, hence the narrow gate. No DOM selectors touched, DRY_RUN untouched.

Tests

nix flake check equivalents pass locally: ruff clean, mypy clean (src + tests), 253 passed / 3 skipped. New coverage:

  • classifier: recognises the sign-in reason (with/without provider), rejects challenge/needs-review/crash/spend-cap/manual/empty
  • probe: resumes a Costco login pause when signed in; keeps a challenge pause latched; won't clear a Costco pause from a signed-in Amazon probe
  • login: clears a matching sign-in pause; leaves a challenge pause latched

Follow-ups (deliberately not in this PR)

  • nix/module.nix env-file quoting (would export DRY_RUN=false into repo shells unless paired with an .envrc guard).
  • Re-deploy with nixos-rebuild switch so a reboot doesn't roll back to the older generation.

A transient Costco sign-in wall latches `worker_state.paused=1` with a
`pause_reason` that tells the operator to run `roomieorder login` — but
nothing ever cleared that flag. `login` re-authenticated, printed "session
persisted", and returned without touching the pause; the periodic session
probe only had a negative branch and could never un-pause. So one transient
failure took the worker down until a human ran the undocumented `resume`,
and the operator saw: log in -> "session persisted" -> tap -> "Costco is
logged out" again. It reads as "login won't persist"; the session was fine
(re-authing 8x/day), the pause flag was stale.

Fix, gated strictly to login/session pauses (captcha `challenge`,
`needs_review`, crash, spend-cap and manual pauses stay operator-gated):

- store: LOGIN_PAUSE_MARKER + is_login_pause(reason, provider) — the single
  source of truth for classifying a sign-in-wall pause from the only thing a
  pause persists, its reason string. Provider-scoped so a signed-in Amazon
  probe can't clear a still-walled Costco pause.
- purchase._signin_required builds its message from LOGIN_PAUSE_MARKER, so
  the reason it latches always carries the marker (and renders identically to
  the existing live string, so the fix also recovers an already-latched pause).
- main._session_check_tick: log every probe outcome (a healthy probe was
  previously silent) and, on a signed-in probe, clear a matching login pause
  (Engine._resume_if_login_pause) — self-heals a transient latch.
- cli login: after a confirmed verify_session(), resume a matching login
  pause, closing the log-in-but-still-paused loop the reason string sends the
  operator into.
- cli doctor: print resolved absolute cwd/db/profile/catalog paths and the
  per-profile absolute path, so a triage run from the repo (CWD-relative
  config defaults) can't mistake a stale repo jar for the live service's.

Auto-resume can re-arm real ordering when DRY_RUN is off, hence the narrow
gate. Does not touch DOM selectors or DRY_RUN. Tests cover the classifier,
the provider-scoped probe resume, challenge-stays-latched, and the login
pause-clear.
@Multipixelone
Multipixelone enabled auto-merge (squash) July 24, 2026 05:20
@Multipixelone
Multipixelone merged commit afddd17 into main Jul 24, 2026
2 checks passed
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.

1 participant