docs: build-and-sign Mac App Store Tauri section, pitfall 114, changelog

This commit is contained in:
CRTkafa 2026-10-24 12:16:19 +08:00
parent f588f4e1aa
commit 33a7f73ab9
3 changed files with 54 additions and 0 deletions

View file

@ -85,6 +85,32 @@ when the owner said so for this run). The MCP server offers only `apple_signing_
6. **Next.** `storebound apple encryption --build N`, `storebound apple testflight distribute --build N --group Team
--dry` (`testflight` skill), `storebound apple listing --version x.y.z --build N` (`appstore-first-release`).
## Mac App Store: a Tauri app (.pkg)
`storebound apple build --platform macos --tauri apps/desktop/src-tauri --path-free --dry` prints the plan; without
`--dry` it runs in the Mac's logged-in GUI session (not over SSH: write a .command file and `open -a Terminal` it):
1. Version from `--version` or tauri.conf.json, build number from `--build-number` or the next free one on App Store
Connect for macOS (CFBundleVersion must increase). `tauri.conf.json` `identifier` must equal `apple.bundleId`.
2. Identities from the login keychain: "Apple Distribution" (or "3rd Party Mac Developer Application") and "Mac
Installer Distribution" (or "3rd Party Mac Developer Installer"). The installer one is its own certificate type
(`apple.signing.certificateType: 'MAC_INSTALLER_DISTRIBUTION'`, `apple signing ensure`).
3. Provisioning profile: `--profile`, else an installed one, else the active `MAC_APP_STORE` profile from the API
(`apple.signing.profileType: 'MAC_APP_STORE'`).
4. `tauri build --bundles app --target universal-apple-darwin --config <overlay>`: the overlay sets the signing identity,
the generated entitlements (app sandbox, application / team identifier, your own keys kept), the embedded profile,
hardened runtime and `bundleVersion`. Set `bundle.category` and `bundle.macOS.minimumSystemVersion` in
tauri.conf.json (the build stops without LSApplicationCategoryType / LSMinimumSystemVersion).
5. Checks of the .app (sandbox, no get-task-allow, profile inside, version / build), `codesign --verify`, then
`productbuild --component <app> /Applications --sign <installer identity>` and `pkgutil --check-signature`.
6. `--path-free`: rustc remaps the checkout, CARGO_HOME, RUSTUP_HOME and the home folder, no debug info, symbols stripped;
the build fails when the home folder or user name is still in the app. `--unsigned` runs the pipeline without
identities (not uploadable). Result: `<out>/export/<version>-<build>/<Product>.pkg` (`--out`, default `build/macos`).
Then `storebound apple upload <pkg> --platform macos --dry` and without `--dry` (App Store Connect build upload,
platform MAC_OS, or `--via altool`). The .pkg is checked first (installer signature); the build shows up in the macOS
version's build list once processed. Details and fixes: `store-pitfalls` 119.
## Android
1. **Upload key.** Generate once (`keytool -genkeypair -v -storetype PKCS12 -keystore upload.p12 -alias upload

View file

@ -1415,3 +1415,29 @@ that fails without the fix (see CONTRIBUTING.md).
`storebound shots copy reviewed --lang de`. Captions over the limit (eyebrow 30, title line 28, sub 90, badge 18) are
not kept.
- **Guard:** `cli/shots/copy.ts`, `cli/lib/shots-copy-translate.ts`, `tests/shots-copy-translate.test.ts`.
## 119. A Tauri Mac App Store build was refused (no sandbox, no profile, wrong installer certificate) or carried the builder's home folder
- **What happens:** a plain `tauri build` makes a Developer ID app: no `com.apple.security.app-sandbox`, no
`embedded.provisionprofile`, signed with the wrong certificate, packed as a .dmg. Packed by hand into a .pkg it fails at
upload with ITMS-90xxx (sandbox, missing profile, CFBundleVersion not above the last one, no LSApplicationCategoryType) or
the .pkg is signed with an application certificate. Separately, rustc panic messages and debug info carry the
checkout, `~/.cargo` and the user name (`/Users/<name>/...`, hundreds of times in a release binary), which ends up
in a public download.
- **Do:** `storebound apple build --platform macos --tauri <src-tauri> --path-free --dry`, then the same without `--dry`
in the Mac's logged-in GUI session (codesign over SSH fails with errSecInternalComponent). It needs, on the Mac: an
"Apple Distribution" (or "3rd Party Mac Developer Application") and a "Mac Installer Distribution" (or "3rd Party Mac
Developer Installer") identity in the login keychain, and an active MAC_APP_STORE profile
(`apple.signing.profileType: 'MAC_APP_STORE'`, `apple signing ensure`, or `--profile <file>`). The installer certificate
is a separate certificate type (`MAC_INSTALLER_DISTRIBUTION`). `--unsigned` checks the whole pipeline without them
(never uploadable). A universal build needs both Rust targets (rustup); with Homebrew Rust only the host
target exists: pass `--target aarch64-apple-darwin`.
- **Guard:** `cli/lib/mas.ts` / `cli/apple/build-mas.ts`: entitlements generated with sandbox and application / team
identifier (the project's own keys kept), profile embedded through a tauri.conf overlay, bundleVersion from App Store
Connect (platform MAC_OS) so it increases, the built app checked (sandbox entitlement, no get-task-allow, category,
minimum OS, profile inside, version / build), `--path-free` remaps checkout / CARGO_HOME / RUSTUP_HOME / home in rustc,
drops debug info and symbols and fails when the home folder or user name is still in the app (without the flag the
same scan warns). `cargo trim-paths` is not used: it is nightly-only (cargo 1.98 refuses it). `apple upload <pkg>
--platform macos` refuses an unsigned .pkg or one not signed with an installer certificate before any network call
(`tests/mas-build.test.ts`). The `com.apple.pkg` file type of the API build upload is taken from Apple's schema and has not
been exercised against the live API yet; `--via altool` (`--type macos`) is the fallback.