Commit graph

91 commits

Author SHA1 Message Date
CRT
77aa09235e storebound api: every App Store Connect and Google Play operation
- specs/: Apple's App Store Connect OpenAPI 4.5.1 and the Google discovery docs for androidpublisher v3 and
  playdeveloperreporting v1beta1, pinned with URL, date and SHA-256 (specs/SOURCES.json)
- tools/gen-api.ts: one row per operation (cli/api/apple.gen.ts 1303, cli/api/play.gen.ts 170), a scan of which
  operations the commands already call (cli/api/wrapped.gen.ts) and docs/api-coverage.md; CI checks freshness
- cli/api/client.ts + types.ts: generic URL / parameter building, retries with Retry-After, pagination, types derived
  from the rows; auth reuses ascJwt and the Play service account
- cli/api/gate.ts: GET runs, writes dry unless --yes in a TTY, owner-only operations need the id typed, nothing
  written under MCP or serve; MCP gets the read-only api_get
- storebound api list | coverage | apple|play <op|METHOD path>; skill store-api, README, CHANGELOG, tests
2026-10-11 23:37:09 +08:00
CRT
54dd012cfa Merge cli-workspace: multi-app workspace, credential profiles, release trains in the CLI and MCP
# Conflicts:
#	.cursor/rules/storebound.mdc
#	.github/copilot-instructions.md
#	AGENTS.md
#	CHANGELOG.md
#	GEMINI.md
#	docs/agents-core.md
2026-10-11 23:36:36 +08:00
CRT
2165322c02 CLI workspace for many apps and studios, credential profiles, release trains (release status / plan)
- storebound.workspace.json: app folders (globs), studios with accounts by credential profile, ignore list, the
  desktop's pairing overrides; ws init | list | status | check | validate | run | apps import | desktop export/import
- credential profiles in ~/.storebound/credentials/<profile>.json or env, --account <profile> on any command
- release status / release plan <version>, table or --json; MCP workspace_list, workspace_status, release_status,
  release_plan (read-only)
- pairing rules (cli/lib/identity.ts), release lanes (cli/lib/train.ts) and the per-app status read
  (cli/lib/app-status.ts) shared with the desktop instead of copied
- tests with sanitized fixtures, README, skills, CHANGELOG
2026-10-11 23:35:45 +08:00
CRT
ae58948abd storebound scan: offline rejection-risk scan of the project itself
Detects the stack (native iOS / Android, React Native, Expo, Capacitor, Cordova,
Flutter, Unity, Godot) and the SDKs from a maintained table with versions,
file:line and each vendor's disclosure page, then reports App Store and Google
Play rejection risks with guideline, evidence, fix, severity and skill: 2.1(a)
demo account and placeholder text, 5.1.1(v) account deletion, 4.8 login
services, 3.1.1 restore and outside payments, 3.1.2 subscription info, 5.1.2(i)
ATT, purpose strings, privacy link, privacy manifest, 2.3.10, 2.3.7, 2.3.8, 4.2
web wrappers, 2.5.1, 2.5.5, ATS, export compliance, 1.3 kids ads, review
prompts, privacy labels vs SDKs; Play target SDK 36, delete-account URL, App
access, foreground services, exact alarms, QUERY_ALL_PACKAGES, SMS / call log,
com.example package name.

Proposes Data safety / App Privacy / ATT / privacy manifest answers (detected
file:line or ask owner) as a diff against the config; --write adds only the
detected ones. scan.ignore records owner-accepted findings. MCP tool scan
(read-only), validate includes open findings, desktop Checks tab shows them.
Fixtures for iOS, Android, Capacitor, Unity, Flutter, clean and teaser.
2026-10-11 23:20:55 +08:00
CRT
f9a53f508e tools: also look in the Android SDK folder Android Studio installs and in Homebrew, for apps started without a shell PATH 2026-10-11 09:51:22 +08:00
CRT
b4d924b132 Guarded read-only run of the Play POST read paths: errorIssues:search in UTC, issues failure keeps the vitals, read-only listing / images dry runs
A live run where only the token exchange, edit insert / delete and Reporting :query were let through:
- health / validate: errorIssues:search answered 400 "Unsupported timezone" for America/Los_Angeles (it takes
  hour-aligned UTC only); the failure dropped the crash and ANR rates and the reason was cut off in the query string.
  Issues are asked in UTC; a failing issues search is a vitals-issues warning; Reporting errors leave out the query.
- play listing --dry / play images --dry wrote into the edit (PUT details and listings, image clears and uploads,
  :validate) before discarding it. Now one throwaway edit is read (details, listings, image sha256) and compared
  with the local copy, then deleted.
- play.read(): one helper for read-only edits (status, next-version-code), always deleted, warns if the delete fails;
  next-version-code counts distinct codes.
- tests on sanitized recorded answers (tests/play-post-reads.test.ts)
2026-10-11 08:41:55 +08:00
CRT
5d485e01b5 Real-account read check of the desktop tabs: analytics snapshot stops when every store failed, compare names why a store has no days (Growth shows it), listing screenshot count skips contact sheets; Growth chart as an index on one axis; recorded price answers round-trip the price sheet 2026-10-11 08:06:26 +08:00
CRT
be38af2dad Merge desktop-complete: prices, app info, growth, store art, exports, onboarding, UX audit 2026-10-11 07:49:56 +08:00
CRT
513c33330d serve: every CLI area for the desktop app (prices.current, project.declarations / listing_text / renders / render, import.fastlane for a new folder; owner.prices_import, owner.ppo_start / stop)
prices export --json reads the current prices without writing; inspect --declarations gives Data safety, the App
Privacy answers it suggests, app info, export compliance and App Review details with every question only the owner
can answer; play data-safety keeps the uploaded CSV in .storebound/ so changes since the upload show (Play cannot read
the form back); shots gallery --json carries the renders folder; inspect --render returns one render as a data: URL
from inside the renders folder only.
2026-10-11 07:40:59 +08:00
CRT
d26244fdc9 store-locales: verify App Store and Play codes against the official lists (2026-10-11), drop zu, aliases for the 2025 languages, tests 2026-10-11 07:37:18 +08:00
CRT
1637765c6f Merge desktop-d5: desktop release pipeline, updater, privacy gate, storebound desktop
# Conflicts:
#	CHANGELOG.md
2026-10-11 05:25:54 +08:00
CRT
10423ae915 storebound desktop: open the desktop app (with the current app folder) or show the download for this system; --download saves it to ~/Downloads after checking SHA-256 and the minisign signature, never installs 2026-10-11 05:16:59 +08:00
CRT
72dda418ea Merge fastlane-import: storebound import fastlane
# Conflicts:
#	CHANGELOG.md
2026-10-11 05:06:15 +08:00
CRT
de681dd967 import fastlane: config, App Store and Play listings, languages and screenshot frames from a fastlane setup
storebound import fastlane [--dir] [--out] [--profile] [--dry] (MCP import_fastlane, dry run by default) reads
Appfile / Deliverfile plain option lines, deliver and supply metadata and screenshots, and writes
storebound.config.ts, store/appstore.md, store/listing.md, the Play icon and feature graphics, and frames with a
folder capture source. App Store and Play language codes are paired (cli/lib/store-locales.ts). Existing files are
never overwritten (.imported copies with a diff hint); keys, team ids, the review contact and demo account are only
named in the report. Fixture tests/fixtures/fastlane-sample, skill migrate-from-fastlane, README and CHANGELOG.
2026-10-11 04:57:03 +08:00
CRT
44e64cf9c6 apps / health / catalog / validate: fixes from a read-only run against live store accounts
- API error bodies on one line (errorBody): Google and App Store Connect pretty-print errors, which hid
  SERVICE_DISABLED from the Play account check (reported permission instead of api-disabled), broke tables
  and turned serve's apps.list error into a JSON fragment
- apps list: failure says the reason and the fix (same words as apps check)
- newest App Store version by createdDate, iOS first (the API groups versions by platform); all versions
  read so no platform is missed; per-app reads four at a time
- apps check (apple): team app count from meta.paging.total with a one-app read
- Play Money without units (prices under 1.00) read as 0.xx, not NaN (catalog diff, subscription diffs)
- health: App Store Connect 404 for perfPowerMetrics / diagnosticSignatures means no field data yet;
  Play vitals behind a disabled Reporting API say so with the fix
- validate: gracRatingClassificationNumber optional, socialMediaAgeRestricted only when socialMedia is yes,
  socialMedia unanswered is a warning
- tests with sanitized recorded responses (tests/store-real-shapes.test.ts)
2026-10-11 04:50:26 +08:00
CRT
f106ec4423 Merge desktop-d3: studios and accounts, store import, pairing, ignore list, settings, confirm-gated writes 2026-10-11 04:33:03 +08:00
CRT
f47c00bed0 D3 writes: owner actions (Play rollout share / halt / resume / complete, iOS phased release, send one approved reply) answer the command's confirmation only with a verified host token; reviews reply edits a draft; native dialog names owner actions; token binding tests for every write the window offers 2026-10-11 04:19:47 +08:00
CRT
c2cb428413 check: name the missing file and the fix instead of a raw ENOENT; clearer demo account message; hero shows the new output 2026-10-11 03:54:03 +08:00
CRT
53f9e6dd75 CLI: storebound apps list | check (apps on a store account, account health with fixes); serve apps.list, account.check and store-only apps through a generated config 2026-10-11 03:53:52 +08:00
CRT
0ace432e87 CLI for desktop D2: doctor, inspect --icon / --listings, reviews drafts / approve, init --dry from embedded templates, iOS phased release share, playwright as optional peer (sidecar bundles playwright-core) 2026-10-11 03:34:45 +08:00
CRT
94d2f3d6ca Desktop: adapt to 0.5.0 (app.platforms, subscriptions, catalog diff), Dependencies polish, ~ for the home folder
- inspect reports platforms, subscription ids and the catalog each store should sell; app identity
  and parity follow app.platforms and per-item platforms; catalog.diff joins the JSON methods
- Portfolio: one Platforms column, compact catalog, paths truncated and shown with ~; the confirm
  dialog and run logs show ~ instead of the home folder
2026-10-11 02:15:48 +08:00
CRT
ab13d95898 serve: app-centric portfolio (apps across iOS / Android, release trains, catalog parity) and local tool detection
- portfolio.status returns apps: identity with both platforms, offline config check, release trains
  (current = highest version live on a store, next = highest above it; per-store phase, build,
  rollout fraction) and catalog parity (config vs both stores) when live
- inspect --json adds product ids and the subscription count
- system.tools: ffmpeg, ffprobe, Chrome / Chrome for Testing, Xcode tools, simctl, adb, git with
  versions and source; STOREBOUND_TOOL_PATH (front of PATH for every command) and STOREBOUND_CHROME
  (Playwright executablePath) let the desktop app hand over its own copies
2026-10-11 01:57:33 +08:00
CRT
d74d99bcc9 serve --stdio: desktop JSON-RPC profile on the MCP core, confirm tokens, --json results, sidecar builds
- 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
2026-10-11 01:57:33 +08:00
CRT
c48eead0e0 0.5.0: mobile apps and games positioning (README, site, og image, skills, CLI, MCP, adapters), MCP tools for subscriptions and catalog diff, tests, changelog 2026-10-11 01:47:09 +08:00
CRT
44699eac8c Full IAP catalog: non-renewing products, per-platform availability, catalog diff (cross-store parity report) 2026-10-11 01:47:08 +08:00
CRT
162834444a Subscriptions on both stores: Apple groups, levels, equalized prices, intro and promotional offers, offer codes; Play base plans, regional prices, offers 2026-10-11 01:47:08 +08:00
CRT
20c0221b1d Review access and account deletion: demo account from .storebound (masked) to App Review, accounts config, profile checks in check and validate, Data safety extra rows 2026-10-11 01:47:08 +08:00
CRT
d3cc7e43d4 Product Page Optimization through the API (apple ppo) and an optional 6.3" iPhone size key
apple ppo status | create --variant b[,c] | upload --variant b | start | stop: v2 experiments (platform IOS, traffic
proportion), one treatment per shots variant (max 3), a treatment localization per App Store locale, and the variant
renders synced into the treatment screenshot sets (shared MD5-idempotent set sync with apple screenshots, which no
longer creates sets on --dry). start / stop ask first and are not MCP tools; MCP: apple_ppo_status, apple_ppo_create,
apple_ppo_upload. Play experiments stay console-only (documented).
apple.iphoneMedium (off by default): iphone-medium size key, 1206 x 2622 (1179 x 2556 accepted), uploaded as
APP_IPHONE_61; rendered, checked, required and uploaded only when enabled. Apple's scaling rule documented in the config
and the store-screenshots skill.
2026-10-10 23:28:10 +08:00
CRT
952a3a6e37 Analytics snapshots: storebound analytics setup | snapshot | compare, store-analytics skill
App Store Connect Analytics Reports API (ONGOING request, Discovery and Engagement + Downloads Standard reports,
daily instances, md5-checked gzip segments, newest processing per day) and the Play statistics exports in the
pubsite_prod_rev_ Cloud Storage bucket (UTF-16 CSV, store listing visitors / acquisitions, daily user installs;
play.reportsBucket). Snapshots in .storebound/analytics/<date>.json; compare lines them up with the git history of the
store files (7 days before vs after each change). MCP: analytics_snapshot, analytics_compare, analytics_setup.
2026-10-10 23:28:10 +08:00
CRT
104cd79117 Price sheet: storebound prices export | import (CSV of product x store x region)
export reads the current App Store manual (and with --with-automatic the equalized) prices and the Play purchase
option regional prices into one CSV. import parses and checks the sheet, prints a diff table (change %), and after a
confirmation writes one App Store price schedule per changed product (base territory + every manual price, future-dated
changes via start_date, price point ids looked up per territory) and the Play regional configs (CSV over current,
convertRegionPrices for regions without a price, --reconvert). MCP: prices_diff (read-only), prices_export; applying
stays a terminal command. store-iap-setup skill: price sheet section.
2026-10-10 23:28:10 +08:00
CRT
c99febc45b Review replies: storebound reviews list | draft | send, review-replies skill
App Store customerReviews / customerReviewResponses and Google Play reviews.list / reviews.reply. draft writes one
Markdown file per unanswered review to .storebound/replies (front matter approved: false, never overwritten); send
only sends approved, unsent drafts that pass the checks (Play 350 characters, no incentives or rating requests,
personal data / link / tone warnings) after a confirmation, and marks them sent. MCP: reviews_list, reviews_draft;
send is never exposed.
2026-10-10 23:28:10 +08:00
CRT
56e107dbbe Crash and vitals health: storebound health [--weekly], validate findings, store-health skill
Play Developer Reporting API v1beta1 (crashRateMetricSet / anrRateMetricSet DAILY queries in America/Los_Angeles,
user-perceived 28-day rates, worst device models, errorIssues:search) and App Store Connect perfPowerMetrics,
diagnostic signatures and TestFlight crash submissions. Thresholds 1.09 % crash / 0.47 % ANR / 8 % per device
(developer.android.com/topic/performance/vitals): over = blocker, from 80 % = warn, in validate too (--no-health).
Weekly Markdown report with week-over-week change in .storebound/health/. MCP: health (read-only), health_report.
2026-10-10 23:28:10 +08:00
CRT
3f12452e3f TestFlight through the App Store Connect API: apple testflight status | groups | testers | what-to-test | info | distribute
Beta groups from apple.testflight.groups (created when missing, never changed), testers from a CSV in .storebound/
(masked in logs, confirmation before Apple emails invitations, --remove / --invite), What to Test per locale from the
App Store listing (whatToTest or whatsNew), Test Information and Beta App Review details, builds by exact number to
groups, Beta App Review submission behind --submit-review and a confirmation. Pure planners in cli/lib/testflight.ts,
shared CSV / table / JSON:API helpers. MCP: apple_testflight_status, _groups, _what_to_test, _info, _distribute
(internal groups only). Skill testflight.
2026-10-10 23:28:10 +08:00
CRT
ea18406712 shots record: gameplay clips from a web build (Chromium screencast), iOS Simulator, Android emulator or a folder 2026-10-10 22:22:52 +08:00
CRT
aecdcb1c50 Store image checks in shots check and validate
- Apple sizes accepted portrait or landscape; Play screenshots any accepted size (320-3840 px, at most 2:1);
  Play rejects 16-bit PNGs; feature graphic exactly 1024 x 500
- Required sets per language (Apple only with an App Store locale, Play only with a Play code)
- shots check scans A/B variant folders only with --variants
- validate adds the local renders checks: store errors are blockers, overflow flags warnings (--no-local skips)
2026-10-10 21:54:47 +08:00
CRT
3d257402cc 13" iPad end to end: frame defaults with apple.ipad, per-device crop, iPad display set, simulator warm-up
- Tablet frames default to the 13" iPad screen (1032 x 1352 @2x below a 24 px bar) when apple.ipad is set
- shots.capture.cropTop takes a number or { phone, tablet }; default is the frame's bar share per device class
- capture warns when a cropped frame does not match the frame aspect
- apple screenshots uploads ipad13 as APP_IPAD_PRO_3GEN_129 only with apple.ipad; validate requires it then
- ios-sim: one warm-up launch after a cold boot (ios.warmupMs, default 8000) so the first frame is not blank
2026-10-10 21:54:47 +08:00
CRT
8a4083d9fd Screenshot pipeline groundwork: capture source config, device builders, store specs, checks, variants, video builders
Salvaged from wip/shots-pipeline. Pure modules (spec, devices, report, video,
check), variant support in render / lib, 13" iPad size and 3:4 template layout.
Not all of it is wired into the CLI yet.
2026-10-10 21:30:40 +08:00
CRT
03a95d2c0a MCP server and install --agent for any AI coding tool
- storebound mcp: stdio MCP server (spec 2025-11-25, tools only), one tool per command, write tools
  dry_run by default, readOnly/destructive/idempotent/openWorld annotations; submit, release,
  rollout, cancel and delete are not exposed. Own JSON-RPC subset, no SDK, zero runtime deps.
- storebound install --agent claude|codex|cursor|copilot|windsurf|gemini|opencode: copies the skills
  and adds the storebound MCP entry (.mcp.json, .codex/config.toml, .cursor/mcp.json, .vscode/mcp.json,
  Windsurf mcp_config.json, .gemini/settings.json, opencode.json). Idempotent, keeps other entries, --dry.
2026-10-10 21:03:10 +08:00
CRT
1fc94da443 CLI: store readiness, release management, export compliance, ASO audit, release notes, privacy manifest scan
- validate: read-only App Store Connect + Play report with ordered blockers (exit 1)
- apple release --phased on|pause|resume|complete and --manual-release (asks first)
- apple status --wait-review (exit 0 approved, 1 rejected, 7 timeout), 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
- Apple IAP description limit is 45 characters (App Store Connect Help), not 55
- config: apple.usesNonExemptEncryption, apple.screenshotTypes, ads.appAdsTxt
2026-10-10 21:02:55 +08:00
CRT
11c45efab8 Rename to storebound (plugin, CLI, config file, credentials folder, repo) 2026-10-10 20:35:26 +08:00
CRT
3cd31b7601 crt-ship 0.1.0: CLI, Claude Code skills and templates for shipping mobile games to Google Play and the App Store 2026-10-10 20:29:20 +08:00