console fill: never copy Google session cookies by default (device-bound); own profile in a Chrome started without automation switches

Google binds its session cookies to the device (Device Bound Session Credentials) and signs out
sessions whose cookies look stolen, which can sign the owner out of their real Chrome. The default is
now storebound's own profile per store; storebound starts Chrome itself (--user-data-dir,
--remote-debugging-port=0, no --enable-automation, navigator.webdriver false) and attaches over CDP.
--use-chrome-session google|apple is an explicit opt-in that warns. /signin/rejected is said plainly.
This commit is contained in:
CRTkafa 2026-10-12 07:46:04 +08:00
parent e0bef82b06
commit 0035931734
22 changed files with 456 additions and 156 deletions

View file

@ -1,6 +1,6 @@
---
name: console-autofill
description: AI-assisted autofill of App Store Connect and Google Play Console forms that have no API (the New App dialog, App Privacy, Play's Create app form, the Play IARC content rating questionnaire, Target audience and content plus the Ads declaration; the App Store age rating is shown as guidance because the API sets it) in a visible browser that reuses the owner's Chrome sign-in (or one they sign in to); storebound opens the form itself. Answers come only from storebound.config.ts; anything the config does not prove stays empty and highlighted. storebound moves through the pages itself (Next; App Privacy: Get Started, Edit, each data type and the draft Save; content rating: Save draft) and never signs in, submits or publishes: the owner presses the final button. Use when the user wants help filling one of these console forms, asks what to answer in them, or wants the answers as a checklist.
description: AI-assisted autofill of App Store Connect and Google Play Console forms that have no API (the New App dialog, App Privacy, Play's Create app form, the Play IARC content rating questionnaire, Target audience and content plus the Ads declaration; the App Store age rating is shown as guidance because the API sets it) in a visible browser with storebound's own profile that the owner signs in to once (never a copy of the owner's Google cookies unless they opt in); storebound opens the form itself. Answers come only from storebound.config.ts; anything the config does not prove stays empty and highlighted. storebound moves through the pages itself (Next; App Privacy: Get Started, Edit, each data type and the draft Save; content rating: Save draft) and never signs in, submits or publishes: the owner presses the final button. Use when the user wants help filling one of these console forms, asks what to answer in them, or wants the answers as a checklist.
---
# Console autofill (forms without an API)
@ -11,8 +11,10 @@ CLI: `storebound` (or `bunx storebound` in a project that has it, or `bun <toolc
answer in the wrong place. The owner reviews every field and presses the final button. storebound never types a
password, never touches a sign-in page, never prints or sends a cookie, and never clicks Submit, Publish, Create, a
final Save or anything that sends a form for review (English or Turkish console). It clicks only what moves through
the form (see "What storebound clicks" below). It reuses the owner's
Chrome sign-in through a temporary copy of only the console cookies (deleted at the end; `--fresh-profile` opts out).
the form (see "What storebound clicks" below). It works in its own
browser profile where the owner signs in once by hand. It never copies the owner's Google cookies unless the owner
opts in (`--use-chrome-session google`), because Google binds them to the device and may sign the owner out of their
real Chrome (step 3).
It is not available over MCP.
## Forms
@ -41,27 +43,44 @@ It is not available over MCP.
```
Age rating answers live in `apple.info.ageRating` (also `socialMedia`, `socialMediaAgeRestricted`).
3. The owner runs `storebound console fill <form>` in a terminal (or presses the button in the desktop app). The
first log line says which browser it uses, in this order:
first log line says which browser it uses:
- **profile** (the default): storebound's own profile (`~/.storebound/console-profile/<store>`, or `--profile <dir>`
/ `STOREBOUND_CONSOLE_PROFILE`; one per store, not per account: every studio shares the one login). Nothing is
read or copied from the owner's own Chrome. storebound starts Chrome itself as a normal window (its own
`--user-data-dir`, a DevTools port on 127.0.0.1, no `--enable-automation`, `navigator.webdriver` false, Chrome's
own user agent) and attaches to it. **First run:** the owner signs in there by hand, once (storebound never
types passwords): Play: the Google account that owns the developer account, then "Stay signed in"; App Store
Connect: Apple ID, password, two-factor code, "Keep me signed in" and "Trust" this browser. It is kept for the
next runs. If Google shows "Couldn't sign you in" (`/signin/rejected`), storebound says "Google refused sign-in in
this window"; try again, or open accounts.google.com in that window and sign in there first.
- **attach**: Chrome already runs with remote debugging (a `DevToolsActivePort` file in Chrome's user data folder,
or `--cdp http://127.0.0.1:<port>`): storebound opens one new tab there and closes only that tab.
- **copy** (default on macOS with Google Chrome installed): the owner's existing Chrome sign-in, no second sign-in.
storebound copies ONLY `Local State` and the profile's `Cookies` (+ `Cookies-journal`) into a temporary folder,
deletes every cookie there except the ones App Store Connect and Play Console get (apple.com and google.com
domains), and opens real Google Chrome on that copy. Never copied: passwords (`Login Data`), history, extensions,
bookmarks or anything else. The temporary folder is deleted when the run ends (window closed, error, Ctrl+C, or
Cancel in the desktop app). Chrome decrypts the cookies with its own Keychain key ("Chrome Safe Storage"); macOS
may ask once to allow that. `--chrome-profile "Profile 1"` picks another Chrome profile (default: the last used).
Cookies are never printed, logged or sent anywhere.
- **profile** (`--fresh-profile`, `--profile <dir>`, `STOREBOUND_CONSOLE_PROFILE`, or when the other two do not
work): storebound's own profile (`~/.storebound/console-profile/<store>`, one per store, not per account: every
studio shares the one login). The owner signs in there once; it is kept for the next run.
Keeping the sign-in: Apple's and Google's sign-in cookies are partly session cookies. storebound launches the copy
and the own profile with `--restore-last-session` (so Chromium loads them again) and always closes the browser
gracefully (window closed or Ctrl+C), so they are written to disk. Apple keeps a long sign-in only with "Keep me
signed in" ticked and "Trust" chosen for the browser; Google with "Stay signed in"; storebound reminds the owner on
the sign-in page. In copy mode the owner's Chrome Cookies file holds the session cookies only while that Chrome
runs, or when Chrome's "On startup: Continue where you left off" is on; otherwise one sign-in in the window is
needed.
or `--cdp http://127.0.0.1:<port>`): storebound opens one new tab there and closes only that tab. That is the
owner's own browser in place: no cookie leaves it.
- **copy: opt-in only, NOT recommended for Google** (`--use-chrome-session google|apple`, macOS): a temporary copy
of ONLY `Local State` and the profile's `Cookies` (+ journal), filtered to the ONE store's sign-in cookies
(google: play.google.com / accounts.google.com; apple: apple.com hosts), opened in real Google Chrome and deleted
when the run ends. Never copied: passwords, history, extensions, anything else. `--chrome-profile "Profile 1"`
picks the Chrome profile. **Why opt-in:** Google binds its sign-in cookies to the device (Chrome's Device Bound
Session Credentials: a key in the TPM / Secure Enclave that never leaves the machine; Google only renews the
short-lived cookies for the browser that holds it; public on Windows from Chrome 146, rolling out on macOS from
Chrome 147), and Google signs out sessions whose cookies look stolen: "the user is logged out of their account for
that session and any related suspicious sessions on that device" and must verify again. A copy of the owner's
Google cookies in a second Chrome is what that detection looks for: Google may answer `/signin/rejected`, AND it
may sign the owner out of their real Chrome or flag the account. In real use (October 2026) a copied Google
session reached Play Console once, then landed on `/v3/signin/rejected` and the account chooser. Apple publishes
no device binding for its web sign-in (fastlane's `spaceauth` reuses Apple sessions on other machines; Apple ties
them to a region), but it does not rule out a security check either, so the Apple copy is opt-in too. An agent
never adds `--use-chrome-session` on its own; the owner chooses it after reading this.
Sources: https://blog.google/security/protecting-cookies-with-device-bound-session-credentials/ ,
https://developer.chrome.com/docs/web-platform/device-bound-session-credentials ,
https://knowledge.workspace.google.com/admin/security/investigate-and-take-action-on-suspicious-session-cookies ,
https://docs.fastlane.tools/getting-started/ios/authentication/
`--fresh-profile` still works: it skips attach and copy.
Keeping the sign-in: Apple's and Google's sign-in cookies are partly session cookies. storebound starts Chrome with
`--restore-last-session` (so Chromium loads them again) and always closes it gracefully (CDP `Browser.close`,
window closed or Ctrl+C), so they are written to disk. Apple keeps a long sign-in only with "Keep me signed in"
ticked and "Trust" chosen for the browser; Google with "Stay signed in"; storebound reminds the owner on the
sign-in page.
Sign-in is detected by URL and by frame (App Store Connect `/login`, a frame from idmsa.apple.com /
appleid.apple.com, accounts.google.com, Google `/signin`), by a visible password field in any frame, and by the
form's own texts ("Sign in with Passkey", "Email or Phone Number", "Keep me signed in" and the Turkish ones):