Implement the Mac-to-iPhone terminal remoting product using Firebase for app/backend primitives and Google Cloud for media relay + compute. Core approach remains terminal-structured streaming (PTY diffs), with Cloud Run WebSocket relay as the v1 primary transport. WebRTC remains a future optimization path.
- Mac runtime now uses native
forkpty(replacedProcess+Pipe). - Relay transport now uses byte-safe base64 payloads:
terminal_output:{ type, encoding: "base64", data }terminal_input:{ type, encoding: "base64", data }terminal_resize:{ type, cols, rows }
- iOS terminal surface now uses
SwiftTermfor ANSI/VT rendering and input handling. - Transitional compatibility remains enabled for legacy text envelopes during migration.
- Selected intermediary: Option 2 (
Cloud Run WebSocket relay as primary transport). - Firebase/Firestore are the control plane (auth/session lifecycle), while terminal I/O uses relay WebSocket data plane.
- Relay room model for demo: iOS and Mac agent join
room=<macDeviceId>. - WebRTC negotiation is deferred; signaling schema remains for future migration.
- Identity and app trust bootstrap: Firebase Authentication (anonymous for demo, upgrade path to Sign in with Apple + Firebase custom claims).
- Session signaling/state: Cloud Firestore + Firebase Cloud Functions (2nd gen).
- Device pairing and tokens: Firestore + Cloud KMS-backed signing in Cloud Functions.
- Connectivity: Cloud Run relay WebSocket primary for v1; WebRTC/STUN/TURN deferred to v1.1.
- Observability: Cloud Logging + Cloud Monitoring + Error Reporting.
- Push/resume notifications: Firebase Cloud Messaging (FCM).
- iOS app distribution for demo: TestFlight; backend secrets in Secret Manager.
govibe-mac-agent(macOS local daemon/app)
- Opens/manages PTY (
zsh/bash/tmux). - Parses ANSI/VT and emits
TerminalDiff/TerminalSnapshot. - Connects to backend via HTTPS for control plane.
- Connects to Cloud Run relay WebSocket room and streams terminal output/input.
- Caches short replay buffer locally for resume.
govibe-ios(Swift)
- Uses Firebase SDK (Auth, Firestore, FCM).
- Native terminal renderer (grid/cell model).
- Keyboard + modifiers + touch cursor + paste/scrollback.
- Connects to Cloud Run relay WebSocket room for live terminal I/O.
- Handles foreground/background resume with session token refresh.
- Firebase/GCP backend
- Firestore collections for pairings, sessions, candidates, heartbeats.
- Cloud Functions endpoints for pairing/session lifecycle/token minting.
- TURN credentials minted ephemerally by Cloud Function.
- Optional Cloud Run “relay-tunnel” fallback for WebSocket tunneling when WebRTC fails.
devices/{deviceId}
platform(mac|ios)pubKeypairedWith[]createdAt,lastSeenAt
pairings/{pairId}
macDeviceId,iosDeviceIdcodeHash,expiresAtstatus(pending|confirmed)
sessions/{sessionId}
ownerDeviceId,peerDeviceIdstate(creating|active|grace|closed)createdAt,graceUntil,lastHeartbeaticePolicy,relayRequired
sessions/{sessionId}/signal/{msgId}
type(offer|answer|ice)fromDeviceIdpayloadcreatedAt
POST /pair/start
- Input:
macDeviceId - Output: short-lived
pairCode,pairId, expiry.
POST /pair/confirm
- Input:
pairId,pairCode,iosDeviceId, device proof. - Output: pairing confirmation + trusted device binding.
POST /session/create
- Input: requester device proof.
- Output:
sessionId, signaling refs, ICE config, ephemeral TURN creds.
POST /session/resume
- Input:
sessionId, device proof. - Output: resume authorization if
now <= graceUntil.
POST /session/close
- Input:
sessionId - Output: closed ack + cleanup trigger.
- iOS calls
session/create. - Both peers watch
sessions/{id}/signal. - Exchange SDP offer/answer + ICE candidates through Firestore docs.
- iOS and Mac join relay room
room=<macDeviceId>. - iOS sends
terminal_inputmessages; Mac sendsterminal_outputmessages.
- Firebase Auth required for all clients (anonymous in demo).
- Firestore Security Rules enforce:
- Device can only access sessions where it is participant.
- Write constraints on signaling message types/ownership.
- Pairing code hashed at rest; TTL enforced by Function + Firestore TTL.
- Session and TURN credentials are short-lived signed tokens.
- Secrets managed by Secret Manager; signing keys in Cloud KMS.
- On background, app sends
session state=grace. - Backend sets
graceUntil = now + 3m(default). - Agent keeps PTY alive and local buffer.
- FCM data message prompts quick resume path if network changes.
- On resume, iOS requests
session/resume; agent sends compact snapshot + tail replay.
- Input-to-echo p50 < 120ms on LTE/Wi-Fi.
- Typical active bandwidth < 80 KB/s.
- Reconnect success in grace window > 95%.
- Signaling setup median < 1.5s.
- Firebase project + iOS app registration.
- Firestore Native mode + TTL indexes.
- Cloud Functions (2nd gen, region
us-west1default). - Cloud Run relay service (min instances 0 for demo, scale-to-zero).
- TURN deployment:
- v1 demo: single-zone GCE Coturn + static IP.
- v1.1: multi-zone managed deployment + autoscaling.
- Monitoring dashboards + alerting (error rate, session failures, TURN auth failures).
- Pairing
- Valid code success, expired code rejection, replay attempt rejection.
- Session bring-up
- Session create success via backend.
- iOS and Mac successfully join same relay room and exchange terminal I/O.
- Terminal correctness
- Shell commands, Claude Code interaction, resize/orientation change.
- Alternate buffer apps (
vim,htop,less). - Unicode width/combining character cases.
- Resilience
- iOS background for 2 minutes then resume.
- Wi-Fi -> cellular handoff during active session.
- Firestore transient error recovery.
- Security
- Unauthorized device read/write blocked by Rules.
- Expired session token denied.
- TURN creds cannot be reused after expiry.
- New backend endpoints under
api.govibe.dev:
/pair/start,/pair/confirm,/session/create,/session/resume,/session/close.
- Firestore collections added:
devices,pairings,sessions, nestedsignal.
- Client protocol envelopes standardized:
TerminalDiff,TerminalSnapshot,InputEvent,SessionEvent.
- Demo targets one Mac + one iPhone.
- Firebase anonymous auth is acceptable for v1 demo.
- Default GCP region:
us-west1. - Keepalive grace window default: 3 minutes.
- Terminal-native-only scope; no arbitrary GUI window remoting in v1.
- Relay room default:
mac-demo-01until dynamic room negotiation is added.