mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
Add iOS App Store build automation (#3451)
This commit is contained in:
+64
-12
@@ -26,17 +26,17 @@ Run the helper script from the repo root. It calls `tauri ios init` with the cor
|
||||
bash scripts/ios-init.sh
|
||||
```
|
||||
|
||||
`tauri ios init` scaffolds `app/src-tauri/gen/apple/`. That directory is **gitignored** (it contains bundle-identifier-specific Xcode project files that differ per developer account).
|
||||
`tauri ios init` scaffolds `app/src-tauri-mobile/gen/apple/`. That directory is **gitignored** (it contains bundle-identifier-specific Xcode project files that differ per developer account).
|
||||
|
||||
### Info.plist privacy keys
|
||||
|
||||
`tauri ios init` creates a generated `Info.plist` at:
|
||||
|
||||
```
|
||||
app/src-tauri/gen/apple/<bundle-id>_iOS/Info.plist
|
||||
app/src-tauri-mobile/gen/apple/<bundle-id>_iOS/Info.plist
|
||||
```
|
||||
|
||||
You must copy the three privacy keys from `app/src-tauri/Info.ios.plist` into that generated file before building:
|
||||
`scripts/ios-init.sh` injects these privacy keys into the generated plist:
|
||||
|
||||
```xml
|
||||
<key>NSCameraUsageDescription</key>
|
||||
@@ -49,10 +49,6 @@ You must copy the three privacy keys from `app/src-tauri/Info.ios.plist` into th
|
||||
<string>OpenHuman uses on-device speech recognition to transcribe your voice messages.</string>
|
||||
```
|
||||
|
||||
**Option A (recommended for now):** Manual copy after each `tauri ios init` run.
|
||||
|
||||
**Option B (automate in a follow-up PR):** Set the `bundle.iOS.template` key in `app/src-tauri/tauri.conf.json` to point at a hand-crafted `Info.plist` template once Tauri v2 stabilises its iOS template pipeline. Until that happens, Option A is simpler and less brittle.
|
||||
|
||||
---
|
||||
|
||||
## Development workflow
|
||||
@@ -81,6 +77,63 @@ pnpm tauri:ios:build
|
||||
|
||||
---
|
||||
|
||||
## App Store Connect delivery
|
||||
|
||||
`.github/workflows/ios-appstore.yml` builds a signed `iphoneos` archive, exports an IPA, uploads the IPA to App Store Connect/TestFlight with `altool`, and stores the IPA + dSYMs as GitHub Actions artifacts.
|
||||
|
||||
Run it from GitHub Actions > iOS App Store. Inputs:
|
||||
|
||||
- `ref` -- optional git ref to build.
|
||||
- `build_number` -- optional `CFBundleVersion`; defaults to `github.run_number`.
|
||||
- `upload_to_app_store_connect` -- set `false` for a signed archive/export dry run.
|
||||
|
||||
Required GitHub environment: `App-Store`.
|
||||
|
||||
Required secrets:
|
||||
|
||||
- `APPLE_TEAM_ID` -- Apple Developer Team ID.
|
||||
- `IOS_KEYCHAIN_PASSWORD` -- temporary CI keychain password.
|
||||
- `IOS_DISTRIBUTION_CERTIFICATE_BASE64` -- base64-encoded `.p12` Apple Distribution certificate.
|
||||
- `IOS_DISTRIBUTION_CERTIFICATE_PASSWORD` -- password for that `.p12`.
|
||||
- `IOS_APPSTORE_PROVISIONING_PROFILE_BASE64` -- base64-encoded App Store provisioning profile for `com.tinyhumansai.openhuman`.
|
||||
- `APP_STORE_CONNECT_API_KEY_ID` -- App Store Connect API key ID.
|
||||
- `APP_STORE_CONNECT_ISSUER_ID` -- App Store Connect issuer ID.
|
||||
- `APP_STORE_CONNECT_API_PRIVATE_KEY_BASE64` -- base64-encoded `AuthKey_<key id>.p8`.
|
||||
|
||||
Local encoding helpers:
|
||||
|
||||
```bash
|
||||
base64 -i ios_distribution.p12 | pbcopy
|
||||
base64 -i OpenHuman_AppStore.mobileprovision | pbcopy
|
||||
base64 -i AuthKey_XXXXXXXXXX.p8 | pbcopy
|
||||
```
|
||||
|
||||
The workflow uploads a build to App Store Connect. It does not submit the build for App Review; that remains a deliberate App Store Connect action.
|
||||
|
||||
### Local upload script
|
||||
|
||||
After downloading an App Store provisioning profile and App Store Connect API key, you can build/export/upload from this Mac:
|
||||
|
||||
```bash
|
||||
TEAM_ID=XXXXXXXXXX \
|
||||
IOS_APPSTORE_PROVISIONING_PROFILE_PATH=/path/to/OpenHuman_AppStore.mobileprovision \
|
||||
ASC_KEY_ID=XXXXXXXXXX \
|
||||
ASC_ISSUER_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \
|
||||
ASC_KEY_PATH=/path/to/AuthKey_XXXXXXXXXX.p8 \
|
||||
UPLOAD=1 \
|
||||
scripts/ios-appstore-upload.sh
|
||||
```
|
||||
|
||||
Use `UPLOAD=0` to stop after IPA export.
|
||||
|
||||
### Updating without a new App Store build
|
||||
|
||||
iOS cannot self-update native code or replace the installed app binary outside App Store/TestFlight distribution. For OpenHuman, this means changes to Rust, Tauri plugins, native permissions, bundled frontend code, or the app shell need a new reviewed build.
|
||||
|
||||
Safe server-side updates include model/provider configuration, feature flags, prompt/content changes, remote data, and backend behavior that the shipped client already knows how to render. Be conservative with remote JavaScript or plugin-style features: Apple allows some software/content delivered outside the binary under specific rules, but it must stay within App Review limits and must not expose native platform APIs without permission.
|
||||
|
||||
---
|
||||
|
||||
## Pairing flow
|
||||
|
||||
```
|
||||
@@ -109,6 +162,7 @@ Desktop iOS
|
||||
```
|
||||
|
||||
Transport selection (handled by `TransportManager`):
|
||||
|
||||
1. LAN HTTP -- fast, zero-latency, requires same network.
|
||||
2. Socket.io tunnel -- E2E encrypted via XChaCha20-Poly1305 over X25519 key agreement.
|
||||
3. Cloud HTTP -- fallback when LAN and tunnel are unreachable.
|
||||
@@ -130,20 +184,18 @@ Transport selection (handled by `TransportManager`):
|
||||
- Single backend instance only (no multi-region failover).
|
||||
- No APNs push notifications -- app must be foregrounded for real-time delivery.
|
||||
- Event-driven pairing detection on the desktop side uses 2-second polling until an SSE/socket event bridge lands.
|
||||
- Xcode signing must be set manually in the generated project (no CI automation yet).
|
||||
|
||||
---
|
||||
|
||||
## CI
|
||||
|
||||
The `.github/workflows/ios-compile.yml` workflow runs on every PR that touches iOS-related paths. It provides:
|
||||
The `.github/workflows/ios-compile.yml` workflow runs as an iOS compile sanity check. It provides:
|
||||
|
||||
- **Hard gate:** `cargo check` on the host target for `app/src-tauri` and `packages/tauri-plugin-ptt`.
|
||||
- **Hard gate:** `cargo check` on the iOS target for `app/src-tauri-mobile` and a host-target check for `packages/tauri-plugin-ptt`.
|
||||
- **Hard gate:** TypeScript compile (`pnpm compile`).
|
||||
- **Hard gate:** iOS-related Vitest suites.
|
||||
- **Soft gate (`continue-on-error: true`):** `cargo check --target aarch64-apple-ios` -- this catches gross API breakage but may fail on third-party C deps that need full Xcode. Failures are flagged but do not block merge.
|
||||
|
||||
Full iOS builds (simulator + device) require macOS runners with Xcode installed. This is tracked as a follow-up to this PR.
|
||||
Full signed App Store builds run through `.github/workflows/ios-appstore.yml`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# App Review Information Draft
|
||||
|
||||
Fastlane uploads `fastlane/metadata/review_information/` automatically when that directory exists. Keep draft review details outside the Fastlane metadata tree until the real review contact email and phone number are ready.
|
||||
|
||||
## Contact
|
||||
|
||||
- First name: Steven
|
||||
- Last name: Enamakel
|
||||
- Email: TODO
|
||||
- Phone: TODO
|
||||
|
||||
## Notes
|
||||
|
||||
OpenHuman for iPhone is a companion app for the OpenHuman desktop runtime.
|
||||
|
||||
To review the app:
|
||||
|
||||
1. Install and open the submitted iOS build.
|
||||
2. Install and open the OpenHuman desktop app on macOS, Windows, or Linux.
|
||||
3. In the desktop app, open Settings > Devices and choose Pair phone.
|
||||
4. Use the iPhone app to scan the pairing QR code.
|
||||
5. After pairing, test text chat and push-to-talk voice input from the iPhone.
|
||||
|
||||
The iOS app requires camera permission for QR pairing and microphone permission for push-to-talk voice input. It does not function as a standalone assistant without a paired OpenHuman desktop runtime.
|
||||
@@ -0,0 +1,104 @@
|
||||
# App Store Listing
|
||||
|
||||
This is the prepared product-page kit for the OpenHuman iOS companion app.
|
||||
|
||||
## App Store Connect Fields
|
||||
|
||||
- App name: `OpenHuman`
|
||||
- Subtitle: `AI companion for your desktop`
|
||||
- Bundle ID: `com.tinyhumansai.openhuman`
|
||||
- SKU: `com.tinyhumansai.openhuman`
|
||||
- Primary category: `Productivity`
|
||||
- Secondary category: `Utilities`
|
||||
- Copyright: `2026 Tiny Humans AI`
|
||||
- Support URL: `https://tinyhumans.ai/openhuman`
|
||||
- Marketing URL: `https://tinyhumans.ai/openhuman`
|
||||
- Privacy Policy URL: `https://tinyhumans.gitbook.io/openhuman/legal/privacy-policy`
|
||||
|
||||
Metadata files live in `fastlane/metadata/en-US/`.
|
||||
|
||||
## Description
|
||||
|
||||
Use `fastlane/metadata/en-US/description.txt`.
|
||||
|
||||
## Keywords
|
||||
|
||||
Use `fastlane/metadata/en-US/keywords.txt`.
|
||||
|
||||
## App Icon
|
||||
|
||||
The App Store icon is already included in the iOS build:
|
||||
|
||||
- `app/src-tauri-mobile/icons/store/appstore.png`
|
||||
- `app/src-tauri-mobile/icons/ios/AppIcon.appiconset/1024.png`
|
||||
|
||||
Both are 1024 x 1024 PNG assets.
|
||||
|
||||
## Screenshots
|
||||
|
||||
Generate the 6.9-inch iPhone screenshot set:
|
||||
|
||||
```bash
|
||||
pnpm --dir app exec node ../scripts/ios-appstore-assets.mjs
|
||||
```
|
||||
|
||||
Upload the generated files from:
|
||||
|
||||
```text
|
||||
fastlane/screenshots/en-US/
|
||||
```
|
||||
|
||||
Use these in App Store Connect under the iPhone 6.9-inch display screenshot slot.
|
||||
|
||||
You can also push the generated screenshots with Fastlane:
|
||||
|
||||
```bash
|
||||
ASC_KEY_ID=9KD934428C \
|
||||
ASC_ISSUER_ID=69a6de8b-cc07-47e3-e053-5b8c7c11a4d1 \
|
||||
ASC_KEY_PATH=/Users/enamakel/Downloads/AuthKey_9KD934428C.p8 \
|
||||
ASC_APP_VERSION=1.0 \
|
||||
fastlane ios push_screenshots
|
||||
```
|
||||
|
||||
Metadata can be pushed with the App Store Connect API helper:
|
||||
|
||||
```bash
|
||||
ASC_KEY_ID=9KD934428C \
|
||||
ASC_ISSUER_ID=69a6de8b-cc07-47e3-e053-5b8c7c11a4d1 \
|
||||
ASC_KEY_PATH=/Users/enamakel/Downloads/AuthKey_9KD934428C.p8 \
|
||||
ASC_APP_ID=6761229174 \
|
||||
scripts/ios-appstore-metadata.mjs
|
||||
```
|
||||
|
||||
## App Review Notes
|
||||
|
||||
Use `fastlane/metadata/review_information/notes.txt`.
|
||||
|
||||
Before submitting, replace the TODO contact fields in:
|
||||
|
||||
- `fastlane/metadata/review_information/email_address.txt`
|
||||
- `fastlane/metadata/review_information/phone_number.txt`
|
||||
|
||||
## Privacy Answers Draft
|
||||
|
||||
Use this as the starting point for App Privacy in App Store Connect:
|
||||
|
||||
- Camera: used to scan the desktop pairing QR code.
|
||||
- Microphone: used for push-to-talk voice messages.
|
||||
- Speech recognition: used to transcribe voice messages.
|
||||
- Identifiers/session data: pairing/session data may be used to connect the phone to the paired OpenHuman desktop runtime.
|
||||
- User content: messages and voice transcripts are sent to the paired OpenHuman runtime to provide assistant responses.
|
||||
|
||||
Before submitting, make sure the App Privacy answers match the production backend/runtime behavior.
|
||||
|
||||
## Current Apple Requirements Checked
|
||||
|
||||
Apple currently requires one to ten screenshots for each platform localization, accepts `.jpeg`, `.jpg`, and `.png`, and allows high-resolution iPhone screenshots to scale down to smaller sizes. Apple lists the 6.9-inch portrait sizes as accepted high-resolution iPhone screenshot sizes.
|
||||
|
||||
Apple currently limits:
|
||||
|
||||
- App name: 30 characters
|
||||
- Subtitle: 30 characters
|
||||
- Promotional text: 170 characters
|
||||
- Description: 4000 characters
|
||||
- Keywords: 100 bytes
|
||||
@@ -0,0 +1,47 @@
|
||||
# OpenHuman iOS Privacy Policy Draft
|
||||
|
||||
Last updated: June 6, 2026
|
||||
|
||||
OpenHuman for iPhone is a companion app for the OpenHuman desktop runtime. It lets you pair your phone with your desktop OpenHuman app, send text messages, and use push-to-talk voice input.
|
||||
|
||||
The App Store Connect listing uses the published TinyHumans privacy policy:
|
||||
|
||||
https://tinyhumans.gitbook.io/openhuman/legal/privacy-policy
|
||||
|
||||
This draft is retained as iOS-specific reference material for review notes and privacy-answer preparation.
|
||||
|
||||
## Data The App Uses
|
||||
|
||||
OpenHuman for iPhone may process:
|
||||
|
||||
- Pairing data, such as a short-lived QR pairing token and device connection identifiers.
|
||||
- Messages you send to your paired OpenHuman desktop runtime.
|
||||
- Voice transcripts created from push-to-talk input.
|
||||
- Basic connection state needed to route requests to the paired desktop runtime.
|
||||
|
||||
## Permissions
|
||||
|
||||
The iOS app requests:
|
||||
|
||||
- Camera access to scan the desktop pairing QR code.
|
||||
- Microphone access for push-to-talk voice messages.
|
||||
- Speech recognition access to transcribe push-to-talk messages.
|
||||
|
||||
## How Data Is Used
|
||||
|
||||
Data is used to:
|
||||
|
||||
- Connect your phone to your paired OpenHuman desktop runtime.
|
||||
- Send your messages and voice transcripts to the paired runtime.
|
||||
- Receive assistant responses from the paired runtime.
|
||||
- Maintain connection health while the app is in use.
|
||||
|
||||
## Desktop Runtime
|
||||
|
||||
The iPhone app is not a standalone assistant. Your long-term workspace, memory, configuration, and integrations are managed by your OpenHuman desktop setup. The exact data handling behavior depends on how you configure OpenHuman desktop, including whether you use managed services, local providers, or custom providers.
|
||||
|
||||
## Contact
|
||||
|
||||
For support, visit:
|
||||
|
||||
https://tinyhumans.ai/openhuman
|
||||
Reference in New Issue
Block a user