diff --git a/.codex/skills/release-mobile/SKILL.md b/.codex/skills/release-mobile/SKILL.md index 6638d97..bb40cd8 100644 --- a/.codex/skills/release-mobile/SKILL.md +++ b/.codex/skills/release-mobile/SKILL.md @@ -19,8 +19,40 @@ so routine release builds must package those checked-in sources. Do not run Use the package scripts in `apps/mobile/package.json`; they create artifacts only. Never infer upload or submission authority from build authorization. Store upload -uses a separately authorized command. Preserve platform signing and local EAS -versioning. After a build, verify that tracked changes are limited to the expected -version metadata, then independently read the artifact version and signature. -Report the artifact, version/build number, upload result when authorized, and -read-back state. +uses a separately authorized command. + +## Upload authorization gate + +After an artifact passes verification, stop immediately before the external +upload and ask the user for confirmation. The request must identify: + +- the platform, exact artifact path, bundle/package identifier, public version, + build number, signature identity, and SHA-256 digest; +- the exact destination and resulting state: Google Play internal-track draft or + App Store Connect/TestFlight processing; +- that the upload does not authorize a public rollout or App Review submission. + +For iOS, inspect the current App Store Connect automatic-distribution behavior +before asking. If the build would be distributed automatically, name the exact +TestFlight groups or testers in the request and include that effect in the fresh +authorization. If the effect cannot be established, stop; changing an automatic- +distribution setting also requires separate authorization. + +Even when the original request includes building, releasing, uploading, or +submitting, require this fresh confirmation once the exact verified artifact and +destination are known. End the request with: `Upload this verified artifact to + now?` A clear affirmative response authorizes one upload of that +artifact to that destination, plus only any automatic TestFlight distribution +explicitly disclosed in the request. Run `eas submit` with the explicit +`--platform`, `--profile production`, `--path`, and `--wait` arguments; never +select `--latest`. If the result is ambiguous, inspect EAS and the store before +doing anything else, do not retry, and ask again before another upload. + +Apply this gate to every upload method, including EAS, Fastlane, Xcode Organizer, +and the store consoles. A later public rollout, App Review submission, or +additional TestFlight distribution requires another fresh authorization. + +Preserve platform signing and local EAS versioning. After a build, verify that +tracked changes are limited to the expected version metadata, then independently +read the artifact version and signature. Report the artifact, version/build +number, upload result when authorized, and store read-back state. diff --git a/docs/releasing.md b/docs/releasing.md index 92634c1..32fe209 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -51,11 +51,27 @@ eas submit --platform android --profile production --path /absolute/path/to/sauc eas submit --platform ios --profile production --path /absolute/path/to/sauci.ipa --wait ``` +Agents must not upload immediately after building, whether they use EAS, +Fastlane, Xcode Organizer, or a store console. Once the artifact is verified, the +agent must show the user the platform, exact path, bundle/package identifier, +version, build number, signing identity, SHA-256 digest, and destination, then ask +for a fresh confirmation to upload it. This confirmation authorizes one upload +of that exact artifact to that exact destination, even if the earlier request +already said to build, release, upload, or submit. + +Before an iOS confirmation, inspect App Store Connect for automatic TestFlight +distribution. If upload will add the build to existing groups or testers, name +them in the confirmation and include that effect in the authorization. If the +effect cannot be established, stop. Changing automatic-distribution settings is +a separate action and requires its own authorization. + Do not use `--latest` for a local release. Before upload, verify the artifact's package or bundle identifier, public version, build number, signature, and SHA-256 digest. After upload, read back the same identity and version from Google Play Console or App Store Connect. Public rollout, App Review submission, and -TestFlight group distribution remain separate, explicitly authorized actions. +additional TestFlight group distribution remain separate, explicitly authorized +actions. If an upload command returns an ambiguous result, inspect EAS and the +store first; do not retry unless the user gives fresh authorization. ### Source integrity @@ -218,14 +234,21 @@ The AAB file will be at: android/app/build/outputs/bundle/release/app-release.aab ``` -### Step 5: Upload to Play Store - -1. Go to [Google Play Console](https://play.google.com/console) -2. Select **Sauci** app -3. Go to **Production** (or testing track) -4. **Create new release** -5. Upload the `.aab` file -6. Add release notes and submit +### Step 5: Upload to Play Store + +Apply the upload authorization gate above before opening or changing the release. +Uploading the AAB and starting any rollout are separate actions; ask again before +the rollout. + +1. Go to [Google Play Console](https://play.google.com/console) +2. Select **Sauci** app +3. Go to **Internal testing**, unless the user authorized a different exact track +4. **Create new release** +5. Upload the `.aab` file +6. Add release notes, save the release as a draft, and read it back + +Do not send the draft for review or start a rollout without the separate fresh +authorization described above. ### Verifying Keystore Fingerprint @@ -261,16 +284,22 @@ cd .. 3. Go to **Product** → **Archive** 4. Wait for the build to complete -### Step 4: Upload to App Store - -1. In Xcode Organizer (Window → Organizer), select the archive +### Step 4: Upload to App Store + +Apply the upload authorization gate above before using Xcode Organizer. Include +any verified automatic TestFlight distribution in the confirmation. + +1. In Xcode Organizer (Window → Organizer), select the archive 2. Click **Distribute App** 3. Select **App Store Connect** → **Upload** 4. Follow the prompts to upload -### Step 5: Submit in App Store Connect - -1. Go to [App Store Connect](https://appstoreconnect.apple.com) +### Step 5: Submit in App Store Connect + +Submitting for App Review is not authorized by the upload confirmation. Ask the +user for fresh authorization immediately before this step. + +1. Go to [App Store Connect](https://appstoreconnect.apple.com) 2. Select **Sauci** 3. Create a new version or select the uploaded build 4. Fill in release notes and submit for review