From 363719894c8ffe32c790dcf67dcf7c9cf40ea4ab Mon Sep 17 00:00:00 2001 From: Flavio Oliva Date: Mon, 29 Jun 2026 18:04:29 +0100 Subject: [PATCH] fix(api): keep --password-store=basic at generation to fix macOS 401 (#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 --- src/gflow_cli/api/client.py | 8 +++++++- tests/api/test_client_launch_kwargs.py | 7 ++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/gflow_cli/api/client.py b/src/gflow_cli/api/client.py index 85a60a0d0..fd2a967c0 100644 --- a/src/gflow_cli/api/client.py +++ b/src/gflow_cli/api/client.py @@ -333,10 +333,16 @@ def _persistent_context_kwargs(self) -> JsonObject: "locale": "en-US", "extra_http_headers": {"Accept-Language": "en-US,en;q=0.9"}, "channel": channel_for_profile(self.profile_dir), + # Do NOT suppress Playwright's default --password-store=basic here. + # auth login (auth/real_chrome.py) seals the profile's cookies with + # the *basic* store; if generation lets Chrome fall back to the OS + # keychain (macOS "Chrome Safe Storage") the basic-sealed cookies + # can't be decrypted -> logged-out context -> 401 on createProject. + # Keeping the flag (via Playwright's default) makes both paths + # symmetric. See issue #222. "ignore_default_args": [ "--enable-automation", "--no-sandbox", - "--password-store=basic", ], "args": ["--disable-blink-features=AutomationControlled", "--disable-dev-shm-usage"], } diff --git a/tests/api/test_client_launch_kwargs.py b/tests/api/test_client_launch_kwargs.py index 04a165468..42fc83b4c 100644 --- a/tests/api/test_client_launch_kwargs.py +++ b/tests/api/test_client_launch_kwargs.py @@ -31,8 +31,13 @@ def test_persistent_context_kwargs_are_unchanged(tmp_path: Path) -> None: assert kwargs["ignore_default_args"] == [ "--enable-automation", "--no-sandbox", - "--password-store=basic", ] + # Regression for #222: generation must NOT suppress --password-store=basic. + # auth login seals the profile cookies with the *basic* store; if generation + # lets Chrome fall back to the macOS keychain, those cookies can't be + # decrypted -> logged-out -> 401 on createProject. (Unit-level proxy: the + # real failure only reproduces on a headed Chrome on macOS.) + assert "--password-store=basic" not in kwargs["ignore_default_args"] assert kwargs["args"] == [ "--disable-blink-features=AutomationControlled", "--disable-dev-shm-usage",