docs(release): authorize scoped store uploads

This commit is contained in:
jjbrunton committed 2026-08-31 10:08:03 +01:00
1 parent 3fc6f8aa1a
commit 8bf93f372b
3 files changed
+48 -46

No files matched your search

+7 -3
View File
@@ -13,9 +13,13 @@ drafting notes and [references/artifact-verification.md](references/artifact-ver
before accepting a build. before accepting a build.
A request to generate or create a release authorizes the scoped version edits, A request to generate or create a release authorizes the scoped version edits,
release notes, local builds, release commits, and one local annotated tag. It release notes, local builds, release commits, and one local annotated tag. When
does not authorize pushing commits or tags, uploading binaries, submitting a the request also specifies a mobile release, upload, or store-submission
store release, changing signing credentials, or regenerating native projects. workflow, it authorizes the requested store upload within its stated platform
and destination scope after the exact artifact has been verified. It does not
authorize pushing commits or tags, changing signing credentials, regenerating
native projects, a public rollout, App Review submission, or additional
TestFlight distribution unless the request explicitly includes that action.
## Defaults ## Defaults
+16 -19
View File
@@ -18,13 +18,13 @@ so routine release builds must package those checked-in sources. Do not run
`expo prebuild` first; native regeneration is a separate reviewed change. `expo prebuild` first; native regeneration is a separate reviewed change.
Use the package scripts in `apps/mobile/package.json`; they create artifacts only. Use the package scripts in `apps/mobile/package.json`; they create artifacts only.
Never infer upload or submission authority from build authorization. Store upload An explicit request for a mobile release, upload, or store-submission workflow
uses a separately authorized command. authorizes the requested store upload within its stated platform and destination
scope. Building an artifact alone does not authorize an upload.
## Upload authorization gate ## Upload execution
After an artifact passes verification, stop immediately before the external Before an external upload, independently verify and report:
upload and ask the user for confirmation. The request must identify:
- the platform, exact artifact path, bundle/package identifier, public version, - the platform, exact artifact path, bundle/package identifier, public version,
build number, signature identity, and SHA-256 digest; build number, signature identity, and SHA-256 digest;
@@ -33,24 +33,21 @@ upload and ask the user for confirmation. The request must identify:
- that the upload does not authorize a public rollout or App Review submission. - that the upload does not authorize a public rollout or App Review submission.
For iOS, inspect the current App Store Connect automatic-distribution behavior For iOS, inspect the current App Store Connect automatic-distribution behavior
before asking. If the build would be distributed automatically, name the exact before uploading. If the build would be distributed automatically, report the
TestFlight groups or testers in the request and include that effect in the fresh exact TestFlight groups or testers. If the effect cannot be established, stop;
authorization. If the effect cannot be established, stop; changing an automatic- changing an automatic-distribution setting is a separately authorized action.
distribution setting also requires separate authorization.
Even when the original request includes building, releasing, uploading, or Once these details match the user's stated scope, upload without requesting a
submitting, require this fresh confirmation once the exact verified artifact and second confirmation. Run `eas submit` with the explicit
destination are known. End the request with: `Upload this verified artifact to
<destination> 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 `--platform`, `--profile production`, `--path`, and `--wait` arguments; never
select `--latest`. If the result is ambiguous, inspect EAS and the store before 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. doing anything else; do not retry unless the user explicitly authorizes another
upload.
Apply this gate to every upload method, including EAS, Fastlane, Xcode Organizer, Apply this policy to every upload method, including EAS, Fastlane, Xcode
and the store consoles. A later public rollout, App Review submission, or Organizer, and the store consoles. A public rollout, App Review submission, or
additional TestFlight distribution requires another fresh authorization. additional TestFlight distribution requires separate explicit authorization
unless it was expressly included in the original request.
Preserve platform signing and local EAS versioning. After a build, verify that Preserve platform signing and local EAS versioning. After a build, verify that
tracked changes are limited to the expected version metadata, then independently tracked changes are limited to the expected version metadata, then independently
+25 -24
View File
@@ -36,7 +36,9 @@ npm run release:ios
Output files are placed in the current directory by default. Output files are placed in the current directory by default.
These scripts create signed artifacts only. They do not upload or submit them. These scripts create signed artifacts only. They do not upload or submit them.
Store mutation always requires a separate, explicitly authorized command. An explicit request for a mobile release, upload, or store-submission workflow
authorizes the requested store upload within its stated platform and destination
scope. Building an artifact alone does not authorize an upload.
## Submit a local artifact with EAS ## Submit a local artifact with EAS
@@ -56,27 +58,26 @@ eas submit --platform android --profile production --path /absolute/path/to/sauc
eas submit --platform ios --profile production --path /absolute/path/to/sauci.ipa --wait eas submit --platform ios --profile production --path /absolute/path/to/sauci.ipa --wait
``` ```
Agents must not upload immediately after building, whether they use EAS, Agents must not upload an unverified artifact, whether they use EAS, Fastlane,
Fastlane, Xcode Organizer, or a store console. Once the artifact is verified, the Xcode Organizer, or a store console. Before upload, they must verify and report
agent must show the user the platform, exact path, bundle/package identifier, the platform, exact path, bundle/package identifier, version, build number,
version, build number, signing identity, SHA-256 digest, and destination, then ask signing identity, SHA-256 digest, and destination. Once those details match the
for a fresh confirmation to upload it. This confirmation authorizes one upload user's stated scope, proceed without asking for a second confirmation.
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 Before an iOS upload, inspect App Store Connect for automatic TestFlight
distribution. If upload will add the build to existing groups or testers, name distribution. If upload will add the build to existing groups or testers, report
them in the confirmation and include that effect in the authorization. If the them before proceeding. If the effect cannot be established, stop. Changing
effect cannot be established, stop. Changing automatic-distribution settings is automatic-distribution settings is a separate action and requires its own
a separate action and requires its own authorization. authorization.
Do not use `--latest` for a local release. Before upload, verify the artifact's Do not use `--latest` for a local release. Before upload, verify the artifact's
package or bundle identifier, public version, build number, signature, and package or bundle identifier, public version, build number, signature, and
SHA-256 digest. After upload, read back the same identity and version from Google 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 Play Console or App Store Connect. Public rollout, App Review submission, and
additional TestFlight group distribution remain separate, explicitly authorized additional TestFlight group distribution remain separate, explicitly authorized
actions. If an upload command returns an ambiguous result, inspect EAS and the actions unless the original request expressly includes them. If an upload command
store first; do not retry unless the user gives fresh authorization. returns an ambiguous result, inspect EAS and the store first; do not retry unless
the user explicitly authorizes another upload.
### Source integrity ### Source integrity
@@ -250,9 +251,9 @@ android/app/build/outputs/bundle/release/app-release.aab
### Step 5: Upload to Play Store ### Step 5: Upload to Play Store
Apply the upload authorization gate above before opening or changing the release. Apply the upload execution policy above before opening or changing the release.
Uploading the AAB and starting any rollout are separate actions; ask again before Uploading the AAB and starting any rollout are separate actions unless the
the rollout. original request expressly includes the rollout.
1. Go to [Google Play Console](https://play.google.com/console) 1. Go to [Google Play Console](https://play.google.com/console)
2. Select **Sauci** app 2. Select **Sauci** app
@@ -261,8 +262,8 @@ the rollout.
5. Upload the `.aab` file 5. Upload the `.aab` file
6. Add release notes, save the release as a draft, and read it back 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 Do not send the draft for review or start a rollout unless the original request
authorization described above. expressly includes that action.
### Verifying Keystore Fingerprint ### Verifying Keystore Fingerprint
@@ -300,8 +301,8 @@ cd ..
### Step 4: Upload to App Store ### Step 4: Upload to App Store
Apply the upload authorization gate above before using Xcode Organizer. Include Apply the upload execution policy above before using Xcode Organizer. Report any
any verified automatic TestFlight distribution in the confirmation. verified automatic TestFlight distribution before uploading.
1. In Xcode Organizer (Window → Organizer), select the archive 1. In Xcode Organizer (Window → Organizer), select the archive
2. Click **Distribute App** 2. Click **Distribute App**
@@ -310,8 +311,8 @@ any verified automatic TestFlight distribution in the confirmation.
### Step 5: Submit in App Store Connect ### Step 5: Submit in App Store Connect
Submitting for App Review is not authorized by the upload confirmation. Ask the Submitting for App Review is not authorized by an upload request unless the
user for fresh authorization immediately before this step. original request expressly includes App Review submission.
1. Go to [App Store Connect](https://appstoreconnect.apple.com) 1. Go to [App Store Connect](https://appstoreconnect.apple.com)
2. Select **Sauci** 2. Select **Sauci**