# Release process No release is authorized by the existence of these scripts. No workflow publishes to either store. A debug APK or unsigned archive is not a production release. 1. Complete every outstanding gate in `validation.md` and `security-review.md`. Obtain independent human review of authentication, navigation, file handlers, local erasure and privacy disclosures. Run actual supported device/OS tests. 2. Resolve bundle/application identifier ownership. `community.yuvomi.mobile` is a provisional community identifier, not proof of registry/store ownership. Confirm use of the Yuvomi name, required attribution and independent status. 3. Bump version/name/code in Android and the iOS project spec; update CHANGELOG. 4. Run native JVM/Compose/emulator/real-upstream HTTPS tests, portable Swift and Xcode simulator tests, static checks, OSV scan, release builds and artifact inspection. Record upstream revision, app SHA, OS/SDK/Xcode versions, results and checksums. 5. Produce signed artifacts only using an authorized maintainer's credentials. 6. Review store privacy/Data Safety answers for the app AND selected-server model, permission rationale, encryption/export compliance, screenshots, support URL, vulnerability contact, and device demonstrations. An incomplete native preview is not a finished PWA replacement or App Store approval. 7. Create a release/tag and publish artifacts/store submissions manually only after explicit maintainer authorization. Never force-push or rewrite history. ## Android The manual `.gitea/workflows/release.yml` workflow runs on `ubuntu-latest` and emits **unsigned** artifacts only. Gitea ignores GitHub environment approval gates, so this workflow does not load signing secrets or offer a signing toggle. An authorized maintainer must separately sign the verified APK/AAB using their own keystore, alias and passwords with `zipalign`, `apksigner`, and `jarsigner`. Keep private material in a protected signing environment, never on the general validation runners. Securely back up the real upload key and use Play App Signing according to the owner's policy. An initial owner-authorized key and repository secrets already exist outside Git; signing workflow changes are parked during the native rebuild. Preserve the key, do not generate a replacement or apply the old signing stash without review. See `native-parity.md`. Manually verify APK/AAB signatures and inspect the final manifest: no debuggable flag, HTTP/test CA or unintended exported component. Never distribute an `.integration` package or include its generated test resources. Run `python3 scripts/collect-android-artifacts.py` immediately after the clean-source build to inspect unsigned outputs and record local hashes/source identity. This collector intentionally rejects signed release outputs; collect before signing. ## iOS The CI archive is unsigned and cannot be uploaded to App Store Connect. An owner needs Apple Developer Program membership, a registered app ID, distribution certificate/private key, provisioning profile and App Store Connect permissions. Generate/open the project, choose the authorized team, set the owned bundle ID, select a physical/generic iOS destination, and use Product -> Archive. Validate the archive in Organizer and export using the owner's distribution method. For CLI export use a **locally supplied** ExportOptions.plist with the correct team, method and provisioning mappings: ```sh xcodebuild -exportArchive -archivePath artifacts/Yuvomi.xcarchive \ -exportPath artifacts/ios -exportOptionsPlist /secure/path/ExportOptions.plist ``` Do not add distribution certificates, profiles, App Store keys or passwords to the repository. Device camera, Files, VoiceOver, memory pressure and app-switcher privacy need physical-device validation beyond simulator tests. ## CI hosting Gitea Actions workflows are provided in `.gitea/workflows/`, using the supplied `ubuntu-latest` and `macos-arm64` runner labels. See [runner setup](ci-runners.md) for SDK, KVM, Xcode, simulator and security requirements. Repository Actions must be enabled. Inspect actual runs before claiming CI is operational; no GitHub mirror or store destination is created. CI is not an application dependency.