- cli/serve.ts: session.hello with a per-session secret, typed methods per tool, project.inspect, portfolio.status over many project folders, progress notifications, cancellation - cli/lib/confirm-token.ts: single-use HMAC tokens bound to method + canonical params + expiry; writes are dry runs without one; no submit / release / publish method exists - cli/lib/runner.ts: shared child runner for mcp and serve, works from a compiled binary - --json on check, testflight / ppo status, next-build, next-version-code, analytics compare, prices import; inspect command; confirm() always answers no under serve - tools/build-sidecars.ts: bun build --compile for five targets, ad-hoc re-sign on macOS, path leak check - tests/serve.test.ts: methods, token binding / expiry / replay, shared vector, stdio and compiled smoke
194 lines
17 KiB
Markdown
194 lines
17 KiB
Markdown
# Changelog
|
|
|
|
## Unreleased
|
|
|
|
- **Desktop machine interface** (`serve --stdio`): JSON-RPC session for the coming desktop app, built on the MCP core.
|
|
Typed methods with argument schemas, structured results, progress notifications, cancellation, `project.inspect`
|
|
and `portfolio.status` (many projects; `live` adds App Store and Play status). Writes are dry runs unless the host
|
|
sends a single-use confirm token bound to the method, arguments and a short expiry (HMAC with a per-session secret
|
|
handed over on stdin). No submit / release / publish method exists. Under `serve`, terminal confirmations always
|
|
answer no.
|
|
- `--json` on `check` (and `check --aso`), `apple testflight status`, `apple ppo status`, `apple next-build`,
|
|
`play next-version-code`, `analytics compare` and `prices import` (read-only diff); new `inspect` command.
|
|
- `tools/build-sidecars.ts`: single-file executables for macOS (arm64, x64), Linux (x64, arm64) and Windows (x64),
|
|
re-signed ad hoc on macOS and checked for build-machine paths. The MCP server now also runs from such a binary.
|
|
|
|
## 0.5.0 · 2026-10-11
|
|
|
|
Apps and games: storebound is for every mobile app, not only games, and the in-app catalog is complete on both stores.
|
|
|
|
- **Positioning**: "Take a mobile app or game from nothing to Submit for review on Google Play and the App Store"
|
|
across the README, the site (new "Apps and games" section, app screenshot style, og image), package, plugin and
|
|
adapter descriptions, CLI help, MCP server instructions and the skills. Game-specific advice stays, marked for games.
|
|
- **`init --profile app|game|subscription-app`** (default `app`): per profile a config, `declarations.md`,
|
|
`app-privacy.md`, the Data safety section, listing and screenshot copy and a privacy policy. app = utility /
|
|
productivity app with an optional account and analytics, no ads; subscription-app = accounts + auto-renewable
|
|
subscriptions with the disclosure text; game = the 0.4 templates. Every answer is flagged "edit to match your app".
|
|
Configs without `app.profile` keep working as games.
|
|
- **App screenshot style** (`shots.style: 'app'`, the default for the app profiles): calm gradient, a clean device frame,
|
|
headline + subline, no sparkles or badges (badges only as quiet chips), status bar text that follows the frame, Inter
|
|
by default, app palettes (mist, paper, mint, sand, rose, sky, ocean, slate), its own feature graphic. Game style
|
|
unchanged. New demo `examples/demo-app` ("Tidy Lists").
|
|
- **App identity**: `app.platforms` (default from the `apple` / `play` sections) and `platforms` on a product or
|
|
subscription to sell it on one store only; one shared catalog and shared listings, per-platform settings in
|
|
`apple` / `play`.
|
|
- **Subscriptions on both stores**: `apple subscriptions` (groups and display names, subscriptions with period, level,
|
|
family sharing, localizations, availability, prices from the USA price point and its equalizations plus overrides
|
|
and `--csv` rows of the prices sheet incl. scheduled changes, introductory offers per territory, promotional offers,
|
|
offer code campaigns, custom codes only with `--codes` after a terminal confirmation, review screenshots) and
|
|
`play subscriptions` (listings with benefits, one auto-renewing base plan with grace period and regional prices from
|
|
`convertRegionPrices`, overrides and CSV, activation, the intro offer for new subscribers and extra offers chosen by
|
|
your app through offer tags). Both print a plan, `--dry` stops there, a terminal run asks first; without a terminal
|
|
(MCP) only new records are created and live price changes wait for the owner. Skill `store-subscriptions`.
|
|
- **Full IAP catalog**: product type `non_renewing` (Apple NON_RENEWING_SUBSCRIPTION; a consumed one-time product on
|
|
Play), and **`catalog diff`**: the config's products and subscriptions against both stores (missing, extra, type,
|
|
billing period, level, US and override prices, localizations, offers) plus regions where the two stores price the
|
|
same item differently (same currency, `--threshold`). Read-only, exit 1 on mismatches.
|
|
- **Review access**: `apple review-details` sends `demoAccountRequired` / `demoAccountName` / `demoAccountPassword`
|
|
from `reviewDemoAccount` in `.storebound/credentials.json` (or `REVIEW_DEMO_USER` / `REVIEW_DEMO_PASSWORD`), masked
|
|
in every log line, and adds the sign-in steps (`reviewAccess.instructions`) and where account deletion is
|
|
(`accounts.inApp`) to the notes (4000-byte check). Skill `review-access`.
|
|
- **Account deletion**: `accounts { enabled, deletionUrl, inApp }`; skill `account-deletion` (Apple 5.1.1(v), Play's
|
|
in-app + web requirement and Data safety). `dataSafety.extra` adds CSV rows for questions Google does not document
|
|
(e.g. the delete-account URL id from a Console export).
|
|
- **Checks**: `check` reports the profile (delete-account URL, Data safety consistent with accounts, demo account
|
|
present, terms URL with subscriptions, subscription review screenshots); `validate` adds subscription states,
|
|
localizations, group names and review screenshots (App Store), active base plans (Play), the delete-account and
|
|
terms URLs answering, the demo account on App Review and a Terms of Use link in the descriptions.
|
|
- **Ad mediation**: `ads-levelplay-checks` became `ads-mediation-checks` (AdMob Ad Inspector, AppLovin MAX Mediation
|
|
Debugger, LevelPlay as a section, app-ads.txt, SKAdNetwork); the old name stays as a pointer skill.
|
|
- **MCP tools**: `apple_subscriptions`, `play_subscriptions` (dry run by default), `catalog_diff` (read-only). Custom
|
|
offer codes and live price changes are not reachable through MCP.
|
|
- Unverified until a live account run (see the README): free promotional offers / offer codes without a price point,
|
|
inline subscription prices and intro offers via `PATCH /v1/subscriptions/{id}`, Play relative-discount and untargeted
|
|
offers, the Play billing period strings and the undocumented Data safety ids.
|
|
|
|
## 0.4.0 · 2026-10-10
|
|
|
|
Wave 2: TestFlight and life after launch (stability, reviews, prices, analytics, experiments), plus MCP 2026-07-28.
|
|
|
|
- **TestFlight through the API** (`apple testflight status | groups | testers | what-to-test | info | distribute`):
|
|
beta groups from `apple.testflight.groups` (internal / external, public links; created when missing, never changed
|
|
or deleted), testers from a CSV in `.storebound/` (the config refuses a path outside it; emails masked in every log
|
|
line; asks before Apple emails invitations; `--remove`, `--invite`), "What to Test" per locale from the App Store
|
|
listing (`### whatToTest`, else the `whats-new` notes), Test Information and Beta App Review contact / notes, a build
|
|
by its exact number to groups, Beta App Review submission behind `--submit-review` and a confirmation. Skill
|
|
`testflight`.
|
|
- **Crash and vitals health** (`health [--weekly]`): Play Developer Reporting API (user-perceived crash and ANR rates,
|
|
28-day user-weighted, worst device models, top error issues) and App Store power and performance metrics,
|
|
diagnostic signatures and TestFlight crash reports. Play's bad behavior thresholds (1.09 % crash, 0.47 % ANR, 8 % per
|
|
device, developer.android.com/topic/performance/vitals): over = blocker, from 80 % = warn, also in `validate`
|
|
(`--no-health`). Weekly Markdown report with week-over-week change in `.storebound/health/`. Skill `store-health`.
|
|
- **Review replies** (`reviews list | draft | send`): App Store customer reviews / responses and Play reviews; drafts
|
|
as Markdown in `.storebound/replies/` (never overwritten), `send` only sends drafts with `approved: true` after a
|
|
confirmation and refuses incentives, rating requests and Play replies over 350 characters. Skill `review-replies`.
|
|
- **Price sheet** (`prices export | import`): one CSV of product x store x region; diff table first, then (after a
|
|
confirmation) one App Store price schedule per changed product (base territory, every manual price, future-dated
|
|
changes with `start_date`) and the Play purchase option's regional prices (`convertRegionPrices` for regions without
|
|
a price, `--reconvert`). `store-iap-setup` skill: price sheet section.
|
|
- **Analytics snapshots** (`analytics setup | snapshot | compare`): App Store Analytics Reports API (Discovery and
|
|
Engagement + Downloads, md5-checked segments, newest processing per day) and the Play statistics exports in the
|
|
`pubsite_prod_rev_` bucket (`play.reportsBucket`); snapshots in `.storebound/analytics/`, `compare` lines them up
|
|
with the git history of the store files. Skill `store-analytics`.
|
|
- **MCP 2026-07-28**: stateless requests with per-request `_meta` and `server/discover` (supported versions,
|
|
capabilities, instructions; `resultType`, server info in every result's `_meta`, cacheable `tools/list`, -32022 for
|
|
unsupported versions); `initialize` clients (2025-11-25 and older) keep working on the same process.
|
|
- **Product Page Optimization through the API** (`apple ppo status | create | upload | start | stop`): v2 tests with
|
|
one treatment per `shots` variant, a localization per locale and the variant renders in the treatment screenshot
|
|
sets; start / stop ask first. Play store listing experiments stay console-only (documented).
|
|
- **`iphone-medium` size key** (1206 x 2622, `APP_IPHONE_61`), off by default; `apple.iphoneMedium: true` renders,
|
|
checks and uploads it. Apple scales the 6.5" set down when it is missing.
|
|
- **MCP tools**: `apple_testflight_status`, `apple_testflight_groups`, `apple_testflight_what_to_test`,
|
|
`apple_testflight_info`, `apple_testflight_distribute` (internal groups only), `health`, `health_report`,
|
|
`reviews_list`, `reviews_draft`, `prices_diff`, `prices_export`, `analytics_snapshot`, `analytics_compare`,
|
|
`analytics_setup`, `apple_ppo_status`, `apple_ppo_create`, `apple_ppo_upload`. Not exposed: tester changes and
|
|
invitations, external distribution and Beta App Review, sending replies, applying prices, starting / stopping tests.
|
|
- Agent rules: owner-only steps now include review replies, tester invitations, price changes and experiments; personal
|
|
data (tester lists, reply drafts, health and analytics files) stays in `.storebound/`.
|
|
- `apple screenshots --dry` no longer creates empty screenshot sets.
|
|
|
|
## 0.3.1 · 2026-10-10
|
|
|
|
Positioning: storebound is the whole road from zero to "Submit for review", screenshots are one step of it.
|
|
|
|
- **README** rebuilt around the end-to-end journey: a new diagram (`docs/img/journey.svg`) and a step table for both
|
|
stores showing what storebound does through the APIs, what the skills walk your agent through in the consoles
|
|
(IARC, target audience, ads, advertising ID, App Privacy, app records, the first Play production send) and what
|
|
stays your own click (Send for review / Submit for Review, releases). "API or console, honestly" summary, a new FAQ
|
|
("Does it fill the questionnaires?"), quick start along the journey with the npm package, skills in journey order;
|
|
the screenshot and video showcase moved to a "Store art" section.
|
|
- Package, plugin, Codex, Gemini and marketplace descriptions follow the new positioning.
|
|
- `package.json` `bin` path normalised (`cli/index.ts`), so npm keeps the `storebound` command.
|
|
|
|
## 0.3.0 · 2026-10-10
|
|
|
|
Screenshots and videos from any engine, reviewed before they leave your machine.
|
|
|
|
- **Capture from anything** (`shots capture --source`): `web` (Playwright, unchanged), `ios-sim` (simctl boot, 9:41
|
|
status bar, launch arguments / deep links, `-AppleLanguages`, warm-up after a cold boot, shuts down only what it
|
|
booted), `android-emu` (demo-mode status bar, per-app language, `am start` with deep links / extras, screencap; never
|
|
boots, wipes or reboots), `folder` (your own frames, checked for aspect and size). Status bar cropped per device
|
|
class. `--dry` prints every simctl / adb command.
|
|
- **13" iPad** end to end with `apple.ipad: true`: `ipad13` size (2064 x 2752, 3:4 layout), iPad frame defaults, the
|
|
`APP_IPAD_PRO_3GEN_129` set in `apple screenshots`, required by `validate`.
|
|
- **Store rules as data** (`cli/shots/spec.ts`, sources cited): pixel sizes per store type, alpha, Play JPEG / 24-bit
|
|
PNG and 8 MB, counts per set, feature graphic, app preview rules. Used by the new `shots check` (local, exit 1 on
|
|
errors, `--variants`, `--json`) and by `validate` (local renders become blockers next to the store state).
|
|
- **`shots gallery`**: one self-contained `index.html` next to the renders (no network): every language x size x
|
|
scene, app previews with posters, variant tabs, filters, light / dark, issues outlined with their message.
|
|
- **A/B variants**: `shots.variants` (scene order / subset, copy overrides, palettes) rendered with
|
|
`shots render --variant b | --variants`, the feature graphic included; `--variant` on `play images`,
|
|
`apple screenshots` and `shots jpeg`. The skill explains Play store listing experiments and App Store Product Page
|
|
Optimization and what stays manual there.
|
|
- **App previews and promo video**: `shots record` (web via Chromium screencast, `simctl io recordVideo`, `adb
|
|
screenrecord`, or a folder of clips), `shots video` (886 x 1920 iPhone, 1200 x 1600 iPad, YouTube 9:16 / 16:9,
|
|
captions from the screenshot copy in every script, silent or music track, poster, ffprobe checks),
|
|
`apple previews` (preview sets per locale, MD5-idempotent, poster frame time code, files checked before upload),
|
|
`play listing` sends `play.video` (Play takes a YouTube URL, no upload).
|
|
- Contact sheet packed into a grid; Play 7" / 10" tablets drawn in an Android tablet body.
|
|
- **MCP**: `shots_check` (read-only), `shots_capture`, `shots_render`, `shots_gallery`, `shots_record`, `shots_video`
|
|
(local files, dry run by default), `apple_previews` (dry run by default); `variant` on the upload tools.
|
|
- **Skills**: new `app-previews`; `store-screenshots` covers sources, iPad, checks, gallery, variants, experiments and
|
|
the iPhone display class Apple now marks as required (6.9" stays the default, scaled down by Apple).
|
|
- **Demo game** `examples/demo-game/` ("Prism Puddle", fictional, procedural art) that storebound renders for the
|
|
showcase in this README; `--dry` on `shots render`, `shots video`, `shots gallery`.
|
|
- README rewritten; `CONTRIBUTING.md`, `SECURITY.md`. Playwright stays a dev dependency; runtime dependencies stay 0.
|
|
|
|
## 0.2.0 · 2026-10-10
|
|
|
|
Works with any AI coding tool now, plus the release and review side of shipping.
|
|
|
|
- **One source, many tools**: skills stay plain Agent Skills (`name` + `description` only); `tools/gen-adapters.ts`
|
|
writes the Claude Code plugin + `.mcp.json`, Codex plugin, Gemini CLI extension + `GEMINI.md`, `AGENTS.md`,
|
|
`.github/copilot-instructions.md` and a Cursor rule. CI fails when they are stale. Shared agent rules in
|
|
`docs/agents-core.md`.
|
|
- **`storebound mcp`**: stdio MCP server (2025-11-25), one tool per command, write tools dry run by default, nothing
|
|
public or irreversible exposed. No SDK, still zero runtime dependencies.
|
|
- **`storebound install --agent claude|codex|cursor|copilot|windsurf|gemini|opencode`**: skills + MCP entry into a
|
|
game project, idempotent, never touches other entries, `--dry`.
|
|
- New commands: `validate` (read-only readiness report for both stores, ordered blockers, exit 1),
|
|
`apple release --phased on|pause|resume|complete` and `--manual-release`, `apple status --wait-review`
|
|
(exit 0 / 1 / 7), `apple next-build`, `apple encryption`, `play rollout --fraction|--halt|--resume|--complete`,
|
|
`play next-version-code`, `check --aso`, `whats-new --since <tag>`, `privacy-manifest --ios <path>`, `version`.
|
|
- New skills: review-rejections, portfolio-originality, release-management, store-preflight, privacy-manifest,
|
|
export-compliance, aso-basics, whats-new.
|
|
- Updated skills: select builds by explicit number, first availability record UI fallback, phased + manual release
|
|
by default, IAP versions in review submissions (API 4.4.1, reported, verify), privacy manifest cross-links, tool-neutral
|
|
CLI instructions.
|
|
- Fix: Apple IAP description limit is 45 characters (App Store Connect Help), not 55.
|
|
- Config: `apple.usesNonExemptEncryption`, `apple.screenshotTypes`, `ads.appAdsTxt`.
|
|
- `bun run ci`: adapters check, tests, typecheck, secrets / personal data scrub.
|
|
|
|
## 0.1.0 · 2026-10-10
|
|
|
|
First public cut, extracted from the scripts I used to ship my own game.
|
|
|
|
- `storebound` CLI: `init`, `check`; Play `products`, `listing`, `images`, `data-safety`, `release`, `status`;
|
|
App Store `bundle`, `iap`, `iap-review`, `listing`, `screenshots`, `appinfo`, `review-details`, `status`
|
|
(incl. canceling a review submission); `icons`; `shots capture | fonts | render | jpeg`.
|
|
- Per-project `storebound.config.ts`; credentials only from env or `.storebound/credentials.json`.
|
|
- Claude Code plugin + marketplace with 8 skills: play-first-release, appstore-first-release, store-iap-setup,
|
|
store-screenshots, app-icons, store-declarations, privacy-policy, ads-levelplay-checks.
|
|
- Templates: config, Play + App Store listing copy, screenshot copy (5 languages incl. Arabic + Japanese), Data
|
|
safety CSV, App Privacy answers, Play declarations, studio-wide privacy policy page.
|
|
- Tests for config validation, copy parsing, Data safety CSV, price mapping, script fonts, args.
|