今天上传成功前反复踩了三个坑:
CFBundleIdentifier 与 Apple Developer profile 的 Bundle ID 不一致。Info.plist 缺少 Mac App Store 必填的 LSApplicationCategoryType。.app 嵌入的 provisioning profile 有 com.apple.application-identifier,但签名 entitlements 没有同一个值,触发 Transporter/TestFlight 90886。com.apple.quarantine 扩展属性,复制进 .app 后被打进 .pkg,触发 Transporter/TestFlight 91109。这些都不是业务功能问题,而是 Mac App Store 上传包的元数据和签名验收不完整。
pkgutil --check-signature 只能证明 .pkg 被 Installer 证书签了,不能证明 App Store 会接受。codesign -vvv --deep --strict 只能证明签名结构有效,不能证明 entitlements 与 embedded profile 一致。CFBundleVersion build 号。CFBundleShortVersionString=2.1.28,但每个新上传包必须有新的 build。*-universal-macappstore.pkg,不能是 sandbox POC DMG,也不能是旧 build。在把 .pkg 交给用户上传前,必须对最终 .pkg 展开检查,而不是只检查 build 目录里的 .app。
必须检查:
CFBundleIdentifier=com.shanghai3168.privatevoicedictationCFBundleShortVersionString 与本次发布版本一致CFBundleVersion 是本次新 buildLSApplicationCategoryType=public.app-category.productivityCR3J54M8BQ.com.shanghai3168.privatevoicedictationcom.apple.application-identifier 是 CR3J54M8BQ.com.shanghai3168.privatevoicedictationcom.apple.developer.team-identifier 是 CR3J54M8BQcom.apple.security.app-sandbox=truearm64 + x86_64libsherpa-onnx-c-api.dylib 是 universal arm64 + x86_64libonnxruntime.1.24.4.dylib 是 universal arm64 + x86_64codesign -vvv --deep --strict 对最终 app PASSpkgutil --check-signature 对最终 pkg PASS.pkg 展开后的 .app 内没有 com.apple.quarantine 扩展属性PKG="/path/to/PrivateVoice-Dictation-2.1.28-buildYYYYMMDD.HHMM-universal-macappstore.pkg"
TMP="/tmp/privatevoice-pkg-check"
rm -rf "$TMP"
pkgutil --expand-full "$PKG" "$TMP"
APP="$(find "$TMP" -name 'PrivateVoice Dictation.app' -type d -print -quit)"
/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "$APP/Contents/Info.plist"
/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$APP/Contents/Info.plist"
/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' "$APP/Contents/Info.plist"
/usr/libexec/PlistBuddy -c 'Print :LSApplicationCategoryType' "$APP/Contents/Info.plist"
PROFILE_PLIST="$TMP/profile.plist"
security cms -D -i "$APP/Contents/embedded.provisionprofile" > "$PROFILE_PLIST"
/usr/libexec/PlistBuddy -c 'Print :Entitlements:com.apple.application-identifier' "$PROFILE_PLIST"
/usr/libexec/PlistBuddy -c 'Print :Entitlements:com.apple.developer.team-identifier' "$PROFILE_PLIST"
SIGNED_ENTITLEMENTS="$TMP/signed-entitlements.plist"
codesign -d --entitlements :- "$APP" > "$SIGNED_ENTITLEMENTS" 2>/dev/null
/usr/libexec/PlistBuddy -c 'Print :com.apple.application-identifier' "$SIGNED_ENTITLEMENTS"
/usr/libexec/PlistBuddy -c 'Print :com.apple.developer.team-identifier' "$SIGNED_ENTITLEMENTS"
/usr/libexec/PlistBuddy -c 'Print :com.apple.security.app-sandbox' "$SIGNED_ENTITLEMENTS"
file "$APP/Contents/MacOS/PrivateVoice Dictation"
file "$APP/Contents/Frameworks/libsherpa-onnx-c-api.dylib"
file "$APP/Contents/Frameworks/libonnxruntime.1.24.4.dylib"
codesign -vvv --deep --strict "$APP"
pkgutil --check-signature "$PKG"
xattr -lr "$APP" | grep -F 'com.apple.quarantine' && exit 1 || true
shasum -a 256 "$PKG"
com.shanghai3168.privatevoicedictation。public.app-category.productivity。com.apple.application-identifiercom.apple.developer.team-identifierkeychain-access-groups20260605.0216,不要再上传 20260604.0049 或 20260604.2353。91109,必须在组装 app 后、签名后、productbuild 前对 .app 执行 xattr -cr,并展开最终 .pkg 检查没有 com.apple.quarantine。Monetization / Pricing and Availability 设置。