gflow-cli 0.6.0a1__tar.gz → 0.6.0a2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/.gitignore +1 -0
  2. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/CHANGELOG.md +56 -1
  3. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/KNOWN_ISSUES.md +29 -0
  4. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/PKG-INFO +1 -1
  5. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/PLAN.md +22 -6
  6. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/ARCHITECTURE.md +38 -1
  7. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/AUTHENTICATION.md +28 -4
  8. gflow_cli-0.6.0a2/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_FINAL_ARCH.md +34 -0
  9. gflow_cli-0.6.0a2/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_FINAL_SEC_UX.md +47 -0
  10. gflow_cli-0.6.0a2/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_FINAL_SEC_UX_VERIFIED.md +30 -0
  11. gflow_cli-0.6.0a2/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_REVIEW_PLAN_SECURITY.md +57 -0
  12. gflow_cli-0.6.0a2/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/COUNCIL_REVIEW_SPEC_SECURITY.md +37 -0
  13. gflow_cli-0.6.0a2/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/PLAN.md +69 -0
  14. gflow_cli-0.6.0a2/docs/superpowers/plans/2026-05-15-auth-login-real-chrome/orchestration.md +20 -0
  15. gflow_cli-0.6.0a2/docs/superpowers/specs/2026-05-15-auth-login-real-chrome-design.md +45 -0
  16. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/pyproject.toml +1 -1
  17. gflow_cli-0.6.0a2/scripts/verify_chrome_auth_viability.py +209 -0
  18. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/__init__.py +1 -1
  19. gflow_cli-0.6.0a1/src/gflow_cli/auth.py → gflow_cli-0.6.0a2/src/gflow_cli/auth/__init__.py +16 -34
  20. gflow_cli-0.6.0a2/src/gflow_cli/auth/base.py +30 -0
  21. gflow_cli-0.6.0a2/src/gflow_cli/auth/factory.py +52 -0
  22. gflow_cli-0.6.0a2/src/gflow_cli/auth/internal_chromium.py +96 -0
  23. gflow_cli-0.6.0a2/src/gflow_cli/auth/real_chrome.py +172 -0
  24. gflow_cli-0.6.0a2/src/gflow_cli/auth/strategies.py +10 -0
  25. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/browser_manager.py +9 -0
  26. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/cli.py +40 -2
  27. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/errors.py +28 -0
  28. gflow_cli-0.6.0a2/tests/auth/strategies/test_factory.py +60 -0
  29. gflow_cli-0.6.0a2/tests/auth/strategies/test_strategies.py +243 -0
  30. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/cli/test_error_handling.py +59 -0
  31. gflow_cli-0.6.0a2/tests/features/auth_login.feature +31 -0
  32. gflow_cli-0.6.0a2/tests/features/test_auth_login_steps.py +127 -0
  33. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/features/test_auth_steps.py +3 -1
  34. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/uv.lock +1 -1
  35. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/.claude/README.md +0 -0
  36. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/.claude/commands/release.md +0 -0
  37. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/.env.template +0 -0
  38. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/.gitattributes +0 -0
  39. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/.github/workflows/ci.yml +0 -0
  40. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/.github/workflows/release.yml +0 -0
  41. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/.planning/todos/pending/2026-05-11-add-project-logo-and-docs-site-promotion-plan.md +0 -0
  42. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/CLAUDE.md +0 -0
  43. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/CONFIGURATION.md +0 -0
  44. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/CONTRIBUTING.md +0 -0
  45. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/DISCLAIMER.md +0 -0
  46. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/LICENSE +0 -0
  47. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/README.md +0 -0
  48. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/RELEASE.md +0 -0
  49. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/CONFIGURATION.md +0 -0
  50. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/INDEX.md +0 -0
  51. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/SECURITY.md +0 -0
  52. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/USAGE.md +0 -0
  53. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/USER_GUIDE.md +0 -0
  54. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/assets/example-run.gif +0 -0
  55. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-09-image-mvp-orchestration.md +0 -0
  56. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-09-image-mvp.md +0 -0
  57. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-09-video-mvp-orchestration.md +0 -0
  58. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-09-video-mvp.md +0 -0
  59. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-10-phase-4-hardening-orchestration.md +0 -0
  60. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-10-phase-4-hardening.md +0 -0
  61. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/2026-05-14-shell-multi-prompt-orchestration.md +0 -0
  62. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_CODE.md +0 -0
  63. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_GEMINI.md +0 -0
  64. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/COUNCIL_REVIEW_SECURITY.md +0 -0
  65. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_PYTHON.md +0 -0
  66. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/IMPLEMENTATION_REVIEW_SECURITY.md +0 -0
  67. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN.md +0 -0
  68. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_CODE.md +0 -0
  69. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_FOLLOWUP.md +0 -0
  70. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_PLANNER.md +0 -0
  71. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY.md +0 -0
  72. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/plans/2026-05-14-shell-multi-prompt/PLAN_REVIEW_SECURITY_FOLLOWUP.md +0 -0
  73. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/specs/2026-05-10-phase-4-hardening-design.md +0 -0
  74. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/specs/2026-05-14-shell-multi-prompt-design.md +0 -0
  75. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/docs/superpowers/verifications/2026-05-11-phase-4-stage-g.md +0 -0
  76. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/examples/README.md +0 -0
  77. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/examples/batch_from_config.py +0 -0
  78. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/examples/multi_prompt_t2i.py +0 -0
  79. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/examples/sample_config.json +0 -0
  80. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/examples/sample_prompts.txt +0 -0
  81. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/examples/single_image_t2i.py +0 -0
  82. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/samples/README.md +0 -0
  83. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/samples/captured/01_upload_image.json +0 -0
  84. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/samples/captured/02_batchAsyncGenerateVideoText.json +0 -0
  85. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/samples/captured/03_batchCheckAsyncVideoGenerationStatus.json +0 -0
  86. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/samples/captured/04_archive_workflow.json +0 -0
  87. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/samples/captured/05_createProject.json +0 -0
  88. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/samples/captured/06_batchGenerateImages.json +0 -0
  89. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/samples/captured/07_batchGenerateImages_seeded.json +0 -0
  90. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/scripts/diag_capture_flow_traffic.py +0 -0
  91. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/scripts/diag_recaptcha_mint.py +0 -0
  92. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/scripts/record_demo.ps1 +0 -0
  93. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/scripts/smoke_e2e.py +0 -0
  94. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/scripts/smoke_image.py +0 -0
  95. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/scripts/smoke_real_chrome_image.py +0 -0
  96. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/scripts/smoke_worker_style.py +0 -0
  97. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/skills/README.md +0 -0
  98. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/skills/gflow-cli/SKILL.md +0 -0
  99. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/__main__.py +0 -0
  100. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/_cli_helpers.py +0 -0
  101. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/api/__init__.py +0 -0
  102. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/api/_retry.py +0 -0
  103. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/api/client.py +0 -0
  104. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/api/dto.py +0 -0
  105. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/api/image.py +0 -0
  106. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/api/recaptcha.py +0 -0
  107. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/api/routes.py +0 -0
  108. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/api/transports/__init__.py +0 -0
  109. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/api/transports/_common.py +0 -0
  110. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/api/transports/_fingerprint.py +0 -0
  111. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/api/transports/base.py +0 -0
  112. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/api/transports/experimental/__init__.py +0 -0
  113. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/api/transports/experimental/bearer.py +0 -0
  114. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/api/transports/experimental/evaluate_fetch.py +0 -0
  115. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/api/transports/experimental/sapisidhash.py +0 -0
  116. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/api/transports/ui_automation.py +0 -0
  117. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/api/video.py +0 -0
  118. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/cli_image.py +0 -0
  119. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/cli_run.py +0 -0
  120. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/cli_video.py +0 -0
  121. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/config.py +0 -0
  122. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/image_batch.py +0 -0
  123. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/manifest.py +0 -0
  124. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/observability.py +0 -0
  125. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/paths.py +0 -0
  126. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/src/gflow_cli/profile_store.py +0 -0
  127. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tasks/lessons.md +0 -0
  128. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/__init__.py +0 -0
  129. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/__init__.py +0 -0
  130. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/test_client.py +0 -0
  131. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/test_client_generate_video.py +0 -0
  132. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/test_client_image.py +0 -0
  133. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/test_concurrency.py +0 -0
  134. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/test_dto.py +0 -0
  135. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/test_image.py +0 -0
  136. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/test_image_dto.py +0 -0
  137. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/test_recaptcha.py +0 -0
  138. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/test_retry.py +0 -0
  139. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/test_routes.py +0 -0
  140. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/test_video.py +0 -0
  141. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/transports/__init__.py +0 -0
  142. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/transports/test_base.py +0 -0
  143. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/transports/test_bearer.py +0 -0
  144. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/transports/test_common.py +0 -0
  145. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/transports/test_evaluate_fetch.py +0 -0
  146. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/transports/test_factory.py +0 -0
  147. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/transports/test_fingerprint.py +0 -0
  148. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/transports/test_sapisidhash.py +0 -0
  149. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/api/transports/test_ui_automation.py +0 -0
  150. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/cli/__init__.py +0 -0
  151. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/cli/test_cli_image.py +0 -0
  152. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/cli/test_cli_run.py +0 -0
  153. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/cli/test_helpers.py +0 -0
  154. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/cli/test_t2i_multi_prompt.py +0 -0
  155. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/conftest.py +0 -0
  156. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/e2e/__init__.py +0 -0
  157. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/e2e/test_transports_e2e.py +0 -0
  158. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/features/__init__.py +0 -0
  159. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/features/auth.feature +0 -0
  160. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/features/conftest.py +0 -0
  161. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/features/image.feature +0 -0
  162. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/features/test_image_steps.py +0 -0
  163. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/features/test_step_collision_guard.py +0 -0
  164. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/features/test_video_steps.py +0 -0
  165. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/features/video.feature +0 -0
  166. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/smoke/__init__.py +0 -0
  167. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/smoke/test_real_flow.py +0 -0
  168. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/test_auth.py +0 -0
  169. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/test_browser_manager.py +0 -0
  170. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/test_cli_video.py +0 -0
  171. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/test_config.py +0 -0
  172. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/test_errors.py +0 -0
  173. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/test_manifest.py +0 -0
  174. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/test_observability.py +0 -0
  175. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/test_paths.py +0 -0
  176. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/test_profile_store.py +0 -0
  177. {gflow_cli-0.6.0a1 → gflow_cli-0.6.0a2}/tests/test_smoke.py +0 -0
@@ -15,6 +15,7 @@ env/
15
15
 
16
16
  # Test / coverage
17
17
  .pytest_cache/
18
+ pytest-of-*/
18
19
  .coverage
19
20
  .coverage.*
20
21
  htmlcov/
@@ -7,7 +7,62 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- ## [0.6.0a1] — 2026-05-14
10
+ ## [0.6.0a2] — 2026-05-16
11
+
12
+ > **Real Chrome auth strategy — G12 block resolved.** This release restores
13
+ > `gflow auth login` reliability by routing logins through the system's real
14
+ > Google Chrome instead of Playwright's bundled Chromium. A carefully ordered
15
+ > stealth configuration prevents Google's bot-detection from blocking the sign-in
16
+ > flow.
17
+
18
+ ### Added
19
+
20
+ - **`--browser [auto|chrome|internal]` flag** on `gflow auth login` — selects
21
+ the browser strategy. `chrome` uses real system Chrome (stealth). `internal`
22
+ falls back to bundled Chromium. `auto` (default) probes for real Chrome and
23
+ falls back gracefully.
24
+ - **`GFLOW_CLI_AUTH_BROWSER` env var** — overrides the browser strategy without
25
+ a CLI flag.
26
+ - **`RealChromeStrategy`** (`src/gflow_cli/auth/real_chrome.py`) — stealth
27
+ persistent context via `channel="chrome"` with
28
+ `--disable-blink-features=AutomationControlled` and a JS init-script to mask
29
+ `navigator.webdriver`.
30
+ - **`InternalChromiumStrategy`** — extracted from the previous `auth.py` monolith
31
+ as an explicit fallback strategy.
32
+ - **`AuthStrategyFactory`** — routes `auto`/`chrome`/`internal` to the
33
+ appropriate strategy based on system state.
34
+ - **`is_chrome_available()`** in `browser_manager.py` — non-raising probe for
35
+ system Chrome presence.
36
+ - **4 new BDD scenarios** in `tests/features/auth_login.feature` covering all
37
+ `--browser` modes.
38
+
39
+ ### Fixed
40
+
41
+ - **G12 bot-detection block** — Google's "browser not secure" rejection (`/v3/signin/rejected`)
42
+ is bypassed by the stealth Chrome launch configuration. Root cause: without
43
+ `--disable-blink-features=AutomationControlled`, Blink's C++ engine sets
44
+ `navigator.webdriver = true` as a non-configurable native property before any
45
+ JS init script can run, making `Object.defineProperty` overrides silently fail.
46
+ - **`add_init_script` timing** — registration now occurs before any page is
47
+ accessed, ensuring the stealth script fires on every navigation including the
48
+ first `goto()`.
49
+ - **Privacy Guard** — `RealChromeStrategy` validates that `profile_dir` is inside
50
+ `GFLOW_CLI_HOME` and raises `SecurityError` if it is not, preventing accidental
51
+ use of the user's primary system Chrome profile.
52
+ - **`ConfigurationError` on missing Chrome** — clear "Chrome binary not found"
53
+ message with install guidance when `--browser chrome` is requested but Chrome
54
+ is not on the system.
55
+ - **Two pyright `TypedDict` errors** in cookie access (`c["name"]` → `c.get("name")`).
56
+
57
+ ### Changed
58
+
59
+ - `src/gflow_cli/auth.py` promoted to `src/gflow_cli/auth/` package with
60
+ `__init__.py`, `base.py`, `factory.py`, `internal_chromium.py`,
61
+ `real_chrome.py`, `strategies.py`.
62
+ - `gflow auth login` now prints the launch strategy announcement before opening
63
+ any browser window.
64
+
65
+
11
66
 
12
67
  > **Shell-friendly multi-prompt `t2i` + performance hardening.** This release
13
68
  > promotes `gflow image t2i` to a variadic command that can consume multiple
@@ -133,6 +133,35 @@ _(none yet)_
133
133
 
134
134
  ## Resolved
135
135
 
136
+ ### G12 "browser not secure" block — Google rejects automated sign-in
137
+
138
+ - **Status:** Resolved · **Severity:** Critical (blocked `gflow auth login`) · **Fixed in:** v0.6.0a2
139
+
140
+ Google's sign-in flow (`accounts.google.com/v3/signin/rejected`) detected Playwright's bundled Chromium as an automated browser and refused the login with no user-facing error.
141
+
142
+ **Root cause (timing race):** Without `--disable-blink-features=AutomationControlled`,
143
+ Blink's C++ engine sets `navigator.webdriver = true` as a non-configurable, non-writable
144
+ native property at Chrome startup — before any JavaScript (including `add_init_script`)
145
+ can run. The `Object.defineProperty` override silently fails. With the flag, the property
146
+ is never set; the JS override then works as belt-and-suspenders.
147
+
148
+ **Resolution:** `v0.6.0a2` adds `RealChromeStrategy` — a new auth strategy that launches
149
+ the system's real Google Chrome via Playwright's `channel="chrome"` with stealth flags.
150
+
151
+ ```bash
152
+ # Bypass G12 block explicitly:
153
+ gflow auth login --browser chrome
154
+
155
+ # Or rely on auto-detection (default behaviour; picks real Chrome if installed):
156
+ gflow auth login
157
+ ```
158
+
159
+ A cosmetic "You are using an unsupported command-line flag" notice may appear briefly in
160
+ the Chrome window — this is harmless and can be dismissed. It is the accepted trade-off
161
+ for bypassing G12.
162
+
163
+ ---
164
+
136
165
  ### v0.1 — provider methods are stubs
137
166
 
138
167
  - **Status:** Resolved · **Severity:** Critical (blocked usage) · **Fixed in:** v0.2.0a1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gflow-cli
3
- Version: 0.6.0a1
3
+ Version: 0.6.0a2
4
4
  Summary: Unofficial CLI for Google Flow — drive Veo image-to-video generations from the terminal.
5
5
  Project-URL: Homepage, https://github.com/ffroliva/gflow-cli
6
6
  Project-URL: Issues, https://github.com/ffroliva/gflow-cli/issues
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **Status:** Living document. Updated as phases complete.
4
4
  > **Owner:** [@ffroliva](https://github.com/ffroliva)
5
- > **Last revised:** 2026-05-11 (Phase 4 Hardening shipped, v0.4.0a2)
5
+ > **Last revised:** 2026-05-15 (Phase 6 / v0.6.0a2 — Real Chrome auth)
6
6
 
7
7
  This plan turns the v0.1 scaffold into a production-grade CLI for Google AI Ultra/Pro subscribers who want to spend their Flow credits via batch automation. The plan is opinionated, treating this repo as a portfolio-grade benchmark.
8
8
 
@@ -76,7 +76,12 @@ Current package layout (post-Phase 4):
76
76
  src/gflow_cli/
77
77
  ├── __init__.py
78
78
  ├── __main__.py
79
- ├── auth.py login + status (Playwright headed for login)
79
+ ├── auth/ v0.6.0a2: strategy pattern (real Chrome + internal Chromium)
80
+ │ ├── __init__.py ← login(), AuthStatus, get_status(), list_profiles()
81
+ │ ├── base.py ← AuthStrategy Protocol
82
+ │ ├── factory.py ← AuthStrategyFactory (auto/chrome/internal routing)
83
+ │ ├── internal_chromium.py ← bundled Chromium (legacy fallback)
84
+ │ └── real_chrome.py ← system Chrome with G12 stealth flags
80
85
  ├── cli.py ← Click app, top-level + auth subgroup
81
86
  ├── cli_image.py ← gflow image upload/t2i/i2i (Click subgroup)
82
87
  ├── cli_video.py ← gflow video t2v/i2v/batch (Click subgroup)
@@ -323,17 +328,28 @@ Page creation averaged **44.7–48.1 ms per page** across N=2/4/8/16 inside one
323
328
 
324
329
  ### Phase 5 — Public alpha soak + first non-alpha release
325
330
 
326
- `v0.2.0a1` through `v0.4.0a2` are already on PyPI under Trusted Publishing.
331
+ `v0.2.0a1` through `v0.6.0a1` are already on PyPI under Trusted Publishing.
327
332
  Phase 5 is the soak window before dropping the `aN` suffix:
328
333
 
329
- - Let `v0.4.0a2` soak on PyPI for at least 1 week with external installs
330
- - Verify `uvx --from "gflow-cli==0.4.0a2" gflow --help` works on a fresh machine on all three OSes (Windows / macOS / Linux)
334
+ - Let `v0.6.0a1` soak on PyPI for at least 1 week with external installs
335
+ - Verify `uvx --from "gflow-cli==0.6.0a1" gflow --help` works on a fresh machine on all three OSes (Windows / macOS / Linux)
331
336
  - Triage any issues filed by external users (`gh issue list`)
332
- - Tag the first non-alpha (`v0.4.0`) once the surface is stable enough for external automation
337
+ - Tag the first non-alpha (`v0.6.0`) once the surface is stable enough for external automation
333
338
  - Optional follow-up: scaffold `OfficialVeoProvider` against [`googleapis/python-genai`](https://github.com/googleapis/python-genai) behind `GFLOW_CLI_PROVIDER=official`
334
339
 
335
340
  ---
336
341
 
342
+ ### Technical Debt & Refactoring — BACKLOG
343
+
344
+ Identified during v0.6.0a1 Council Review. To be addressed before or during Phase 6.
345
+
346
+ - **Unify Output Resolution**: `cli_run.py` uses `out/<UTC>` while `cli_image.py` uses `images/<YYYY-MM-DD>`. Align both to the date-partitioned daily strategy or a single shared helper.
347
+ - **Deduplicate JSON Validation**: `cli_run.py` duplicates model/aspect validation logic. Consolidate into `image_batch.py` helpers.
348
+ - **Generic Batch Orchestrator**: Refactor `run_image_batch` to accept a worker callback. This will allow the same sequential/fail-fast orchestration to support `video` batches in the future.
349
+ - **Playwright Thread Safety**: Investigate why `unittest.mock.patch` plus multi-threaded `asyncio` hangs in `tests/test_browser_manager.py`. The test is currently skipped.
350
+
351
+ ---
352
+
337
353
  ### Phase 6 — Operations history & cost tracking — BACKLOG
338
354
 
339
355
  Foundation laid by Phase 4's structured `error_raised` events + Problem Details. Phase 6 adds a local persistence layer so users can answer "what did I generate last week and what did it cost?".
@@ -57,6 +57,43 @@ The hexagonal target above is the steady state. The **current** package — and
57
57
  - Restructure existing modules beyond minimal dedup (shared CLI helpers were promoted to `gflow_cli._cli_helpers` at the package top level — kept flat to avoid a `cli.py` file / `cli/` package collision).
58
58
  - Introduce dependency-injection containers, command/query buses, or any DDD/CQRS scaffolding (deferred per [PLAN ADR #2](../PLAN.md#5-decision-log-adrs-in-miniature)).
59
59
 
60
+ **v0.6.0a2 module additions — auth strategy package:**
61
+
62
+ `auth.py` was promoted to a sub-package `gflow_cli.auth/` with the strategy pattern to support multiple browser backends for the `gflow auth login` command:
63
+
64
+ ```text
65
+ src/gflow_cli/auth/
66
+ ├── __init__.py # public: login(), AuthStatus, get_status(), list_profiles()
67
+ ├── base.py # AuthStrategy Protocol — the shared contract
68
+ ├── factory.py # AuthStrategyFactory — routes auto/chrome/internal modes
69
+ ├── internal_chromium.py # InternalChromiumStrategy — Playwright bundled Chromium (legacy)
70
+ ├── real_chrome.py # RealChromeStrategy — system Google Chrome with stealth flags
71
+ └── strategies.py # (internal) shared Playwright helpers
72
+ ```
73
+
74
+ **Why:** Google's bot-detection ("G12 block") rejects Playwright's bundled Chromium during `gflow auth login`. Launching the user's installed Google Chrome with `--disable-blink-features=AutomationControlled` plus a JS `add_init_script` that overrides `navigator.webdriver` bypasses detection. Two strategies are needed because the setup (persistent-context flags, Chrome binary path, stealth init) differs fundamentally between them.
75
+
76
+ **AuthStrategy Protocol** (`base.py`):
77
+ ```python
78
+ class AuthStrategy(Protocol):
79
+ name: str
80
+ async def login(self, profile_dir: Path, headless: bool) -> None: ...
81
+ ```
82
+
83
+ **AuthStrategyFactory** (`factory.py`):
84
+ - `mode="auto"` — probes `is_chrome_available()` → `RealChromeStrategy` if found, else `InternalChromiumStrategy` with a warning.
85
+ - `mode="chrome"` — explicit `RealChromeStrategy`; raises `ConfigurationError` if Chrome binary missing.
86
+ - `mode="internal"` — explicit `InternalChromiumStrategy`.
87
+
88
+ **RealChromeStrategy stealth design** (`real_chrome.py`):
89
+ - Uses a **Passive Capture** pattern: launches system Chrome via `subprocess.Popen` without any automation flags or remote-debugging ports.
90
+ - Provides a 100% clean browser process that Google's G12 block cannot detect.
91
+ - The CLI blocks on `proc.wait()`, prompting the user to complete the sign-in and **close the browser completely**.
92
+ - Post-close: performs a fast, headless `launch_persistent_context` probe to verify the `SAPISID` cookie was successfully captured.
93
+ - Privacy guard: raises `SecurityError` if the resolved `profile_dir` is outside `GFLOW_CLI_HOME` — protects the user's primary system Chrome profile from being used as a session store.
94
+
95
+ **CLI surface:** `gflow auth login [--browser auto|chrome|internal]` (env: `GFLOW_CLI_AUTH_BROWSER`).
96
+
60
97
  When the project converges on the hexagonal target above, modules graduate to layers: e.g., today's `gflow_cli.api` becomes `gflow_cli.infrastructure.flow_api`, `gflow_cli.cli` becomes `gflow_cli.interfaces.cli`, and so on. The modular-monolith shape is the staging area, not the destination.
61
98
 
62
99
  ## Folder layout
@@ -64,7 +101,7 @@ When the project converges on the hexagonal target above, modules graduate to la
64
101
  > **Note: this document describes the TARGET architecture, not the current
65
102
  > package layout.** The current shape (per [PLAN.md § 2](../PLAN.md#2-architecture-steady-state)
66
103
  > and [ADR #2](../PLAN.md#5-decision-log-adrs-in-miniature)) is the simpler
67
- > `src/gflow_cli/{api/, cli.py, cli_image.py, cli_video.py, auth.py,
104
+ > `src/gflow_cli/{api/, auth/, cli.py, cli_image.py, cli_video.py,
68
105
  > config.py, paths.py, profile_store.py}`. The DDD layout below was deferred
69
106
  > indefinitely; converge toward it incrementally if/when a second `Provider`
70
107
  > or a `gflow serve` HTTP front-end justifies the split.
@@ -127,14 +127,38 @@ Use `gflow auth login --profile <name>` to add or refresh a profile.
127
127
 
128
128
  ### `gflow auth login`
129
129
 
130
- Opens a headed Chromium, navigates to `https://labs.google/fx/tools/flow?hl=en`, and waits for you to sign in. The browser window must be closed within **10 minutes total** (the underlying `wait_for_event("close", timeout=600_000)`); after that the command times out. When the window is closed, the captured session is persisted to disk.
130
+ Opens a headed browser, navigates to `https://labs.google/fx/tools/flow?hl=en`, and waits
131
+ for you to sign in. The CLI automatically detects success and persists the session to disk.
131
132
 
132
133
  ```bash
133
- gflow auth login # default profile
134
- gflow auth login --profile work # named profile (creates if missing)
134
+ gflow auth login # default profile, auto browser
135
+ gflow auth login --profile work # named profile (creates if missing)
136
+ gflow auth login --browser chrome # force real Chrome (bypasses G12 block)
135
137
  ```
136
138
 
137
- Re-running this command refreshes an expired session: it reuses the existing profile dir, so you typically just have to click "Continue as <you>" on the Google account chooser.
139
+ Re-running this command refreshes an expired session: it reuses the existing profile dir,
140
+ so you typically just have to click "Continue as <you>" on the Google account chooser.
141
+
142
+ #### `--browser [auto|chrome|internal]`
143
+
144
+ | Value | Browser used | When to use |
145
+ |---|---|---|
146
+ | `auto` (default) | Real Chrome if installed; falls back to internal | First choice for most users |
147
+ | `chrome` | System Google Chrome (**Passive Capture**) | Required to bypass "G12" blocks |
148
+ | `internal` | Playwright's bundled Chromium | Fallback when Chrome isn't installed |
149
+
150
+ Override with the env var: `GFLOW_CLI_AUTH_BROWSER=chrome gflow auth login`
151
+
152
+ **Why `chrome` bypasses bot detection:** Playwright's default automation mode exposes
153
+ `navigator.webdriver = true` as a non-configurable native property. Google detects this
154
+ and redirects to `/v3/signin/rejected` (the "G12 block"). The `chrome` strategy
155
+ implements **Passive Capture**: it launches your real system Chrome as a 100% standard
156
+ process without any automation flags or debugging ports. You log in manually, close
157
+ the window, and `gflow` extracts the verified session from the profile.
158
+
159
+ **Privacy guard:** The `chrome` strategy strictly refuses to use any profile directory
160
+ outside `GFLOW_CLI_HOME`. This protects your primary system Chrome profile from
161
+ accidental interference or data corruption.
138
162
 
139
163
  ### `gflow auth status`
140
164
 
@@ -0,0 +1,34 @@
1
+ # Architectural Review: Shell Multi-Prompt
2
+
3
+ **Target:** `2026-05-14-shell-multi-prompt`
4
+ **Reviewer:** Senior Architect
5
+ **Date:** 2026-05-14
6
+
7
+ ## Summary of Findings
8
+ The architectural review of the Shell Multi-Prompt feature reveals a successful extraction of shared logic for the image domain, but also highlights minor technical debt and architectural divergence from the video domain.
9
+
10
+ ### Key Insights:
11
+
12
+ 1. **DRYness and Coupling**:
13
+ - `image_batch.py` effectively DRYs up the execution and rendering logic for image batches.
14
+ - **Leakage**: The module imports `rich` for summary rendering. While acceptable for a CLI-targeted helper, it strictly couples the batch logic to terminal-based reporting.
15
+ - **Duplication**: `cli_run.py` duplicates validation of model/aspect ratios instead of using helpers.
16
+ - **Inconsistency**: `resolve_t2i_batch_output_dir` (image) uses `images/<YYYY-MM-DD>`, while `_resolve_output_dir` (run) uses `out/<UTC-timestamp>`.
17
+
18
+ 2. **Extension Safety**:
19
+ - `BatchPromptItem` is tightly coupled to image-specific fields (`count`, `aspect_ratio`). Adding video-batch support will require either a more generic `BatchItem` or a parallel `VideoBatchItem`.
20
+ - The image batch runner is sequential (supporting fail-fast), whereas the existing video batcher is concurrent (using `asyncio.gather` and the Page pool). Unifying these will require reconciling these different execution models.
21
+
22
+ 3. **Constant Alignment**:
23
+ - `image_batch.py` acts as the CLI source of truth.
24
+ - `ALLOWED_MODELS` is a restrictive subset of `api/image.py`'s aliases. This is consistent across the CLI but limits users to "friendly" aliases (e.g., `nano2` vs `narwhal`).
25
+
26
+ ## Verdict
27
+ **PROCEED**
28
+
29
+ The implementation is robust, well-tested, and a significant improvement for UX. The identified technical debt is manageable and can be addressed in future phases (e.g., during video-batch unification).
30
+
31
+ ## Recommended Refactors
32
+ - Unify output directory resolution logic.
33
+ - Move duplicated validation in `cli_run.py` into `image_batch.py`.
34
+ - Parameterize `run_image_batch` to accept a worker function, facilitating future video support.
@@ -0,0 +1,47 @@
1
+ # Security & UX Review: Shell Multi-Prompt
2
+
3
+ **Date:** 2026-05-14
4
+ **Reviewer:** Senior Code Reviewer
5
+ **Status:** Completed
6
+ **Verdict:** **PATCH** (Path leaks in terminal output)
7
+
8
+ ## 1. Memory Safety
9
+ **Focus:** Bounded `sys.stdin.read` logic in `cli_image.py`.
10
+
11
+ - **Finding:** **PASS**
12
+ - **Analysis:** The implementation in `src/gflow_cli/cli_image.py` correctly uses `sys.stdin.read(MAX_PROMPT_FILE_BYTES + 1)` where `MAX_PROMPT_FILE_BYTES` is 512 KiB. This "slurp" is safely bounded, preventing OOM crashes even if a massive stream is piped to the CLI. The code properly raises `click.UsageError` if the input exceeds the limit.
13
+ - **Verification:** Verified in `src/gflow_cli/cli_image.py` lines 282-293.
14
+
15
+ ## 2. Resource Integrity
16
+ **Focus:** `sqlite3` connections in `sapisidhash.py` and related tests.
17
+
18
+ - **Finding:** **PASS**
19
+ - **Analysis:** Both the implementation in `src/gflow_cli/api/transports/experimental/sapisidhash.py` and the corresponding unit tests in `tests/api/transports/test_sapisidhash.py` use robust `try...finally` blocks to ensure that `sqlite3` connections are explicitly closed (`conn.close()`). No resource leaks were identified.
20
+ - **Verification:**
21
+ - `sapisidhash.py`: `read_sapisid_from_profile` uses `try...finally`.
22
+ - `test_sapisidhash.py`: `_build_cookie_db` and test cases use `try...finally`.
23
+
24
+ ## 3. Path Safety
25
+ **Focus:** Prevention of absolute path leaks in terminal output.
26
+
27
+ - **Finding:** **PATCH REQUIRED**
28
+ - **Analysis:** Several locations in the CLI output absolute paths, which may leak sensitive information such as the local username (e.g., `C:\Users\<username>\...`).
29
+ - `cli_image.py`: The `output_dir` and generated image paths in tables use `str(path)`.
30
+ - `image_batch.py`: The `render_image_batch_summary` table joins absolute paths into the "detail" column.
31
+ - `cli_video.py`: Similar leaks in `t2v` and `i2v` success messages.
32
+ - **Recommendation:** Implement a `safe_path_text` helper that replaces the user's home directory with `~` and/or shows paths relative to the Current Working Directory (CWD) where appropriate.
33
+
34
+ ## 4. CLI UX
35
+ **Focus:** Help strings for positional prompts vs flags.
36
+
37
+ - **Finding:** **PATCH SUGGESTED**
38
+ - **Analysis:**
39
+ - The `t2i` help string says "Generate 1-4 images from a text prompt", which is slightly misleading for the new multi-prompt mode. It should be updated to "one or more text prompts".
40
+ - The mutual exclusivity of positional `PROMPTS`, `--prompts-file`, and `--stdin` is well-enforced in code and illustrated by examples, but the `Usage` line `[PROMPTS]...` might still be slightly ambiguous to a new user. However, this is standard `click` behavior and is acceptable.
41
+ - **Recommendation:** Update the short help and main help text to explicitly mention "one or more text prompts".
42
+
43
+ ## Final Verdict
44
+ The feature is functionally solid and secure regarding memory and database resources. However, it fails the "no absolute path leaks" requirement. A patch is required to sanitize path rendering in terminal output before the feature can be considered production-ready.
45
+
46
+ ---
47
+ **Reviewer Signature:** Senior Code Reviewer
@@ -0,0 +1,30 @@
1
+ # Final Security & UX Review
2
+
3
+ **Verdict: PROCEED**
4
+
5
+ The 'Auth Login via Real Chrome' feature has been thoroughly reviewed against the implementation plan and codebase.
6
+
7
+ ## 1. G12 Bypass Validation
8
+ **Status: Verified**
9
+ The Passive Capture strategy is correctly implemented. `RealChromeStrategy.login()` utilizes `subprocess.Popen` to launch the system's Google Chrome executable. It explicitly avoids injecting `--remote-debugging-port` or `--enable-automation` flags, ensuring the browser runs as a standard, manual user session. Because Playwright is not attached during the login phase, Google's G12 bot detection (which looks for `navigator.webdriver` and other CDP signatures) is completely bypassed. Playwright is only invoked locally and headlessly *after* the browser is closed to verify the persisted cookies.
10
+
11
+ ## 2. Privacy Guard Audit
12
+ **Status: Verified**
13
+ The implementation includes a robust boundary check in `src/gflow_cli/auth/real_chrome.py`. Before launching Chrome, the code enforces that the `profile_dir` is confined to the `GFLOW_CLI_HOME` boundary using `Path.relative_to(settings.home)`. Any attempt to resolve a path outside this directory (e.g., targeting the user's primary system Chrome profile) will raise a `SecurityError`. The default profile location resolution mechanism in `gflow_cli.paths` is also correctly scoped.
14
+
15
+ ## 3. User Experience Review
16
+ **Status: Verified**
17
+ The terminal UI during the passive authentication flow is exceptionally clear. The CLI prints a highly visible block that guides the user through the process:
18
+ 1. Open Chrome.
19
+ 2. Navigate to the Gemini URL.
20
+ 3. Complete the sign-in.
21
+ 4. Close the browser.
22
+
23
+ The specific instruction to "CLOSE THE BROWSER" is bolded and highlighted in yellow, which is critical for proceeding with the headless cookie verification. Additionally, if the user takes too long or fails to close the browser, an `AuthLoginTimeoutError` is raised with a clear remediation hint explaining how to increase the timeout limit.
24
+
25
+ ## 4. Quality Gates
26
+ **Status: Verified**
27
+ Test coverage for the newly encapsulated `src/gflow_cli/auth/` package stands at **85%**, comfortably exceeding the 80% minimum requirement. The tests adequately cover the core logic, including boundary violations (Privacy Guard), timeout handling, fallback mechanisms, and proper command-line argument construction for the Chrome subprocess.
28
+
29
+ ## Conclusion
30
+ The implementation is solid, secure, and user-friendly. The transition to the Passive Capture mechanism mitigates the existing bot-detection blockers while safeguarding user privacy. The system gracefully falls back to the internal Chromium strategy when necessary. The codebase is ready for integration/release.
@@ -0,0 +1,57 @@
1
+ # Council Review: Implementation Plan - Security & Quality
2
+
3
+ **Review of Plan:** `docs/superpowers/plans/2026-05-15-auth-login-real-chrome/PLAN.md`
4
+ **Orchestration:** `docs/superpowers/plans/2026-05-15-auth-login-real-chrome/orchestration.md`
5
+ **Reviewer:** Senior Code Reviewer (Agent)
6
+ **Date:** 2024-05-15 (Simulated)
7
+
8
+ ## 1. Test Coverage Analysis
9
+ **Status:** ⚠️ **Insufficient**
10
+
11
+ * **Focal Point:** Ensure 80%+ coverage for `src/gflow_cli/auth/`.
12
+ * **Findings:**
13
+ * The plan allocates tasks for Factory tests (T1.1) and BDD scenarios (T1.2).
14
+ * **GAP:** There are no explicit unit tests for `RealChromeStrategy` or `InternalChromiumStrategy` logic (e.g., error handling, path resolution, stealth patch application).
15
+ * BDD tests are excellent for integration but typically do not hit all edge cases in the strategy implementations required to reach 80% coverage.
16
+ * **Recommendation:** Add a task `T1.4: Strategy Unit Tests` to Phase 1. This should specifically target mocking Playwright browser contexts to verify strategy-specific behavior without opening real windows.
17
+
18
+ ## 2. Security Verification (Privacy Guard)
19
+ **Status:** ❌ **Not Explicitly Tested**
20
+
21
+ * **Focal Point:** Verification of the 'Privacy Guard' implementation (T2.2).
22
+ * **Findings:**
23
+ * The implementation of the Privacy Guard is correctly identified in T2.2 (preventing leakages outside `GFLOW_CLI_HOME`).
24
+ * **GAP:** The plan fails to define a test case in the RED phase (Phase 1) that verifies this guard.
25
+ * **Recommendation:** Update `T1.1` or add `T1.4` to include: "Verify `RealChromeStrategy` raises exception if a `user_data_dir` outside `GFLOW_CLI_HOME` is provided."
26
+
27
+ ## 3. Manual Verification (Smoke Testing)
28
+ **Status:** ❌ **Missing**
29
+
30
+ * **Focal Point:** Manual smoke-test recipe in release ceremony or documentation.
31
+ * **Findings:**
32
+ * **GAP:** The plan lacks a specific task for a manual smoke test. Given that "Real Chrome" interactions can be brittle due to local environment variations (Chrome version, OS-level security prompts), a manual verification step is essential.
33
+ * **Recommendation:** Add a task to **Phase 3** or **Phase 4**: `T4.3: Manual Smoke-Test Execution`. This should follow a "Recipe" (e.g., Run `gflow auth login --browser chrome`, perform real login, verify `SAPISID` is captured and persisted).
34
+
35
+ ## 4. UX (Optimistic Orchestration)
36
+ **Status:** 🟡 **Minor Edits Required**
37
+
38
+ * **Focal Point:** Correct ordering of T2.4 to prevent brittle behavior.
39
+ * **Findings:**
40
+ * T2.4 correctly identifies the polling targets (`SAPISID` cookie + `New project` UI element).
41
+ * The Risk Management section in `orchestration.md` correctly notes the need for a "settle-time".
42
+ * **GAP:** The plan description "1s polling for SAPISID cookie + New project UI element" does not explicitly define the terminal state condition.
43
+ * **Recommendation:** Clarify T2.4 implementation details: "The login is successful only when (Cookie is valid AND UI element is interactive). Wait for 500ms after detection to ensure session persistence before closing the browser."
44
+
45
+ ## 5. Summary of Plan Deviations
46
+ * The plan is structurally sound but leans too heavily on BDD for coverage.
47
+ * Security features (Privacy Guard) are treated as implementation details rather than verifiable requirements.
48
+
49
+ ## Recommendations
50
+ 1. **Add T1.4 (Phase 1):** Unit tests for Strategy logic and Security Guards.
51
+ 2. **Add T4.3 (Phase 4):** Manual smoke-test recipe and ceremony step.
52
+ 3. **Refine T2.4 (Phase 2):** Explicit "AND" condition and settle-time for polling.
53
+
54
+ ## Verdict
55
+ **Verdict:** **MAJOR-REVISION**
56
+
57
+ *Reasoning:* The current plan will likely fail the 80% coverage requirement and lacks the necessary testing rigor to guarantee the 'Privacy Guard' security feature works as intended before implementation begins. The absence of a manual smoke test recipe for a high-risk UI feature is a quality blocker for release.
@@ -0,0 +1,37 @@
1
+ # Security & UX Review: Auth Login via Real Chrome
2
+
3
+ **Review Date:** 2026-05-15
4
+ **Spec Version:** v0.6.0a2
5
+ **Verdict:** MINOR-EDITS
6
+
7
+ ## 1. Stealth Integrity (Ref: Section 3.1)
8
+ * **Finding:** The proposed flags (`--enable-automation` removal and `AutomationControlled`) are necessary but **insufficient** for bypassing modern Google (G12) bot detection. Google also monitors for `navigator.webdriver == true` and specific CDP-injected window properties.
9
+ * **Recommendation:**
10
+ * Explicitly require the override of `navigator.webdriver` to `undefined` in the `RealChromeStrategy`.
11
+ * Ensure the `ignore_default_args` parameter is used in Playwright to effectively strip the `--enable-automation` flag.
12
+ * **Citations:** Ref Section 3, Line 1 (Decision 1).
13
+
14
+ ## 2. Privacy & Data Isolation (Ref: Section 3.4 & 7)
15
+ * **Finding:** Using `channel="chrome"` with `launch_persistent_context` poses a risk if the `user_data_dir` defaults to or is accidentally pointed at the user's *actual* personal Chrome profile.
16
+ * **Risk:** This could cause profile locking or unintentional modification of the user's primary browser data.
17
+ * **Recommendation:**
18
+ * Add a hard requirement that `RealChromeStrategy` must ONLY use directories inside `GFLOW_CLI_HOME`.
19
+ * The implementation must include a safeguard that prevents using the system's default `User Data` path.
20
+ * **Citations:** Ref Section 3, Line 4 (Decision 4); Section 7.
21
+
22
+ ## 3. UX Review (Ref: Section 2 & 5)
23
+ * **Finding:** The terminology `bundled` in `--browser [auto|chrome|bundled]` might be confusing for non-technical users.
24
+ * **Recommendation:**
25
+ * Consider `internal` or `embedded` as more descriptive alternatives to `bundled`.
26
+ * Help text for `auto` (Section 5, AC-5) should clearly state the preference order and why a fallback occurred.
27
+ * **Citations:** Ref Section 2, CLI Flag; Section 5, AC-5.
28
+
29
+ ## 4. Success Detection Robustness (Ref: Section 4)
30
+ * **Finding:** Depending solely on the `SAPISID` cookie for "Auth Success" (Section 4) is fast but potentially brittle if the redirect hasn't finished or the session isn't fully flushed to disk.
31
+ * **Recommendation:**
32
+ * Implement a "Dual-Check" success condition: `SAPISID` cookie presence **AND** a UI-based confirmation (e.g., visibility of the Flow editor's main container).
33
+ * Ensure a short 500ms "settle time" after detection before closing the context to ensure the `storage_state.json` is correctly written.
34
+ * **Citations:** Ref Section 4, "Auth Success" heading.
35
+
36
+ ---
37
+ **Verdict:** **MINOR-EDITS**. The spec is technically sound but needs these hardening details to be production-ready for the v0.6.0 release.
@@ -0,0 +1,69 @@
1
+ # Implementation Plan: Auth Login via Real Chrome (`v0.6.0a2`)
2
+
3
+ > **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:subagent-driven-development` (recommended) or `superpowers:executing-plans` to implement this plan task-by-task. Steps use checkpoint protocol.
4
+
5
+ ## Phase 1: Test Scaffold (RED)
6
+ Goal: Define the contract and verify failure for all new surfaces.
7
+
8
+ - [ ] **T1.1: Auth Strategy Unit Tests** (`tests/auth/strategies/test_factory.py`)
9
+ - Verify `AuthStrategyFactory` returns `RealChromeStrategy` when available and requested.
10
+ - Verify fallback to `InternalChromiumStrategy` when Chrome is missing in `auto` mode.
11
+ - Verify `ConfigurationError` when `chrome` is requested but missing.
12
+ - [ ] **T1.2: BDD Scenarios** (`tests/features/auth_login.feature`)
13
+ - Add scenarios for `--browser chrome`, `--browser internal`, and `auto` selection.
14
+ - [ ] **T1.3: Strategy Protocol** (`src/gflow_cli/auth/base.py`)
15
+ - Define `AuthStrategy` protocol with `login(profile_dir: Path, headless: bool) -> None`.
16
+ - [ ] **T1.4: Concrete Strategy Tests** (`tests/auth/strategies/test_strategies.py`)
17
+ - Scaffold tests for `RealChromeStrategy` (stealth flags, success polling).
18
+ - Scaffold tests for `InternalChromiumStrategy`.
19
+ - [ ] **T1.5: Privacy Guard Tests** (`tests/auth/strategies/test_strategies.py`)
20
+ - Verify `RealChromeStrategy` raises a security exception if `user_data_dir` is outside the allowed `GFLOW_CLI_HOME` boundaries.
21
+
22
+ ## Phase 2: Implementation (GREEN)
23
+ Goal: Feature-complete implementation via atomic commits.
24
+
25
+ - [ ] **T2.1: Package Promotion** (`src/gflow_cli/auth.py` -> `src/gflow_cli/auth/__init__.py`)
26
+ - Convert the module to a package.
27
+ - Re-export legacy functions (`profile_dir`, `status`, `default_profile_root`) to ensure zero breakage for `cli.py`, `profile_store.py`, and `_cli_helpers.py`.
28
+ - [ ] **T2.2: InternalChromiumStrategy** (`src/gflow_cli/auth/internal_chromium.py`)
29
+ - Migrate legacy logic from `auth.py`.
30
+ - [ ] **T2.3: RealChromeStrategy** (`src/gflow_cli/auth/real_chrome.py`)
31
+ - Implement with **Passive Capture**: launch via `subprocess.Popen` without any debugging flags.
32
+ - Logic: Block on `proc.wait()`, prompting user to log in and CLOSE the browser.
33
+ - Implement Privacy Guard (validate `user_data_dir`).
34
+ - Add post-close verification: headless probe for `SAPISID` cookie.
35
+ - [ ] **T2.4: Factory & CLI Integration** (`src/gflow_cli/auth/factory.py` + `src/gflow_cli/cli.py`)
36
+ - Implement lazy registry and `get_strategy`.
37
+ - Update `gflow auth login` to parse `--browser` flag and `GFLOW_CLI_AUTH_BROWSER` env var, and dispatch via factory.
38
+ - [ ] **T2.5: Session Verification**
39
+ - Implement the headless verification probe in `RealChromeStrategy`.
40
+
41
+ ## Phase 3: Documentation & Knowledge Base (First-Class Citizen)
42
+ Goal: Ensure all documentation, architecture specs, and agent memory reflect the new strategy.
43
+
44
+ - [ ] **T3.1: Architecture Documentation** (`docs/ARCHITECTURE.md`)
45
+ - Document the new `AuthStrategy` pattern, detection logic, and the "Real Chrome" bypass mechanism.
46
+ - [ ] **T3.2: User Guidance** (`docs/AUTHENTICATION.md` & `docs/USAGE.md`)
47
+ - Rewrite Authentication flows to highlight the new Real Chrome default.
48
+ - Document the `--browser` flag and env var overrides.
49
+ - [ ] **T3.3: Changelog & Issues** (`CHANGELOG.md` & `KNOWN_ISSUES.md`)
50
+ - Add `v0.6.0a2` section highlighting the G12 fix.
51
+ - Move G12 from "open investigation" to "fixed" in Known Issues.
52
+ - [ ] **T3.4: MemPalace & Knowledge Graph Updates**
53
+ - Use `mempalace_kg_add` to record the architectural shift (Strategy pattern for auth).
54
+ - Use `mempalace_diary_write` to log the G12 bypass methodology (stealth + real chrome).
55
+
56
+ ## Phase 4: Council Review, Verification & Release
57
+ Goal: Final audit and release ceremony.
58
+
59
+ - [ ] **T4.1: Implementation Council Review**
60
+ - Invoke `code-reviewer` and `codebase_investigator` for a final implementation audit.
61
+ - [ ] **T4.2: Manual Smoke-Test Verification**
62
+ - Execute `uv run gflow auth login --browser chrome` on the operator's machine.
63
+ - Verify G12 bypass and successful session capture empirically.
64
+ - [ ] **T4.3: Release Ceremony**
65
+ - Bump version to `0.6.0a2` in `pyproject.toml`.
66
+ - Tag `v0.6.0a2` and push to trigger PyPI release.
67
+
68
+ ---
69
+ _End of Plan._
@@ -0,0 +1,20 @@
1
+ # Orchestration: Auth Login via Real Chrome
2
+
3
+ ## Strategy
4
+ This plan follows a **Test-Driven Refactor** strategy. We first promote the `auth.py` module to a package and define a strict Protocol to ensure both strategies are interchangeable. We use the existing `browser_manager` idioms for Chrome detection to keep the implementation consistent with the rest of the project.
5
+
6
+ ## Checkpoints
7
+ 1. **Checkpoint A (After T1.3)**: Protocol defined + failing tests.
8
+ 2. **Checkpoint B (After T2.4)**: Implementation complete + all tests green (GREEN phase).
9
+ 3. **Checkpoint C (After T3.2)**: Docs aligned with implementation.
10
+ 4. **Checkpoint D (After T4.2)**: Tagged and pushed.
11
+
12
+ ## Risk Management
13
+ - **Risk**: Real Chrome detection fails on a specific OS (macOS/Linux).
14
+ - **Mitigation**: Use the existing `browser_manager` probe which is already OS-aware.
15
+ - **Risk**: Optimistic polling is too fast and hits race conditions.
16
+ - **Mitigation**: Ensure a minimum settle-time after cookie detection before declaring success.
17
+
18
+ ## Resource Allocation
19
+ - **Primary Agent**: Implementation & TDD.
20
+ - **Council**: Spec review (DONE), Plan review (Next), Implementation review (Final).
@@ -0,0 +1,45 @@
1
+ # Spec: Auth Login via Real Chrome (`v0.6.0a2`)
2
+
3
+ **Goal:** Restore the ability to sign in to Google Flow by routing `gflow auth login` through the system's installed Google Chrome ("Real Chrome") to bypass the G12 security block.
4
+
5
+ ## 1. Problem Statement
6
+ Google currently identifies and blocks Playwright's bundled Chromium during the sign-in flow with the error: *"This browser or app may not be secure"*. While existing authenticated profiles still work for generation, fresh logins or re-authentications are impossible without brittle manual workarounds.
7
+
8
+ ## 2. Surfaces
9
+ - **Auth Strategies**: Refactor `src/gflow_cli/auth.py` (module) into a package `src/gflow_cli/auth/` containing:
10
+ - `base.py`: Defines the `AuthStrategy` `typing.Protocol`.
11
+ - `real_chrome.py`: Uses a **Passive Capture** strategy. It launches the system's real Chrome without any automation flags/ports, waits for the user to sign in and close the window, and then verifies the resulting session.
12
+ - `internal_chromium.py`: Legacy behavior (formerly "bundled"), kept as a fallback.
13
+
14
+ ## 3. Locked Decisions
15
+ 1. **Passive Capture is Mandatory**: Any active automation (CDP, WebDriver flags) during the login flow is currently detected by Google. Login MUST happen in a 100% standard process.
16
+ 2. **Strategy Pattern**: Auth logic must mirror the `UiAutomationTransport` factory pattern (lazy registry) for consistency.
17
+ 3. **Smart Defaults**: `auto` mode probes for Real Chrome; falls back to `internal` if missing.
18
+ 4. **No Breaking Changes**: Existing `profile_<name>` directories must remain compatible.
19
+ 5. **TDD Workflow**: Failing tests for all strategies and the factory must be written before implementation.
20
+ 6. **Privacy Guard**: `RealChromeStrategy` must validate that the provided `user_data_dir` is NOT the user's primary system Chrome profile.
21
+ 7. **Clean Exit**: The CLI will wait for the browser process to terminate before proceeding to verify the capture.
22
+
23
+ ## 4. Performance & UX
24
+ - **No More Stalls**: By removing automated click-throughs (which Google detects), we eliminate the hangs and timeouts seen in previous attempts.
25
+ - **Clear Instructions**: The CLI will provide a prominent "LOG IN THEN CLOSE BROWSER" instruction.
26
+ - **Session Verification**: After the window closes, the CLI will perform a fast, headless check for `SAPISID` to confirm success.
27
+
28
+ ## 5. Acceptance Criteria
29
+ 1. **AC-1**: `gflow auth login --browser chrome` opens a stealth-hardened Real Chrome window.
30
+ 2. **AC-2**: Google Login accepts credentials without a "browser not secure" block.
31
+ 3. **AC-3**: The CLI automatically detects login completion via cookie state + UI signals and exits cleanly (no manual window-close required).
32
+ 4. **AC-4**: `gflow auth login --browser internal` still functions as the legacy fallback.
33
+ 5. **AC-5**: If `auto` is used and Chrome is missing, the CLI warns the user and falls back to `internal`.
34
+ 6. **AC-6**: Unit tests verify the factory logic and strategy selection across all three OSes.
35
+
36
+ ## 6. Out of Scope
37
+ - Support for Chrome Beta, Canary, or Edge.
38
+ - Automatic password injection or MFA handling (remains operator-interactive).
39
+ - Refactoring `UiAutomationTransport` itself (only `auth` is targeted).
40
+
41
+ ## 7. Migration
42
+ Zero action required. The `storage_state.json` format is standard across Chromium-based browsers; sessions captured in Real Chrome will work seamlessly with the existing `UiAutomationTransport`.
43
+
44
+ ---
45
+ _Next Phase: Phase E — Implementation Plan._
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "gflow-cli"
3
- version = "0.6.0a1"
3
+ version = "0.6.0a2"
4
4
  description = "Unofficial CLI for Google Flow — drive Veo image-to-video generations from the terminal."
5
5
  readme = "README.md"
6
6
  license = { file = "LICENSE" }