references/app-privacy.md
# App Privacy publish state
Read this reference only when readiness validation reports an App Privacy advisory or the public API cannot confirm the published state.
The public App Store Connect API does not cover the full App Privacy workflow. Treat the following commands as authenticated web-session automation, not public-API proof.
## Inspect and plan
Pull the current answers into a reviewable file:
```bash
asc web privacy pull --app "APP_ID" --out "./privacy.json"
```
Review the planned change before writing:
```bash
asc web privacy plan --app "APP_ID" --file "./privacy.json"
```
Check every data type, purpose, tracking answer, and linkage answer against the app's real behavior and third-party SDKs. Do not infer privacy answers from the binary name or store copy.
## Apply and publish
Apply the reviewed file:
```bash
asc web privacy apply --app "APP_ID" --file "./privacy.json"
```
Publish only after the applied answers have been checked:
```bash
asc web privacy publish --app "APP_ID" --confirm
```
Keep the plan and apply steps separate. A successful apply does not prove that the answers were published.
## Manual fallback
If the user declines web-session automation, open the app's App Privacy page and confirm the published state manually:
```text
https://appstoreconnect.apple.com/apps/APP_ID/appPrivacy
```
Report the boundary plainly: the public API readiness report can raise an advisory, while final publish-state verification requires the web flow or a manual check.
references/digital-goods.md
# Digital-goods readiness
Read this reference only when IAP or subscription validation fails, Apple requires a first-review attachment, or a versioned product must join an existing review submission.
When work starts from an existing review draft, preserve its `SUBMISSION_ID` in the handoff to `asc-release-flow`. The release flow must inspect and reuse that draft rather than create another submission.
## Contents
- [Run product validators](#run-product-validators)
- [Attach subscriptions for first review](#attach-subscriptions-for-first-review)
- [Prepare a subscription version](#prepare-a-subscription-version)
- [Prepare a subscription-group version](#prepare-a-subscription-group-version)
- [Prepare an IAP version](#prepare-an-iap-version)
- [Handle first-version IAP attachment](#handle-first-version-iap-attachment)
## Run product validators
Start with the relevant validator:
```bash
asc validate iap --app "APP_ID" --output table
asc validate subscriptions --app "APP_ID" --output table
```
Use JSON when automation needs the exact diagnostic payload:
```bash
asc validate subscriptions --app "APP_ID" --output json --pretty
```
Fix missing localization, pricing, availability, review screenshots, and promotional images before attaching products to review.
## Attach subscriptions for first review
The public API cannot perform the first-review subscription selection. Inspect the web-session state:
```bash
asc web review subscriptions list --app "APP_ID"
```
Attach the intended group:
```bash
asc web review subscriptions attach-group \
--app "APP_ID" \
--group-id "GROUP_ID" \
--confirm
```
Attach one subscription instead when that is the intended review unit:
```bash
asc web review subscriptions attach \
--app "APP_ID" \
--subscription-id "SUB_ID" \
--confirm
```
These commands require an authenticated Apple web session. If the user declines web-session automation, select the subscription manually in App Store Connect.
Do not build workflows around `asc subscriptions review submit`; it was removed in 5.0.0.
## Prepare a subscription version
Use this public-API flow for an existing review submission. It does not replace first-review web attachment.
Resolve a `PREPARE_FOR_SUBMISSION` version:
```bash
asc subscriptions versions list \
--subscription-id "SUB_ID" \
--state PREPARE_FOR_SUBMISSION \
--paginate \
--output json
```
Branch before writing:
- Zero versions: create one and capture `.data.id` as `SUBSCRIPTION_VERSION_ID`.
- One version: reuse `.data[0].id`.
- More than one: stop and require an explicit version ID.
Create only in the zero-result branch:
```bash
asc subscriptions versions create --subscription-id "SUB_ID" --output json
```
Resolve the intended locale:
```bash
asc subscriptions versions localizations list \
--version-id "SUBSCRIPTION_VERSION_ID" \
--paginate \
--output json
```
Create `en-US` only when absent:
```bash
asc subscriptions versions localizations create \
--version-id "SUBSCRIPTION_VERSION_ID" \
--locale "en-US" \
--name "Premium" \
--description "Premium access"
```
Update the one resolved localization when its values differ:
```bash
asc subscriptions versions localizations update \
--id "SUBSCRIPTION_LOC_ID" \
--name "Premium" \
--description "Premium access"
```
Resolve images before uploading or deleting anything:
```bash
asc subscriptions versions images list \
--version-id "SUBSCRIPTION_VERSION_ID" \
--paginate \
--output json
```
Upload only when the intended image is absent:
```bash
asc subscriptions versions images upload \
--version-id "SUBSCRIPTION_VERSION_ID" \
--file "./promotional.png"
```
Treat replacement as a separate confirmed branch:
```bash
asc subscriptions versions images delete --id "SUBSCRIPTION_IMAGE_ID" --confirm
asc subscriptions versions images upload --version-id "SUBSCRIPTION_VERSION_ID" --file "./promotional.png"
```
Inspect the completed version and return its ID to `asc-release-flow`:
```bash
asc subscriptions versions view --id "SUBSCRIPTION_VERSION_ID" --output table
asc subscriptions versions localizations list --version-id "SUBSCRIPTION_VERSION_ID" --paginate --output table
asc subscriptions versions images primary --version-id "SUBSCRIPTION_VERSION_ID" --output table
asc subscriptions versions images list --version-id "SUBSCRIPTION_VERSION_ID" --paginate --output table
```
Do not add the version to a review submission from this skill. Hand `SUBSCRIPTION_VERSION_ID` to the multi-item workflow in `asc-release-flow`.
## Prepare a subscription-group version
Resolve the group version:
```bash
asc subscriptions groups versions list \
--group-id "GROUP_ID" \
--state PREPARE_FOR_SUBMISSION \
--paginate \
--output json
```
Branch before writing:
- Zero versions: create one and capture `.data.id` as `GROUP_VERSION_ID`.
- One version: reuse `.data[0].id`.
- More than one: stop and require an explicit version ID.
Create only in the zero-result branch:
```bash
asc subscriptions groups versions create --group-id "GROUP_ID" --output json
```
Resolve and repair the intended locale:
```bash
asc subscriptions groups versions localizations list --version-id "GROUP_VERSION_ID" --paginate --output json
asc subscriptions groups versions localizations create --version-id "GROUP_VERSION_ID" --locale "en-US" --name "Premium"
asc subscriptions groups versions localizations update --id "GROUP_LOC_ID" --name "Premium"
```
Run create only when the locale is absent; run update only when the single resolved locale differs.
Inspect the group version and return its ID to `asc-release-flow`:
```bash
asc subscriptions groups versions view --version-id "GROUP_VERSION_ID" --output table
asc subscriptions groups versions localizations list --version-id "GROUP_VERSION_ID" --paginate --output table
```
Do not add the version to a review submission from this skill. Hand `GROUP_VERSION_ID` to the multi-item workflow in `asc-release-flow`.
## Prepare an IAP version
Upload a missing legacy review screenshot when diagnostics request one:
```bash
asc iap review-screenshots create --iap-id "IAP_ID" --file "./review.png"
```
Do not build workflows around `asc iap submit`; it was removed in 5.0.0.
Resolve a version-scoped IAP:
```bash
asc iap versions list \
--iap-id "IAP_ID" \
--state PREPARE_FOR_SUBMISSION \
--paginate \
--output json
```
Branch before writing:
- Zero versions: create one and capture `.data.id` as `IAP_VERSION_ID`.
- One version: reuse `.data[0].id`.
- More than one: stop and require an explicit version ID.
Create only in the zero-result branch:
```bash
asc iap versions create --iap-id "IAP_ID" --output json
```
Resolve and repair the intended localization:
```bash
asc iap versions localizations list --version-id "IAP_VERSION_ID" --paginate --output json
asc iap versions localizations create --version-id "IAP_VERSION_ID" --locale "en-US" --name "Premium" --description "Unlock premium features"
asc iap versions localizations update --localization-id "IAP_LOC_ID" --name "Premium" --description "Unlock premium features"
```
Create only when `en-US` is absent. Update only when one resolved localization differs.
Resolve images before writing:
```bash
asc iap versions images list --version-id "IAP_VERSION_ID" --paginate --output json
```
Create an image only when the intended file is absent:
```bash
asc iap versions images create --version-id "IAP_VERSION_ID" --file "./review.png"
```
Treat replacement as a separate confirmed branch:
```bash
asc iap versions images delete --image-id "IAP_IMAGE_ID" --confirm
asc iap versions images create --version-id "IAP_VERSION_ID" --file "./review.png"
```
Inspect the version and return its ID to `asc-release-flow`:
```bash
asc iap versions view --version-id "IAP_VERSION_ID" --output table
asc iap versions localizations list --version-id "IAP_VERSION_ID" --paginate --output table
asc iap versions image --version-id "IAP_VERSION_ID" --output table
asc iap versions images list --version-id "IAP_VERSION_ID" --paginate --output table
```
Do not add the version to a review submission from this skill. Hand `IAP_VERSION_ID` to the multi-item workflow in `asc-release-flow`.
## Handle first-version IAP attachment
Apple may require the first IAP, a new IAP type, or a non-renewing IAP to be selected with the next app version. Prepare localization, pricing, and review screenshots first.
Use the web-session fallback only for that public-API gap:
```bash
asc web review iaps attach --app "APP_ID" --iap-id "IAP_ID" --confirm
```
Say that the command requires an authenticated Apple web session. Keep manual selection in the app version's “In-App Purchases and Subscriptions” section as the fallback.
references/readiness-repairs.md
# Readiness repairs
Read only the section that matches a proven `asc validate` or `asc review doctor` blocker.
## Contents
- [Build processing and encryption](#build-processing-and-encryption)
- [Content rights](#content-rights)
- [Age rating](#age-rating)
- [Version metadata and localizations](#version-metadata-and-localizations)
- [App info and privacy policy URL](#app-info-and-privacy-policy-url)
- [Screenshots](#screenshots)
- [Initial availability](#initial-availability)
- [Review details](#review-details)
## Build processing and encryption
Inspect the exact build before editing declarations:
```bash
asc builds info --build-id "BUILD_ID" --output table
```
Require `processingState` to be `VALID`. If encryption remains unresolved, inspect existing declarations:
```bash
asc encryption declarations list --app "APP_ID" --output table
```
Create a declaration only when its answers accurately describe the binary:
```bash
asc encryption declarations create \
--app "APP_ID" \
--app-description "Uses standard HTTPS/TLS" \
--contains-proprietary-cryptography=false \
--contains-third-party-cryptography=true \
--available-on-french-store=true
```
Assign the declaration to the resolved build:
```bash
asc encryption declarations assign-builds --id "DECLARATION_ID" --build-id "BUILD_ID"
```
If the app truly uses only exempt transport encryption, update the local plist and rebuild instead of making a false declaration:
```bash
asc encryption declarations exempt-declare --plist "./Info.plist"
```
## Content rights
Read the current declaration, then edit it only when the answer is known:
```bash
asc apps content-rights view --app "APP_ID" --output table
asc apps content-rights edit --app "APP_ID" --uses-third-party-content=false
```
## Age rating
Inspect the full declaration before a partial edit:
```bash
asc age-rating view --app "APP_ID" --output table
```
Set the social-media fields only when they describe the app:
```bash
asc age-rating edit --app "APP_ID" --social-media false --social-media-age-restricted false
```
Apple requires `userGeneratedContent=true` before `socialMedia` can be true. It requires both `ageAssurance=true` and `socialMedia=true` before `socialMediaAgeRestricted` can be true. Set every required prerequisite in the same edit or preserve the current values explicitly.
Use `--age-rating-override-v2` when an override is required. The older `--age-rating-override` flag is deprecated.
## Version metadata and localizations
Inspect the version and its attached resources:
```bash
asc versions view --version-id "VERSION_ID" --include build,appStoreVersionSubmission --output json
asc localizations list --version "VERSION_ID" --output table
```
Use the canonical metadata workflow for repair:
```bash
asc metadata pull --app "APP_ID" --version "1.2.3" --platform IOS --dir "./metadata"
asc metadata validate --dir "./metadata" --output table
asc metadata push --app "APP_ID" --version "1.2.3" --platform IOS --dir "./metadata" --dry-run --output table
asc metadata push --app "APP_ID" --version "1.2.3" --platform IOS --dir "./metadata"
```
Review the dry-run diff before applying metadata. Do not overwrite local changes with a pull unless the user has chosen the remote copy as the source of truth.
## App info and privacy policy URL
Resolve the app-info record and its localizations:
```bash
asc apps info list --app "APP_ID" --output table
asc localizations list --app "APP_ID" --type app-info --app-info "APP_INFO_ID" --output table
```
For every iOS or macOS app, populate the privacy policy URL when missing:
```bash
asc app-setup info set \
--app "APP_ID" \
--primary-locale "en-US" \
--privacy-policy-url "https://example.com/privacy"
```
## Screenshots
Inspect the localization's current screenshot set and the accepted dimensions:
```bash
asc screenshots list --version-localization "LOC_ID" --output table
asc screenshots sizes --output table
asc screenshots validate --path "./screenshots" --device-type "IPHONE_65" --output table
```
Use `asc-screenshot-resize` or `asc-shots-pipeline` for screenshot production. Return here after the files pass validation and are uploaded.
## Initial availability
First confirm that no availability record exists:
```bash
asc pricing availability view --app "APP_ID" --output table
```
Bootstrap the first record through the public API:
```bash
asc pricing availability create \
--app "APP_ID" \
--territory "USA,GBR" \
--available true \
--available-in-new-territories true
```
If Apple rejects this public-API bootstrap, it has not configured availability. Authenticate a web session with `asc web auth login --apple-id "EMAIL"`, then retry through the web fallback:
```bash
asc web apps availability create \
--app "APP_ID" \
--territory "USA,GBR" \
--available-in-new-territories true
```
Alternatively, configure Pricing and Availability in App Store Connect.
Use the edit command only after a record exists:
```bash
asc pricing availability edit \
--app "APP_ID" \
--territory "USA,GBR" \
--available true \
--available-in-new-territories true
```
Do not assume a standard territory list. Ask the user which territories should receive the app.
## Review details
Inspect the version's review details:
```bash
asc review details-for-version --version-id "VERSION_ID" --output table
```
Create missing details:
```bash
asc review details-create \
--version-id "VERSION_ID" \
--contact-first-name "Dev" \
--contact-last-name "Support" \
--contact-email "dev@example.com" \
--contact-phone "+1 408 555 0100" \
--notes "Explain the reviewer access path here."
```
Update the resolved record instead of creating a duplicate:
```bash
asc review details-update --id "DETAIL_ID" --notes "Updated reviewer instructions."
```
Set demo-account fields only when App Review needs credentials, and never print secrets in logs or handoff text.
SKILL.md
---
name: asc-submission-health
description: Diagnose App Store submission blockers and operate review health with asc, including readiness validation, repair routing, status monitoring, cancellation, and retry decisions. Use when validation fails, a version is not in a valid state, review status is unclear or stuck, or a failed submission must be repaired and retried. For staging, upload, publication, and submission execution, use asc-release-flow.
---
# App Store submission health
Use this skill to explain why a release cannot proceed and to manage an existing review submission. Hand healthy release execution back to `asc-release-flow`.
## Ownership boundary
This skill owns:
- readiness validation and blocker diagnosis;
- public-API, web-session, and manual repair routing;
- review status and history;
- cancellation and retry decisions.
Use `asc-release-flow` for staging, upload, publication, and submission. Switching skills continues the current task with its resolved targets, authorization, and verified progress; it does not require the user to restart the workflow. Continue authorized repairs and return to release execution when healthy. Ask for new authority only when a repair exceeds scope.
## Answer order
1. State whether the version is ready, blocked, or already under review.
2. Name each blocker and the evidence that proves it.
3. Separate public-API repairs from web-session and manual work.
4. Run the read-only checks needed to establish the diagnosis. For diagnosis-only requests, report the evidence and one proposed repair command without executing that repair. For authorized execution, continue the repair queue and report completed work and remaining blockers.
## Establish the target
- Resolve `APP_ID`, the version string or `VERSION_ID`, `BUILD_ID`, platform, and any known `SUBMISSION_ID`.
- Configure auth with `asc auth login` or `ASC_*` environment variables.
- Use `ASC_BYPASS_KEYCHAIN=1` only for repository tests and isolated verification, not normal user sessions.
- Prefer IDs once the target is resolved; stop when app, version, or product resolution is ambiguous.
## Diagnose readiness
Run the canonical readiness report first:
```bash
asc validate --app "APP_ID" --version "1.2.3" --platform IOS --output table
```
Use `--version-id "VERSION_ID"` when known. Add `--strict` when warnings must fail automation.
Ask the review-specific doctor for an ordered explanation:
```bash
asc review doctor --app "APP_ID" --version "1.2.3" --platform IOS --output table
```
Collect direct evidence when the report points at the build or version:
```bash
asc builds info --build-id "BUILD_ID" --output table
# The attached build and submission are in .data.relationships and .included
asc versions view --version-id "VERSION_ID" --include build,appStoreVersionSubmission --output json
```
For digital goods, run only the relevant product validator:
```bash
asc validate iap --app "APP_ID" --output table
asc validate subscriptions --app "APP_ID" --output table
```
Treat the ordered remediation plan from `asc validate` as the repair queue. Fix and verify one class of blocker before moving to the next.
## Route repairs
Use public API commands when the blocker is build processing, metadata, screenshots, review details, encryption, content rights, age rating, availability, or version-scoped product metadata.
Read [references/readiness-repairs.md](references/readiness-repairs.md) when diagnostics identify one of those common blockers or a first-release availability gap.
Read [references/digital-goods.md](references/digital-goods.md) only when IAP or subscription validation fails, Apple requires first-review attachment, or a versioned product must join an existing review submission.
Read [references/app-privacy.md](references/app-privacy.md) only when validation reports an App Privacy advisory or the publish state cannot be confirmed through the public API.
When validation reports a Game Center component or version blocker, hand it to `asc-release-flow` and request the multi-item reference's **Prepare every item** section. Do not route Game Center through general readiness or digital-goods repairs.
Use the web-session commands only for a gap the public API cannot cover, and say that an authenticated Apple web session is required. Keep a manual App Store Connect fallback when the user declines web-session automation.
## Decide whether the version is healthy
A version is ready to return to `asc-release-flow` when:
- `asc validate` has no blocking issues;
- the attached build is `VALID`;
- metadata, screenshots, app info, review details, content rights, encryption, age rating, pricing, and availability are resolved;
- the relevant `asc validate iap` and/or `asc validate subscriptions` checks have no blocking issues, and the required digital-goods versions are prepared;
- any Game Center version items have been checked through `asc-release-flow`'s multi-item submission reference;
- App Privacy is confirmed or published.
Do not call a version ready merely because one validator exits successfully. Report any warning that still needs a web-session or manual check.
## Monitor review
Use app-scoped status when the submission ID is unknown:
```bash
asc review status --app "APP_ID" --version "1.2.3" --platform IOS --output table
```
Use exact submission or version IDs when available:
```bash
asc submit status --id "SUBMISSION_ID" --output table
asc submit status --version-id "VERSION_ID" --output table
```
Use the release dashboard for surrounding build and review signals:
```bash
asc status --app "APP_ID" --include builds,appstore,submission,review --output table
```
To wait for the review outcome, poll until it settles. The command exits 0 when approved, 1 when rejected, and 7 when still pending at the timeout:
```bash
asc status --app "APP_ID" --until review-done --timeout 2h --output json
```
Status JSON lists suggested follow-ups in `summary.nextCommands`, each marked with whether it mutates App Store Connect. Treat mutating suggestions as proposals that still need the user's authorization.
Use history to distinguish a current stall from earlier rejected or completed submissions:
```bash
asc review history --app "APP_ID" --version "1.2.3" --paginate --output table
```
## Cancel an unhealthy submission
Resolve the exact active submission before cancelling. Preview status first, then require confirmation:
```bash
asc submit status --id "SUBMISSION_ID" --output table
asc submit cancel --id "SUBMISSION_ID" --confirm
```
When resolving by version, include the app for the modern review-submission lookup:
```bash
asc submit status --version-id "VERSION_ID" --output table
asc submit cancel --version-id "VERSION_ID" --app "APP_ID" --confirm
```
The lower-level equivalent is valid when the exact review submission is already known:
```bash
asc review submissions-cancel --id "SUBMISSION_ID" --confirm
```
Do not cancel a submission solely because review is taking longer than expected. Confirm the state and the user's intent first.
## Decide when to retry
There is no dedicated retry command. Use this sequence:
1. Cancel only if the active submission must be withdrawn.
2. Repair the proven blockers.
3. Re-run `asc validate` and the relevant product validators.
4. Confirm no active submission already owns the version or review items.
5. Hand the healthy version and any preserved `SUBMISSION_ID` to `asc-release-flow` for submission execution. Reuse an inspected `READY_FOR_REVIEW` draft; create a submission only when no matching draft or active submission exists.
## Common failure routing
| Symptom | First evidence | Repair route |
| --- | --- | --- |
| Version is not in a valid state | `asc validate`, `asc review doctor` | ordered readiness repairs |
| Export compliance must be approved | build info and encryption declaration | readiness repairs |
| Multiple app infos found | `asc apps info list --app "APP_ID"` | resolve exact app-info ID |
| IAP or subscription is not ready | product validator | digital-goods reference |
| Game Center component or version is not ready | `asc validate` diagnostic | `asc-release-flow` multi-item preparation section |
| App Privacy publish state is unclear | validation advisory | App Privacy reference |
| Review appears stuck | review status plus history | monitor; cancel only with evidence and approval |
## Guardrails
- Do not use removed `submit-preflight` or `submit-create` shortcuts.
- Do not submit from this skill; return healthy execution to `asc-release-flow`.
- Do not treat web-session automation as public App Store Connect API coverage.
- Do not retry until the earlier submission state and blocker repairs are verified.
- Use `--output table` for human diagnosis and JSON for automation.
- For macOS, use `--platform MAC_OS` while keeping the same health lifecycle.