# Changelog
## Unreleased
- `apple build` is hermetic and can be path-free. `--derived-data
` (`apple.build.derivedData`) is xcodebuild `-derivedDataPath`; with `--out` (or `apple.build.out`) it defaults to `/DerivedData` instead of `~/Library/Developer/Xcode/DerivedData` (without `--out` Xcode's folder stays). `--path-free` (`apple.build.pathFree`) remaps the home folder, checkout, out and DerivedData out of the app binary and the archive's dSYMs / Symbols (Swift `-debug-prefix-map` / `-file-prefix-map`, clang `-ffile-prefix-map`; dwarf-with-dsym stays, symbol upload keeps working), scans the archive and stops before the export with the hit count and the first file + offsets (never the paths). `--scan-paths` only scans and warns. A `--out` outside the home folder prints a hint. `--json` / `latest.json` carry `derivedData`, `pathFree` and `leaks`. Store-pitfalls 124.
## 0.8.53 · 2026-10-26
- Updates are agent steps (the owner's standing rule), first releases stay the owner's. `play release --production completed|inProgress --yes`, `play upload --track production --yes`, `apple submit --build --yes` and `apple release --manual-release --yes` run without an owner gate, in a terminal and in a pipeline, when the store says the app is already live (Play: the production track holds a completed / inProgress / halted release; App Store: a version of the platform is or was `READY_FOR_SALE` / `READY_FOR_DISTRIBUTION` / `REPLACED_WITH_NEW_VERSION`; `cli/lib/release-kind.ts`). The result line carries `releaseKind`; a re-run is exit 7. The first-ever release of an app with `--yes` is exit 3 `OWNER_STEP` ("first release of this app: the owner approves it once"), approved by `--first-release` (after the owner's yes) or bypass mode; a person answering the prompt (no `--yes`) is the approval too. `apple release` is now a ship step (`--json`, `--result-file`, exit 7 when the version is released already). Policy in docs/bypass.md ("Updates are agent steps"), docs/ship-step.md, the release-management and play-first-release skills, AGENTS.md; pitfall 123 / 96.
## 0.8.52 · 2026-10-26
- `analytics snapshot` and `reports` for a collector: a store-only config may name the App Store app by `apple.appId` alone (`bundleId` null or absent; every write still needs it); the Play reports bucket also comes from env `PLAY_REPORTS_BUCKET` or the credential profile's `reportsBucket` when `play.reportsBucket` is missing; `analytics snapshot --json` prints the snapshot as one JSON document on stdout (also when every store failed, with the exit code 1) and `--no-write` skips the file.
- Snapshots carry active-user numbers per day: App Store App Usage (`sessions`, `activeDevices`, `sessionSeconds`, `crashes` from the App Sessions and App Crashes reports; a missing usage report is a `notes` line, not a failure) and Play `activeDeviceInstalls` and `totalUserInstalls` (installs overview file, else the country file summed) next to `installs` (Daily User Installs).
- `reports apple-sales --days N | --from YYYY-MM-DD [--to ...] --json` reads the daily SALES reports of a range into one JSON (per-day summary and totals per currency, range totals per currency, `missing` days listed, never errors); `reports play-sales --days N | --from ...` gives the daily revenue per currency from the estimated sales reports (orders, refunds, charged, refunded, net, by order charged date). MCP `reports` takes `days`, `from`, `to`.
- Release: the dev-channel CI job no longer gates a release.
## 0.8.51 · 2026-10-26
- Tagged but not published (the dev-channel job hit a CDN 502); everything ships in the next version.
## 0.8.50 · 2026-10-25
- App Groups fail early under automatic signing too: `apple signing status` / `ensure` and `apple build` read the App ID's APP_GROUPS capability settings and the newest profile the API lists for each bundle id (an Xcode-managed one too) and compare it with the target's `com.apple.security.application-groups`. A profile without the group (or the capability off) stops `signing ensure` and `apple build` before the archive with the exact portal steps (Certificates, Identifiers & Profiles > Identifiers > the ID > App Groups > Configure > tick the group > Continue > Save), the deep link `.../identifiers/bundleId/edit/`, the plan command and `signing ensure --refresh-profile`; a group nothing can prove only warns with the same steps. `apple build --allow-app-group-gap` overrides.
- New `storebound console plan apple-app-group [--bundle-id ] [--groups group.a,group.b] [--lookup]` (MCP `console_plan`: `bundleId`, `groups`, `lookup`): the agent-first developer portal plan to assign an App Group to an extension's App ID (start URL per bundle id resource id, portal labels, answer sheet per extension, never-press list: Remove / Delete / Revoke). Its final Save is the agent's own (`buttons.finalByAgent`: a capability edit, not a store submission). `console verify apple-app-group` (MCP `console_verify`, API only) re-reads the App ID and the newest profile and fails while a group is missing or cannot be proven.
- Google access through a credential broker (`~/.storebound/broker.json`: `url`, `apiKeyFile`; env `STOREBOUND_BROKER_URL` / `STOREBOUND_BROKER_KEY_FILE`): Play tokens come from the broker's `POST /api/google/token` (in memory until 5 minutes before expiry, one request per account and scope, never logged; ya29. tokens and the API key redacted in errors), the local service account key stays the fallback when the broker does not answer or does not know the account; a broker that refuses the API key stops without retry. `PLAY_SERVICE_ACCOUNT_EMAIL` names the account (env, profile, project file); a profile opts out with `"broker": false`. The key file must be mode 600 on macOS / Linux. Play write commands read the package's Play permissions and enabled APIs from the broker first and stop before any Play call on a missing one (`CAN_MANAGE_TRACK_APKS`, `CAN_MANAGE_PUBLIC_LISTING`, `CAN_MANAGE_ORDERS`, `CAN_MANAGE_APP_CONTENT`, the Games Configuration API) with the exact permission or API and its link; `validate` lists them (gaps are blockers, SDK config drift a warning) and `--json` carries `credentials.play.source`; `doctor`, `accounts` and `apps check` / the desktop's Accounts view say whether tokens come from the broker or the key file. A Google 403 SERVICE_DISABLED / PERMISSION_DENIED in the Play client names the API or grant with its fix link and is never retried (pitfall 122, docs/credential-broker.md).
## 0.8.49 · 2026-10-25
- `play listing` for a language Play does not have yet uploads, in the same edit as the text, everything Play requires to commit it: icon, feature graphic, 2+ phone screenshots from `store/renders//` and the tablet sets when the other languages have them (a set the folder lacks falls back to the default language's). The dry run lists the uploads or refuses with the missing file, instead of a 403 "too few screenshots" at commit. `play images` creates a Play listing that does not exist yet (text from the listing file) together with its images instead of skipping the language (pitfall 102).
## 0.8.48 · 2026-10-24
- Desktop tray: the right-click menu is drawn by the app (the design system's menu look) instead of the OS menu. Each submenu opens as its own small panel; the pin button, Ctrl+click or a middle click keeps a panel open (pinned): it can be dragged, steps aside so it never covers another pinned panel, and comes back after a restart. Values (the apps and their store state, mute) update in place after every store read without closing anything. The native menu stays as a fallback (and on Linux), built from the same menu tree. The left-click tray card is unchanged.
- Desktop right-click menus in the window work the same way: a menu's pin button keeps it open as a floating panel, a submenu can be torn off (its pin button, Ctrl+click or a middle click), pinned panels survive the next menu, can be dragged, and update in place when the data behind them changes ("Gone" when the thing they were for left the screen).
- `shots.feature.rotate` (degrees) is honoured by the Play feature graphic like a scene frame's `rotate`: added to the template tilt and the phone is re-fitted (`-90` stands a landscape game frame upright); with `shots.layout: "bleed"` the frame image is turned and still covers the canvas.
- `shots check` / `shots render` without frames for a language that has copy use the default language's frames (an info line, no failure); `shots.perLanguageFrames: true` requires per-language frames. `shots fonts --lang en,tr` limits the report to those languages (the font manifest keeps all of them).
- `shots capture` web shots take `waitSelector` and `click` selector lists per layout (`{ phone, tablet, any }`, data attributes first, `text=` fallback). A miss names the selector and the size with every candidate's match count; `shots capture --dry` prints the candidates per size and `--dry --probe` opens the pages and reports which one matched or MISSed on which size.
- `apple signing ensure` signs every target of the Xcode project, not only the app: it reads the pbxproj targets (app, app extensions such as a share extension or widget, watch app, App Clip: Release PRODUCT_BUNDLE_IDENTIFIER and entitlements), registers each extension's bundle id (`POST /v1/bundleIds`, platform from the profile type), enables the capabilities its entitlements need (read back) and, with manual signing, creates its App Store profile; `--dry` lists every target. `apple.signing.extensions` (`bundleId`, `name`, `capabilities`, `appGroups`) replaces the detected extensions when detection is wrong; `status` shows a target table.
- App Groups: the API cannot assign a group to a bundle id, so `signing status` / `ensure` and (manual signing) `apple build` decode the profile and compare its `com.apple.security.application-groups` with the target's entitlements; a gap names the developer portal link (`.../identifiers/bundleId/edit/`) and the steps to tick the group. `signing ensure --refresh-profile` makes the profile again afterwards; `apple build --allow-app-group-gap` overrides.
- `apple build` over SSH / in CI: the refusal now names the fixes (GUI session `.command` file, a CI runner with an unlocked keychain, a build keychain). New `--keychain-unlock` (keychain password from `STOREBOUND_KEYCHAIN_PASSWORD`, never printed; runs `security unlock-keychain` and `set-key-partition-list`) and `--keychain ` (sign with a build keychain).
- `storebound api` writes: the usage, the dry-run message and the refusals show the agent form with an example (`--yes --confirm `), and the store-api skill says both flags are needed.
- Play managed publishing: `storebound console plan play-publish-changes` (Publishing overview > "Changes ready to publish" > the owner's final "Publish N changes" + its confirm dialog; never-press: Discard changes, Stop managed publishing; `--lookup` lists the ready production releases from the API) and `console verify play-publish-changes` (API: passes when no production release is left ready to publish; or the page text). `play status` (and `--json` `readyToPublish`) prints the ready items and the plan hint, `storebound status` names the plan, and the desktop Releases tab shows the same hint with a button that opens Publishing overview. A release counts as ready to publish only when the public store page positively shows an older version; a 404, a failed or stale page read, a same or unparseable version is never ready (verify says "not determined" instead of a mismatch).
- `apple upload` / `play upload` `--pre-check ""` (config `upload.preCheck`) runs your gate before any byte is sent; a nonzero exit refuses the upload (ship-step exit 1, `PRE_CHECK_FAILED`). `--evidence ` (`upload.evidence`) writes file, sha256, size, command, exit code, stdout tail, time and version, also on failure, and the result carries it as `preCheck`.
- New `storebound shots copy translate --to de,es` fills store/shots/copy.json per language (agent translation or `--translate ""`), machine-translated until `shots copy reviewed`, caption limits respected; `shots copy check`; `check` / `shots render` name this command for a missing language.
- `apple game-center --locale-map en=en-GB` (config `games.localeMap`) maps a config language to the live Game Center locale; the dry run suggests it when the live Game Center has exactly one variant of the language.
- `play games`: a 403 SERVICE_DISABLED / accessNotConfigured names the Google Play Game Services Publishing API, the enable URL for the project and `console plan play-games-services`.
- `apple build --platform macos --tauri [--path-free] [--unsigned]`: Mac App Store build of a Tauri app. Generated sandbox entitlements, Mac App Store profile (installed, `--profile` or from the API), Apple Distribution / Mac Installer Distribution identities, `tauri build --bundles app`, checks of the .app, `productbuild` to a signed .pkg, `pkgutil --check-signature`; `--path-free` remaps local paths in rustc and fails on any leak of the home folder or user name. `apple upload --platform macos` uploads it (platform MAC_OS). New certificate types MAC_APP_DISTRIBUTION and MAC_INSTALLER_DISTRIBUTION. Pitfall 119.
- Desktop dev update channel: Settings > Updates offers Stable (the npm releases) and Dev (every push to main). Each push to main builds Windows and Linux bundles stamped `-dev.` (above the current stable, below the next one); the VDS signs them and serves `storebound.dev/desktop/dev/latest.json` (newest 5 kept). The app checks its channel at start, every 15 minutes, after sleep and right after a channel switch, installs a strictly newer build quietly (deferred while the window is in use), never downgrades (dev back to stable waits for a newer stable), rewrites its logon autostart on every start, and the tray card shows version and channel. No macOS dev builds (Developer ID signing needs the Mac's GUI session).
- `shots` full-bleed layout: `shots.layout: "bleed"` fills the image with the app's own frame (no device, no background) and puts the scene title as a short corner caption (`corner`, `captionScale`, `captionWidth`, `captionInset` per scene) legible through a text shadow and soft glow only; the Play feature graphic shows the logo or `shots.feature.title`. Frames are captured per size at its own pixels in `///.png` (feature: `/feature/`), including the `mac` and `chromebook` sizes; `shots check` / `capture --source folder` verify aspect and native width. `shots.orientation: "landscape"` (bleed only) renders every portrait size landscape (stores accept it). Templates `template-bleed.html`, `feature-bleed.html`.
- `storebound desktop`: "opened" now also works when a hidden tray copy is already running. On Windows it prints "opened" only when a process of the installed path has a visible window (the running copy shows it through the single-instance handoff); on macOS / Linux a visible start or a handoff to the running copy counts, otherwise it says only a tray copy runs. The graceful stop waits 3 s on Windows (closing a tray app only hides it), then stops by PID.
## 0.8.47 · 2026-10-23
- `storebound desktop`: an update no longer reports "installed" while the old app stays. It stops the running app first (exact install path only, graceful close, then by PID), checks the installed exe's own version (Windows PE version resource instead of the registry entry; Info.plist on macOS) and fails with what it found, and prints "opened" only when a visible (not `--hidden`) process started from the installed path, otherwise it names the app's log.
- `play products` / `play subscriptions`: regions outside Play's min / max (a 649.99 USD product in KR: "must be between ₩70 and ₩600,000") are flagged in the dry run (old -> new) and clamped to the bound on write with a warning; `--skip-out-of-range-regions` leaves them out. Limits Play reports in a 400 are learned (`.storebound/play-price-limits.json`) and the write is retried. A product or subscription that fails no longer stops the others: per-product results, exit 1 at the end.
- `apple iap` / `apple subscriptions`: edits to approved (ACTIVE) localizations, which App Store Connect refuses with 409 UNMODIFIABLE, are marked "not editable now" in the dry run and skipped with a warning on write; prices and the other changes still apply. One IAP failing no longer stops the rest (results at the end, exit 1).
## 0.8.46 · 2026-10-23
- `storebound watch` has an `ingest` sink (`--notify ingest`, `ingest` in ~/.storebound/watch.json): a JSON POST per event to a push ingest endpoint with a Bearer token read from a file at send time (refused when group or world readable), 8 KiB body cap, 60 sends a minute, one retry on 5xx; `watch test` covers it.
- Ship-step contract for release pipelines (docs/ship-step.md): `play build | upload | release`, `apple build | upload | submit | resubmit` exit 0 ok, 1 failure, 2 usage, 3 needs the owner (with `error.code` and the console deep link), 4 store refused, 7 nothing to do; `--json` ends with exactly one result line on stdout, `--result-file` writes it atomically (also on failure), `--progress json` gives one JSON line per phase on stderr.
- `--env-file ` loads KEY=VALUE secrets before the credentials resolve (POSIX: mode 600 or stricter) and every known secret value is scrubbed from stdout, stderr and the result file; `--version-from version.json` takes the version and build ({version, build}, {versionName, versionCode}, {marketing, build}).
- Re-runs never upload twice: `play upload` with a versionCode Play has and `apple upload` with a build number App Store Connect has end with exit 7 and what is there; `play release` with the same release and `apple submit` of an already submitted build too.
- `play upload --track production` (the pipeline's update step; `--status draft` keeps it for the Console) and `--version-code N` to pick the AAB.
- New `storebound status [--app ] [--json]`: per platform the live and next version, build, track, review state and rollout %, read-only. `release status --app` also takes a folder or a store id.
- Desktop: every read goes through one registry: one store call per read however many buttons are clicked, overlapping buttons (Refresh all, card refresh, Check again, Import, Test) are busy and disabled together, a read just finished is not repeated, and all reads share the scheduler's rate limits and backoff.
- Desktop: tray mini card on left click (rejections, releases moving, crash alerts, recent low reviews, refresh, quick actions); right click keeps the menu.
- `apple build` / `apple upload`: `--allow-version-mismatch` is accepted (it was missing from the flag list); 1.0 and 1.0.0 count as the same version train, as on App Store Connect.
- Desktop: custom context menus everywhere (apps, releases, art, reviews, checks, fields, products, accounts, folders) with keyboard navigation, Shift+F10 and submenus; the WebView2 browser menu and browser shortcuts are off.
- Desktop: each app shows once again (a folder project no longer appears a second time as a store-only app); a store app with a folder's bundle id or package is never listed separately.
- Desktop UX pass on every screen: app tabs fit the window, slim app header, secondary actions in "…" menus, Ctrl+K lists app actions, Alt+Up/Down switches apps, accounts and folders decluttered.
- Play Console links open the app's own page: developer id per credential profile (`storebound accounts play-developer `, editable in Studios & accounts), one link builder for desktop, CLI and watch.
- Desktop: tabs in one row with a More menu, one Refresh, reviews keyboard (J/K, R, C, O), Settings and More tools search, sticky first column and compact density for wide tables, styled in-app dry-run preview before every write.
- Checks: "Open guide" opens the matching skill for every finding.
## 0.8.45 · 2026-10-23
- Tagged but not published (the release upload could not reach the server after an IP change); everything ships in the next version.
## 0.8.44 · 2026-10-23
- Tagged but not published (desktop clippy red on the bump commit); everything ships in the next version.
## 0.8.43 · 2026-10-23
- Tagged but not published (CI red: scrub hits in test fixtures, a ship-step test); everything ships in the next version.
## 0.8.42 · 2026-10-23
- Tagged but not published (generated API tables differed on Linux CI); everything ships in the next version.
## 0.8.41 · 2026-10-23
- Tagged but not published (a generated API table was stale in CI); everything ships in the next version.
## 0.8.40 · 2026-10-23
- Tagged but not published (the desktop boot check stopped it); everything ships in the next version.
## 0.8.39 · 2026-10-23
- Tagged but not published; everything ships in the next version.
## 0.8.38 · 2026-10-23
- Desktop: the app hero no longer shows a cropped second copy of the app icon.
- `play build` passes the upload key (ANDROID_KEYSTORE, ...) to Gradle as injected signing properties (store file and alias as `-P` arguments, the passwords only through `ORG_GRADLE_PROJECT_*` environment variables, never on argv), so a build file that signs only from a local keystore.properties no longer gives an unsigned AAB in CI (pitfall 107).
- `play build`, `play upload` and `play release` of a local AAB verify it is signed (META-INF entries, `jarsigner -verify` when a JDK exists) and fail with the fix before any upload.
- `apple build --version` and `apple upload` refuse an IPA whose CFBundleShortVersionString is not the intended / editable App Store version; `--allow-version-mismatch` overrides (pitfall 108).
- Play release notes that name iOS, iPhone or the App Store are caught by `storebound check` and `play build`, not only at release time (pitfall 109).
## 0.8.37 · 2026-10-22
- `storebound apps ignore|unignore [--store apple|play]`: hide dormant apps, or one store side of an app, from watch, reads and the desktop (MCP apps_ignore / apps_unignore).
- Reviews: a store read that fails is an error, not an empty "no new reviews" list; the Reviews tab notes Apple API lag and Play's 7-day window (pitfall 106).
- Desktop: live store thumbnails load right away, also in a hidden window.
## 0.8.36 · 2026-10-22
- `storebound watch`: a store-only App Store app added without a bundle id is no longer skipped; the bundle id is read from the API with the app's own key.
## 0.8.35 · 2026-10-22
- Desktop v2 ships (0.8.33 and 0.8.34 stopped at the desktop boot check, which still expected the old markup).
## 0.8.34 · 2026-10-22
- Desktop v2 ships (0.8.33 stopped at the desktop boot check, which still expected the old markup).
## 0.8.33 · 2026-10-22
- **Desktop v2**: every screen redesigned in one language: portfolio home, releases (store cards, stage stepper,
rollout ring), submit checklist, TestFlight, listings as store pages with completeness, framed screenshots with issue
badges, products and price matrix, health tiles, review feed with rating distribution, growth funnel, readiness score
with fix-first, tools, settings, accounts, folders, dependencies and onboarding.
- Desktop: tray with a context menu, autostart, silent auto-update and notifications by event kind (rejections too),
also while the window is hidden.
## 0.8.32 · 2026-10-22
- Node: a `storebound.config.json` (and every store-only app) loads again; it needed an import attribute. Pitfall 105.
## 0.8.31 · 2026-10-22
- **`storebound watch`**: store events for every app on the machine (rejected, approved, live, rollout halted, crash
threshold, low or unanswered reviews), sent to ntfy (phone), Telegram, a webhook or an OS notification; runs as a loop
(`--every 15m`) or `--once`; a PM2 recipe for a server is in docs/watch.md. `storebound events` and the MCP tool
`events_recent` let people and agents read what happened.
- **Desktop notifications that arrive.** The app reads the stores in the background from the tray too (it skipped
every read while hidden, so a rejection went unnoticed), every 15 minutes with backoff. Notifications by kind, each
with a switch: rejected, approved, live, halted, crash / ANR, low-rated reviews; quiet hours and mute for an hour.
Opening the window after a notification lands on that app.
- **Tray:** Open, Read the stores now, an Apps menu with each app's state on both stores, Mute, Check for updates,
Settings, Quit; a tooltip with what is in review and what needs you; a red dot on the icon after a rejection or halt.
- `apple listing` refused by an approved version waiting for a manual release now names the way out:
`storebound apple release --manual-release --version `. `play release --dry` shows the staged rollout share.
## 0.8.30 · 2026-10-22
- **Desktop: a new home.** Store-style app cards (your rendered screenshots, or the icon on its tint), a release
pipeline per store (Build -> Testing -> Review -> Live -> Rollout), the crash curve and one next-step button per app;
below, What changed and Fix first. The table view stays one switch away.
## 0.8.29 · 2026-10-22
- **Existing store items are compared with the config, field by field** (pitfall 104). The dry run shows every
difference (old -> new); texts are sent, money and availability need a flag, fields Apple cannot edit are named.
- `apple iap`: price (`--allow-price-changes`), localization names and descriptions, reference name, review note,
family sharing (reported), territories.
- `apple subscriptions`: prices in the dry run, localizations, group names, reference name, review note, level,
territories; intro offers, period and family sharing reported.
- `play subscriptions`: offer phases and prices, other-regions price, regions no longer sold (all price-gated),
grace period, languages missing from the config kept unless `--prune-languages`.
- `apple appinfo`: app price (`--allow-price-changes`) and territories (removals `--allow-availability-changes`);
`apple review-details --dry` shows old -> new.
- Offer-code and win-back campaigns that differ are named; in-app event attributes patched on drafts; a removed
custom page deep link cleared; config languages without a version localization named.
- `prices diff` (the `catalog diff` report).
## 0.8.28 · 2026-10-22
- Windows: no false "entitlements not referenced by CODE_SIGN_ENTITLEMENTS" warning (paths compared with forward slashes). Pitfall 103.
- **`storebound apps relink`** after a machine move: every "folder not found" entry of the app folder list is pointed at
the same app on this machine (by its path or its app name), ids kept so the desktop keeps its accounts and settings;
`apps folders` says so when entries are missing. `apps add` names an app after its config's app name.
## 0.8.27 · 2026-10-21
- **Desktop: tray app that starts at logon and updates itself.** First run registers a logon entry (`--hidden`): the app
starts silently in the tray; closing the window keeps it there, the tray menu quits. A signed update is checked a
minute after start and every 30 minutes, installed silently, and the app restarts as it was.
- **App Privacy console plan follows today's page** (verified 2026-10-22): on an app published before, Edit opens the
Data Collection question first and the type list ends in Continue; each type's last step is Publish (it goes live,
no draft). Publish stays the owner's unless bypass mode is on.
- **A new Play language in one run.** `play listing` uploads the hi-res icon (and the feature graphic when rendered) for a
language Play does not have yet, in the same edit (Play refused the commit with 403 otherwise). Pitfall 102.
- Script traces skip test files (`*.test.*`, `*.spec.*`).
- **CI-friendly Play output.** `storebound aab --json` reads packageName, versionCode, versionName, SDKs and
sha256 offline (no config, no upload); `play release ... --json` prints {versionCode, sha256, name, tracks[{track,
status, userFraction}]}. `play status --json` already lists each track's releases.
- **`apple build` stops at once over SSH** (codesign fails there with errSecInternalComponent) and names how to run it
in the logged-in session; relative `ASC_P8` / `PLAY_SERVICE_ACCOUNT` paths are read from the project folder and
xcodebuild gets an absolute key path. Pitfall 101.
## 0.8.26 · 2026-10-21
- **Bypass mode (owner opt-in, default off).** `storebound settings bypass on` (or "y" in `storebound init`) lets the AI
agent press the owner-only buttons too: MCP `owner_step` (submit, release, rollout, testers, replies, prices, ...;
dry run first), owner-only `storebound api` operations with `--yes --confirm `, console plans'
`buttons.final`. Every action is logged to `.storebound/owner-actions.log`; `bypass off` restores the old behaviour.
docs/bypass.md.
- **Build dependencies in `doctor` and the desktop Dependencies screen.** JDK (with the version the project needs from
the Android Gradle plugin / jvmToolchain, "too old" when below it), Android SDK command-line tools, CocoaPods, Node.js,
Bun and bundletool join ffmpeg, Chrome, Xcode, adb and git. `storebound doctor --install --yes` runs this OS's
package-manager command (winget / brew); sudo and admin commands are printed, never run.
- **A livelier terminal.** At a terminal, lines get colors and status emoji (✅ ⚠️ ❌ 📦 🚀 🧪) and every wait ("waiting
for ...", uploads, downloads, progress) is one live spinner line with the elapsed time. Piped, CI, `NO_COLOR`,
`TERM=dumb`, `--json` and MCP keep the plain lines exactly as before.
- **MCP `console_verify` reads multi-line page text whole** (it kept only the first line on Windows), and long JSON
output such as `console_plan` keeps its start and names a file with the whole output. Pitfall 100.
- **Windows builds.** `play build` runs `gradlew.bat` through `cmd /c` (it was looked up on PATH only) and takes
`C:/...` keystore paths as absolute. Pitfall 98.
- **`check` verifies credential files.** Every credential path that does not exist on this machine and an upload keystore
the stored password / alias do not open (keytool) are named by field. Pitfall 99.
- `play build` / `apple build` write `/latest.json` with the AAB / IPA path for CI; CI install from a git clone documented.
- **Scripts that call the store APIs themselves are named.** `androidpublisher.googleapis.com`, the googleapis
androidpublisher client, `api.appstoreconnect.apple.com`, altool and Transporter in CI files and scripts: `check` and
`release status` warn, `scan` reports `direct-store-api`, each with file:line and the storebound command. Pitfall 97.
## 0.8.25 · 2026-10-21
- **fastlane left in a project is named.** `check` and `release status` warn and `scan` reports `fastlane-upload`
when a Fastfile / Appfile or a CI file or script still runs `fastlane supply`, `deliver` or `pilot`, with the
file:line and the way over (`storebound import fastlane`). Pitfall 96.
## 0.8.24 · 2026-10-21
- **Windows: the MCP server starts.** `storebound install` writes `cmd /c npx -y storebound@ mcp` (or
`bun /cli/index.ts mcp`) on Windows, where `npx.cmd` and the sh launcher cannot be spawned. Pitfall 94.
- **`storebound desktop` no longer waits forever on a stalled download.** Progress every 10 %, and an error after
60 s without data. Pitfall 95.
- Windows checkouts keep LF line endings (`.gitattributes`); README badges: live npm version, real skill count.
## 0.8.23 · 2026-10-21
- **`apple submit --yes` submits a draft prepared with `--no-submit`.** The second step of the two-step flow
ended with "nothing to submit" when the draft already held the version and every item; it now sends the submit
(same "not ready yet" retry). `iap-submit` the same for a draft that holds the asked-for items. Pitfall 90.
## 0.8.22 · 2026-10-20
- **`apple submit` / `resubmit` switch Game Center on first.** A build with the Game Center entitlement and an app
without a Game Center detail was refused with 409 STATE_ERROR.BUILD_INDICATES_GAME_CENTER_ENABLED; submit,
resubmit and `apple signing ensure` now create `gameCenterDetails` and the version's `gameCenterAppVersions` first
(dry run shows it), and `validate` blocks while either is missing. Pitfall 89.
- **`apple testflight distribute` creates missing configured groups first** (only the asked-for ones, never removes
one); tester invites stay the owner's.
- **Console plans follow the live pages (2026-10-21 run).** Play health: "My app does not have any health features"
(verify accepts it, "Other" stays a fallback); Sign in details: "Is any part of your app restricted?" Yes / No and
"Add details" (old labels kept as `altLabels`); finance: the boxes on step 1, step 2 information only; App Privacy:
the "Additional Setup Required" OK that opens the first type's setup by itself is in the steps and UI facts.
- **Save after every page.** Every Play plan step that answers a page with a Save next to Next now says Save, wait
for "Your changes have been saved", then Next; the rule line says it too.
- **IARC by exact labels.** "Purchases of digital goods" is ticked after Yes on "Digital purchases" (the loot-box and
trading follow-ups show only then); the in-page helper matches exact labels and questions and refuses patterns,
radios without their question and blanket group answers.
- **`console verify` reads input states.** The Play declaration plans' `verify.capture` returns every radio /
checkbox with aria-checked / checked / aria-selected as JSON; `console verify