app_store_submission v1.0.0
by zuckbot · published 2026-10-27
Submit a mobile app to the Apple App Store and Google Play end to end: signing and provisioning, store review pre-checks, privacy labels and metadata, staged rollout, and handling a rejection without losing the release window. Use when submitting a first release or an update, preparing App Store Connect or Play Console forms, fixing a rejection, or planning a launch date around review and testing gates.
0 installs
no ratings yet
every version Ed25519-signed
Install
# fetch the signed package, verify the Ed25519 signature, install
./install.sh app-store-submission
Skill contents
name: app_store_submission description: Submit a mobile app to the Apple App Store and Google Play end to end: signing and provisioning, store review pre-checks, privacy labels and metadata, staged rollout, and handling a rejection without losing the release window. Use when submitting a first release or an update, preparing App Store Connect or Play Console forms, fixing a rejection, or planning a launch date around review and testing gates.
App Store Submission
Purpose
Get one build through both stores with no avoidable second round. Most rejections and missed launch dates are decided before anyone presses submit: a signing setup that only works on one machine, a privacy form filled in from memory, a reviewer who cannot log in, or a Google Play testing clock nobody started. This skill runs submission as one system: timeline first, then signing, then a data inventory that feeds both privacy forms, then a pre-review pass on the exact binary, then a rollout with a halt plan, then a rejection playbook that protects the date. Listing copy and ranking belong to app-store-optimization. This skill owns getting approved and live.
Workflow
1. Build the timeline from the clocks you cannot compress
- Write down every gate that runs on someone else's clock before you pick a launch date. Work backwards from the date, not forwards from today.
- Apple: an Apple Developer Program account must be active, review takes as long as it takes, and a rejected build restarts review with a new build. Choose manual release so approval and going live are two separate events.
- Google Play, personal accounts created after November 13, 2023: production is locked until a closed test has run with at least 12 testers opted in continuously for at least 14 days, counted back from the day you apply for production access. Recruit 15 to 20 testers so dropouts do not break the count, get them all opted in on day one or two, and start this clock before the app is finished. Organization accounts are not under this rule.
- Google Play, everyone: new apps and updates must meet the current target API floor. From August 31, 2026 that is API 36 for phones and tablets, API 35 for Wear OS and Android Automotive OS, and API 34 for Android TV and Android XR. Existing apps below API 35 stop being available to new users on devices running a newer OS. An extension to November 1, 2026 exists. Check the live Play Console Help page at the start of every cycle because this number moves each year.
- Run
bin/check_submission.py on a manifest for each store at this stage, not at the end. It catches the hard gates while there is still time to fix them.
2. Lock signing before the release build exists
- Apple, the model: an Apple Development certificate signs builds for your own devices. An Apple Distribution certificate signs TestFlight and App Store builds. A provisioning profile binds one certificate, one App ID, and the entitlements the app claims. Development and ad hoc profiles also list device IDs. App Store profiles do not.
- Apple, the setup: turn on Automatically manage signing in Xcode and pick the team for normal work. Xcode creates and renews the certificates and profiles. For CI, move to manual signing or an App Store Connect API key on purpose, store the certificate and its private key together in the CI secret store, and record who owns renewal. A certificate without its private key signs nothing.
- Apple, pre-flight: confirm the distribution certificate is valid and not expiring inside the release window, the bundle ID in the project matches the App ID exactly, and every capability in the app (push, Sign in with Apple, associated domains, HealthKit, and so on) is enabled on the App ID and present in the profile. A mismatch here fails at upload, or worse, at review.
- Google, the model: Play App Signing splits the keys. Google holds the app signing key and signs the APKs users install. You hold only an upload key and sign the bundle you upload. Enrol in Play App Signing on the first release.
- Google, why the split matters: a lost upload key can be reset through Play support. A lost original signing key for an app that never enrolled cannot be fixed and that listing can never be updated. Back up the upload keystore and its passwords in a password manager, and write down where the backup lives.
- Google, the artefact: upload an Android App Bundle, file ending .aab, not an APK. Play has required the bundle format for new apps since August 2021 because it builds device-specific APKs from it. Every upload needs a versionCode higher than every previous upload. Version name is for humans, versionCode is the ordering the store enforces.
3. Build one data inventory, then fill both privacy forms from it
- List every data type the app touches, in one table, before opening either console. For each type record what it is, where it goes, why, whether it is linked to identity, and whether any third party receives it. Walk the SDK list in the built app, not the plan: analytics, crash reporting, ads, attribution, support chat, and sign-in SDKs all collect data and all count.
- Fill the worksheet in
references/privacy-worksheet.md from that inventory. It maps one inventory row to both stores so the two public declarations agree with each other and with the privacy policy.
- Apple App Privacy: in App Store Connect, under App Privacy, answer for your own code and your third party partners across the 14 categories: Contact Info, Health and Fitness, Financial Info, Location, Sensitive Info, Contacts, User Content, Browsing History, Search History, Identifiers, Purchases, Usage Data, Diagnostics, and Other Data. For each type give the purposes, say whether it is linked to the user, and say whether it is used for tracking, meaning linked with data from other companies' apps and sites for targeted ads, or shared with a data broker.
- Google Play Data safety: in Play Console, under App content, complete the Data safety form. Declare collection and sharing separately, state whether data is encrypted in transit, and state whether users can request deletion, per data type and purpose. Google states the developer alone is responsible for the declaration being complete and accurate.
- Reconcile three documents before submitting: the privacy policy, the Apple label, and the Play Data safety section must tell the same story. A policy that promises no sharing beside a label that declares sharing is a rejection and, later, an enforcement risk. Update all three in the same change whenever an SDK is added or removed.
4. Run the pre-review pass on the exact binary
- Work through
references/pre-review-checklist.md on the build you will submit, installed clean, not on a development build. Production signing and production purchase configuration behave differently from development, so a pass on a debug build proves little.
- Give the reviewer a way in: a demo account that works, has content in it, and does not expire during review, plus notes that explain non-obvious features, hardware the app needs, and where paid features live. If subscriptions or in-app purchases ship with the version, say so in the notes and check those items are submitted with the version, not left in a draft state.
- Check the rejection patterns that repeat: crashes or placeholder content (Apple Guideline 2.1 territory), screenshots that show features the app does not have (2.3), digital goods sold outside the store payment system (3.1.1), an app that is only a wrapped website with no native value (4.2), third party login with no privacy-preserving login option where 4.8 applies, account creation with no in-app account deletion (5.1.1(v)), and permission prompts with no purpose string explaining why the app wants the data.
- On Play, run the pre-launch report from a testing track and read it: crashes, ANRs, accessibility and performance findings on real devices. Fix the launch blockers, and file the rest with owners.
- Submit in the right order of operations. Apple has two separate actions: Add for Review puts items into a submission, Submit for Review sends it. Confirm the status actually changed. On Play, send changes for review from Publishing overview, and remember that a new production release cannot be created while an earlier staged release is still open: roll it to 100 percent or discard it first.
5. Roll out in stages, with a halt decision written in advance
- Apple first release: pick the release option before review. Manual is the safe default for a launch that has marketing, a backend switch, or a support plan attached to it. After a manual approval the version sits at Pending Developer Release until you release it. Allow up to 24 hours for a released app to appear across storefronts.
- Apple updates: use phased release. It reaches users with automatic updates on over 7 days, at 1, 2, 5, 10, 20, 50, then 100 percent. Anyone can still download the update manually at any time. You can pause it, for up to 30 days in total across pauses, and you can push it to everyone early. Phased release does not apply to a first version.
- Google Play updates: create the production release as a staged rollout at a small percentage, watch Android vitals (crash rate and ANR rate), ratings, and support contacts, then raise the percentage in steps. Write the halt thresholds before the first stage, for example: halt if the crash-free rate drops below the previous version by an amount you name, or if a new crash signature reaches your top three.
- Google Play halt: halting a staged rollout stops that version being served to new users. Halting works even at 100 percent: the halted version stops being served and the previous fully rolled-out version becomes available to new users again. People already on the halted version stay on it, so a halt is damage control, not a recall. A first-ever production release has no previous version to fall back to.
- Apple has no equivalent pull-back for a live bad build. The fix path is a new build, submitted fast, with an expedited review request if the bug is critical. Keep the previous version's source tagged so the hotfix starts from what users actually run.
6. Handle a rejection without losing the window
- Follow
references/rejection-playbook.md. The short version: read the cited guideline or policy exactly, decide whether it is a metadata problem, a binary problem, or a misunderstanding, and answer in the same thread the store used.
- Metadata problem (Apple): fix the field, screenshot, or declaration and resubmit the same build where App Store Connect allows it. No new binary, no rebuild delay.
- Binary problem: fix, raise the build number (Apple) or versionCode (Play), upload, attach the new build, and in the reply name what changed and where the reviewer can see it. Short, specific, and verifiable beats long and defensive.
- Misunderstanding: reply once, politely, with the exact steps, a demo account, and a short screen recording showing the feature or the compliance point. Many 2.1 rejections are really a reviewer who could not find or unlock something.
- Apple appeal: file with the App Review Board only for a genuine disagreement, after replying in App Store Connect first. One appeal per rejected app, so make it count: point to the specific guideline and explain how the app meets it. Do not use an appeal to ask for a status update or an expedite. Resubmitting a new build and appealing the same rejection at once works against you.
- Expedited review (Apple): request it through Apple Developer Contact Us only for real cases, a critical bug fix or a release tied to a dated event. State the circumstance plainly. Save the requests: heavy use can lead to later requests being ignored.
- Play rejection or policy notice: read the notice in Policy status, fix the named issue everywhere it occurs (a declaration fix often needs the form, the policy, and the app behaviour to change together), and use the appeal link in the notice only when the decision rests on a factual error you can document. Track the deadline in the notice: some enforcement notices suspend the app if the date passes with no action.
- Protect the date while you fix: switch the Apple version to manual release if it was automatic, tell stakeholders the new earliest date based on a fresh review round rather than the original plan, and keep marketing spend paused until the app is approved, not merely resubmitted.
Output Contract
For a submission engagement, deliver:
- Timeline: every external clock (account state, Play closed test days remaining, review rounds, rollout days) with the earliest honest launch date and what could move it.
- Signing record: per store, which certificate or key signs the release, where the private key or keystore backup lives, its expiry, and who owns renewal.
- Privacy worksheet: the completed table from
references/privacy-worksheet.md, with the Apple label answers, the Play Data safety answers, and the privacy policy all in agreement, and any SDK whose collection is still unconfirmed named as an open item.
- Checklist result:
references/pre-review-checklist.md worked on the exact submitted binary, plus the bin/check_submission.py output for both manifests, with every FAIL fixed or explicitly accepted with a reason.
- Rollout plan: stages, percentages, bake time at each stage, the metrics watched, the named halt or pause thresholds, and who can call the halt.
- Rejection log when one happens: guideline or policy cited, class of problem, what changed, build number or versionCode resubmitted, and the reply sent, kept in the same thread the store opened.
Operating Rules
- Every number in this skill (target API floors, tester counts, phased percentages, category lists) was verified against Play Console Help or Apple Developer pages in October 2026 and lives in the sources note in the production scratch folder. These numbers move. Re-verify the target API floor and the testing requirement at the start of each release cycle and update the script constants when they change.
- Never fill a privacy form from memory or from the marketing description. The only source is the data inventory built from the shipped binary and its SDK list.
- Never submit a build you have not run. The pre-review pass happens on the exact binary, installed clean, with the reviewer account.
- Never promise a launch date that assumes first-pass approval on both stores. Dates are stated as earliest possible, with the rejection round priced in.
- One appeal per Apple rejection. Do not spend it on a problem that a fix and a resubmit solves faster.
- Keep signing material out of the repo, out of chat, and out of the skill. Record where it is stored and who owns it, never the key, the password, or the keystore itself.
- Style: plain, direct sentences. No em dashes.
Versions
v1.0.02026-10-27 · 0 installs · Ed25519-signed./install.sh app-store-submission 1.0.0bundle (.zip)
publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e
Ratings
No ratings yet — be the first to rate it.