Skip to content

fix(api): keep --password-store=basic at generation to fix macOS 401 (#222) - #225

Merged
ffroliva merged 1 commit into
developfrom
bugfix/issue-222-password-store
Jun 29, 2026
Merged

ffroliva merged 1 commit into
developfrom
bugfix/issue-222-password-store

Conversation

@ffroliva

Copy link
Copy Markdown
Owner

Summary

Fixes the macOS 401 AuthExpiredError on project.createProject reported in #222, where gflow image t2i opened a logged-out browser despite a verified auth login.

Root cause — a --password-store asymmetry between login and generation:

  • auth login (auth/real_chrome.py:69) launches Chrome with --password-store=basic, sealing the profile's cookies with Chrome's basic store (not the macOS Keychain).
  • Generation (api/client.py:_persistent_context_kwargs) listed --password-store=basic in ignore_default_args, stripping the flag Playwright adds by default — so that Chrome used the macOS Keychain ("Chrome Safe Storage") to read the cookies.
  • basic-sealed cookies read under the Keychain → decrypt failure → logged-out → 401. macOS/Linux-only; Windows uses DPAPI and ignores the flag (why it never reproduced on Windows, and why auth login/auth status — which don't hit this path — succeeded).

Fix: stop suppressing --password-store=basic at generation so it is symmetric with login.

⚠️ Verification status — INCOMPLETE (needs macOS)

  • Unit: launch-kwargs pin test updated + regression assertion added (tests/api/test_client_launch_kwargs.py) — 2 passed
  • ruff check + ruff format --check clean; pyright src/gflow_cli/api/client.py 0 errors
  • Live gflow image t2i on macOS confirming the 401 is gone — NOT DONE
  • Confirm auth login (still basic) + generation (now basic) round-trip on macOS

This cannot be verified on CI (headless Linux) or on Windows — #222 is a macOS-Keychain-specific failure. Held as draft pending a maintainer macOS run. Auth-surface change — please review the symmetry argument before promoting.

Refs #222 (not Closes) — do not auto-close until macOS-verified.

🤖 Generated with Claude Code

…222)

auth login (auth/real_chrome.py) launches Chrome with --password-store=basic,
sealing the profile's cookies with the *basic* store. Generation suppressed
that flag via ignore_default_args, so on macOS Chrome fell back to the keychain
("Chrome Safe Storage") to read those basic-sealed cookies -> decrypt failure
-> logged-out context -> 401 on project.createProject. Windows is immune (DPAPI
ignores the flag), which is why it reproduced only on macOS and why auth
login/verify (which never hit this path) succeeded.

Fix: stop suppressing Playwright's default --password-store=basic at generation
so it is symmetric with login. Updates the launch-kwargs pin test and adds a
regression assertion (unit-level proxy; the runtime failure only reproduces on
a headed Chrome on macOS).

Refs #222
@ffroliva

Copy link
Copy Markdown
Owner Author

/code-review (high-effort) — no correctness findings. Verified the fix is on the path the issue hit: the #222 log shows ui_automation.setup_shared_page, which is the shared-page branch (ui_automation.py:722-728) where FlowApiClient owns the launch via _persistent_context_kwargs — exactly the code changed here. The standalone ui_automation path (ui_automation.py:774) already passed --password-store=basic; the FlowApiClient shared-page path was the lone inconsistent outlier, which is why the 401 surfaced only there.

Two low-severity follow-ups (non-blocking, not hotfix scope): the scattered --password-store=basic across ~8 launch sites could be centralized; and scripts/dev/spike_patchright.py:113 (a dev replica) now drifts.

Merge decision: merging to develop now (regression risk near-zero — no-op on Windows, symmetric with login/standalone elsewhere). develop is not released; #222 stays open (Refs, not Closes) pending the reporter's macOS gflow image t2i confirmation before this ships in a release.

@ffroliva
ffroliva marked this pull request as ready for review June 29, 2026 17:10
@ffroliva
ffroliva merged commit 44cb08e into develop Jun 29, 2026
9 checks passed
@ffroliva
ffroliva deleted the bugfix/issue-222-password-store branch June 29, 2026 17:11
ffroliva added a commit that referenced this pull request Jun 29, 2026
The shared generation context in FlowApiClient._persistent_context_kwargs was
the ONLY Chrome launch site that did not explicitly pass --password-store=basic
— it merely relied on Playwright's internal default. auth login
(auth/real_chrome.py) and verification (auth/verification.py) seal/read the
profile cookies with Chrome's *basic* store, as do every other launch site
(auth/cookies.py, auth/internal_chromium.py, browser_manager.py,
ui_automation.py). On macOS, letting the generation context fall back to the OS
Keychain ("Chrome Safe Storage") means it cannot decrypt the basic-sealed
cookies -> logged-out context -> HTTP 401 at project.createProject, while login
and verification (which DO pass the flag) succeed. #225 added a comment about
this but never the flag itself.

- _persistent_context_kwargs: add --password-store=basic to args (explicit
  symmetry with all other launch paths; no longer relies on Playwright defaults).
- _log_and_guard_launch: also log launch_args, ignore_default_args, and a
  password_store_basic boolean, so the reporter's macOS run confirms the flag is
  present on the failing path and whether the 401 clears.
- Update the launch-kwargs + recording-client tests to pin the flag in args.

Awaiting macOS verification from the reporter (credit-free) before claiming
fixed. Refs #222
15990166686ll-crypto pushed a commit to 15990166686ll-crypto/gflow-cli that referenced this pull request Aug 24, 2026
…rd-store

fix(api): keep --password-store=basic at generation to fix macOS 401 (ffroliva#222)
15990166686ll-crypto pushed a commit to 15990166686ll-crypto/gflow-cli that referenced this pull request Aug 24, 2026
…iva#222)

The shared generation context in FlowApiClient._persistent_context_kwargs was
the ONLY Chrome launch site that did not explicitly pass --password-store=basic
— it merely relied on Playwright's internal default. auth login
(auth/real_chrome.py) and verification (auth/verification.py) seal/read the
profile cookies with Chrome's *basic* store, as do every other launch site
(auth/cookies.py, auth/internal_chromium.py, browser_manager.py,
ui_automation.py). On macOS, letting the generation context fall back to the OS
Keychain ("Chrome Safe Storage") means it cannot decrypt the basic-sealed
cookies -> logged-out context -> HTTP 401 at project.createProject, while login
and verification (which DO pass the flag) succeed. ffroliva#225 added a comment about
this but never the flag itself.

- _persistent_context_kwargs: add --password-store=basic to args (explicit
  symmetry with all other launch paths; no longer relies on Playwright defaults).
- _log_and_guard_launch: also log launch_args, ignore_default_args, and a
  password_store_basic boolean, so the reporter's macOS run confirms the flag is
  present on the failing path and whether the 401 clears.
- Update the launch-kwargs + recording-client tests to pin the flag in args.

Awaiting macOS verification from the reporter (credit-free) before claiming
fixed. Refs ffroliva#222
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