Skip to content

refactor(mobile-remote): add platform adapter boundary - #1220

Draft
beruro wants to merge 1 commit into
junyu/mobile-remote-controlfrom
junyu/ios-remote-shared
Draft

refactor(mobile-remote): add platform adapter boundary#1220
beruro wants to merge 1 commit into
junyu/mobile-remote-controlfrom
junyu/ios-remote-shared

Conversation

@beruro

@beruro beruro commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Problem

Mobile Remote currently mixes shared chat/session behavior with browser-only globals for OAuth, Web Storage, WebSocket construction, timers, visibility, navigation, and randomness. That prevents a lightweight Tauri iOS shell from reusing the proven Web Remote UI and reducers without copying logic. The synchronous browser implementation also hides async Keychain/config races and keeps an established relay socket alive while the app is backgrounded.

Solution

Introduce an injected MobileRemotePlatform boundary with runtime, auth, connection, and client-identity ports. Both browser entry points now render the same platform-neutral MobileRemoteRoot; browser OAuth/storage/socket behavior lives only under platform/browser.

Move timer, visibility, UUID, persistence, and socket ownership behind the port while preserving the existing Desktop EventStore, round, event, and tool identity model. Serialize connection writes, generation-guard slow bootstrap and commits, sequence logout cleanup after stale auth work, close foreground sockets while hidden, reconnect once on visibility return, and reject stale socket close events. Missing server permission tiers now fail closed to read-only.

Add static import-boundary tests plus lifecycle and race coverage for async storage, auth logout, background transport release, reconnect ownership, RPC bounds, and exact initialize/send wire shapes.

Potential risks

  • This is stacked on Web Remote PR feat(mobile-remote): add secure browser session control #1150 and must not merge before that base.
  • The native Tauri iOS adapter, Keychain implementation, Universal Links, APNs, encrypted offline cache, and real-device acceptance matrix are intentionally deferred to later single-responsibility PRs.
  • The shared connection port intentionally exposes the WebView DOM WebSocket contract for v1; a future native socket requirement would need a narrower transport interface.
  • Backgrounding now closes the Web Remote socket and foregrounding resubscribes, so a brief reconnect/loading transition is expected after returning.
  • Older Desktop builds that omit the permission tier now become read-only instead of inheriting full access.

Verification

  • pnpm typecheck — passed
  • pnpm lint — passed, including oxlint and ESLint with zero warnings
  • pnpm test -- src/modules/MobileRemote src/mobileRemoteEntry.test.ts src/modules/AppLogin/index.test.ts src/router/guards/AuthGuard.test.ts --reporter=dot — 33 files, 153 tests passed
  • pnpm build — passed; webpack compiled successfully
  • git diff --check origin/junyu/mobile-remote-control...HEAD — passed
  • Commit hooks: lint-staged, staged TypeScript check, circular dependency stats — passed

No screenshot is attached because this PR is an environment-boundary refactor with no intended visual change. Native iOS visual and real-device evidence belongs to the shell PR.

Audit

  • Architecture: all 10 layers reviewed in docs/architecture/mobile-remote-platform-boundary.md
  • Frontend UI: 0 fix / 5 keep with reason / 0 abstract
  • Lifecycle performance: pass for the shared boundary; native lifecycle and Keychain evidence remains a later hard gate

Stack

Base: #1150 (junyu/mobile-remote-control)
Next: Tauri iOS shell, OAuth callback, Keychain pairing, and device list.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant