feat(mobile-remote): add Tauri iOS shell - #1222
Closed
beruro wants to merge 7 commits into
Closed
Conversation
This was referenced Sep 4, 2026
Brings the platform boundary, the base branch's relay auth and mobile UX, and the review fixes onto the iOS shell. Conflict resolution: kept this branch's shared supabaseMobileAuthClient refactor, and carried the PKCE persistence fix into it — Supabase replaces the supplied storage adapter with memory storage when persistSession is false, which loses the code verifier across the OAuth redirect on native as well as in the browser. The Providers type import is the union of both sides. The Tauri runtime adapter implements the new portalContainer port member with the WebView document body.
The Tauri shell registers org2remote://pair and hands the raw link to the shared parser, but parsePairingLink only accepted orgii:// and http(s)://. Every native pairing link therefore failed to parse, and because MobileRemoteApp suppresses the stored-desktop bootstrap whenever a pairing intent is present, the phone also skipped loading its paired desktops and sat on the welcome screen with an empty Devices tab. Accept org2remote://pair and read the payload from the pair query parameter as well as the fragment, matching what the shell's hasOpaquePairPayload accepts.
src-tauri/binaries was committed as a symlink to a local checkout while staging the review fixes. CI stages the org2-pm sidecar into that path, and mkdir fails on the dangling link, so the Rust job died before clippy ran. The .gitignore entry uses a trailing slash, which matches a directory and not a symlink, so git add -A picked it up.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Web Remote already contains the Mobile Remote product flow, but there is no installable iOS host for it. Reusing the Desktop Tauri crate would also pull the local agent runtime, terminal, database, filesystem, and Desktop-only permissions onto the phone. The browser auth path additionally assumes redirect remounts and browser storage, so it cannot safely handle warm iOS callbacks or durable native credentials.
The first simulator launch also exposed two monorepo-specific launch defects: the generated Xcode build phase invoked
pnpm taurifrom a directory where pnpm selected the Desktop Tauri config, and the native window path was appended to adevUrlthat already contained the same path. Requiring a live Cloud OAuth round trip for every local simulator launch also blocked rapid UI and pairing development. The first bypass implementation then used a fixedlocal-developmentpairing owner, which made existing account-scoped Keychain pairings invisible and looked like pairing was lost on every launch.Solution
Add a separate lightweight Tauri iOS shell for ORG2 Remote and keep the agent running on the paired Desktop. The production native entry renders the existing MobileRemoteRoot and supplies only platform adapters for system-browser Supabase PKCE, cold and warm
org2remotedeep links, foreground WebSocket creation, and app-owned Security.framework Keychain commands.The shell uses product name ORG2 Remote, bundle id
org2ai.org2.remote, iOS 17+, and an independently generated Apple project. Native and Desktop webpack artifacts are isolated. Pairings are stored as a versioned, account-scoped local inventory capped at 20 entries with credential-free summaries and one active Desktop. Shared DevicesTab rows reuse Button, InlineAlert, SectionContainer, SectionRow, StatusDot, and existing typography/color tokens, including pending and failure states.The generated Xcode build script now changes into the mobile
src-tauridirectory and invokes the repository Tauri binary directly, preserving theorg2ai.org2.remoteconfiguration. The development URL is now origin-only whilemobile-native.htmlremains the window entry, so Tauri resolves the entry exactly once. Contract tests protect both invariants.Native development builds dynamically load an isolated development root with a synthetic identity. It never creates a Cloud auth client or writes an auth session, but it still consumes native pairing intents and renders the same MobileRemoteApp. Before React bootstraps connection state, the development entry resolves one stable Keychain owner: it keeps a populated development inventory, otherwise reuses the last persisted account user id, and falls back to
local-developmentonly when neither exists. This preserves both pairings made during bypass development and pairings created before the bypass. Production builds take the real MobileAuthGate branch, and the development module and synthetic identity are absent from the emitted production bundle. Settings hide the otherwise non-functional sign-out action while the bypass is active.This is stacked on #1220 and does not change the relay JSON-RPC protocol or move agent execution to iOS.
Potential risks
org2remote://auth/callbackoutside this repository.connect-srcretainswss:. Pairing validation and per-Desktop credentials remain the authorization boundary.Verification
Passed:
pnpm test -- src/modules/MobileRemote— 34 files, 178 testspnpm exec vitest run src/modules/MobileRemote/platform/tauri/iosLaunchConfigContract.test.ts— 1 file, 2 testspnpm exec eslint src/mobileRemoteNativeEntry.tsx src/modules/MobileRemote/dev/MobileRemoteDevelopmentRoot.tsx src/modules/MobileRemote/dev/MobileRemoteDevelopmentRoot.test.ts src/modules/MobileRemote/platform/tauri/tauriMobileRemotePlatform.test.tspnpm typecheckpnpm lintpnpm check:test-placement— 470 directories consistentpnpm buildpnpm build:mobile-nativelocal-development, local-development profile, or development resolver strings emittedcargo fmt --checkcargo checkcargo check --target aarch64-apple-ioscargo test --lib— 2 testscargo tree --depth 1— no Desktop workspace/runtime cratesBUILD SUCCEEDEDorg2ai.org2.remoteon iPhone 17 Pro / iOS 26.5git diff --checkNot run:
Audit
docs/architecture/ios-remote-shell.mddocs/feature-lifecycle-2026-09-02/IosRemoteShell.md