feat(mobile): add Shipyard for iPhone
Last of the phone app's PRs. Stacked on #206 (packages/core), so its diff shows only the app; it retargets to main once #206 merges. It uses the box API from #207 and the relay from #208, and still works with older boxes.
mobile/: Expo SDK 58, expo-router, iOS first (Android later from the same code)
- Pair: scan the existing Settings ā Phone QR code in the app, paste its link, or open
berth://pair#ā¦. Each box is asked who it is before it's kept. - Needs you: every box's agents, waiting first, plus runs at a gate; a badge on the tab.
- Session: Chat (the conversation, from #207) or Screen; answer buttons (a permission reads as Allow / Always allow / Deny, keeping the option's number); Enter, Stop and arrow keys; a prompt.
- Runs: approve, reject, pick an attempt, cancel.
- Boxes: notifications Off / Needs you / Needs you and done (registers with the relay, then each box), Forget, Pair another box.
- Live: a version 2 box's event stream while the app is open; older boxes are read every 4 s like the web app. Push covers the background, and a tap opens the session or run, also from a cold start.
- Storage: tokens in the keychain (
AFTER_FIRST_UNLOCK_THIS_DEVICE_ONLY). - ATS:
NSAllowsLocalNetworkingplus an exception forts.net. NoNSAllowsArbitraryLoads; raw tailnet addresses aren't subject to ATS. - Demo (acme data, no box), for App Review.
- Shared code comes from
@berth/core/*(tsconfig paths, MetrowatchFolders, JestmoduleNameMapper).
Desktop: Settings ā Phone gets a Phone apps group (the phones the boxes notify, with which boxes, what they hear and when they last got one) with Remove. The pairing steps mention the app, and a note suggests turning ntfy off when a phone uses the app. New spec e2e/phone-apps.spec.ts.
Docs: phone guide section and changelog. The guide links to the relay section added in #207.
Checks:
mobile:pnpm typecheck,pnpm test(12), andpnpm export(Metro bundles the iOS app, which provespackages/coreresolves).- A new
mobileCI job runs the same three. - The app's full checks and build pass; the new e2e spec passed 3/3.
- The demo was driven in Chromium at iPhone size through a temporary web export (not committed).
Not verified, needs Apple setup:
- An EAS development build on a device.
- ATS for tailnet addresses, short names and
*.ts.net. - Streaming the event feed over Tailscale on iOS.
- A real APNs notification through the deployed relay.
Prerequisites:
- An Apple Developer org account, App ID
dev.berth.phoneand an APNs key (the same key goes to the relay). - An EAS account.
- A privacy policy URL and review notes for App Review.
Merging after #207/#208: each PR adds its own changelog bullet, CI job and AGENTS.md line in the same places, so expect small additive conflicts.
š¤ Generated with Claude Code