# Clipboard Sync Implementation Plan ## 1. Goal and Scope Build clipboard synchronization between the Android input method in `Xime/` and the Windows input method in `winxime/`, using a Docker-deployable HTTPS relay server. MVP scope: - Sync text clipboard content only. - Devices join the same sync chain by entering a sync code. - Remote content is written to the local system clipboard, equivalent to a user copy action. - Android additionally exposes received synced text in the IME candidate bar so users can commit it directly. - Users can enable/disable sync in settings and must configure an HTTPS relay server URL. Out of MVP scope: - Image/file/rich-text clipboard sync. - Automatic paste into the currently focused field. - Multi-user administration UI. - Cloud-hosted default relay. ## 2. Repository Layout Proposal Add a new backend service at workspace root: ```text sync-server/ Dockerfile docker-compose.yml src/ README.md ``` Client integrations: - Android: `Xime/app/src/main/java/com/kingzcheung/xime/settings`, `service`, `clipboard`, and `ui`. - Windows: `winxime/crates/winxime-server` for clipboard watching, WebSocket sync, and local clipboard writes. - Shared protocol docs: `CLIPBOARD_SYNC_PROTOCOL.md` or `sync-server/docs/protocol.md`. ## 3. Core Product Rules - A sync chain is a group of devices allowed to exchange clipboard events. - A sync code authorizes a device to join a chain. It must be random, revocable, and regeneratable. - The server must reject non-HTTPS client relay URLs. For local development, allow explicit debug-only overrides such as `http://localhost`. - Every synced item must be inserted into the local clipboard and local clipboard history where the platform/app supports it. - Android must show the latest remote synced text in the candidate bar. Tapping it should commit the text through the IME. - Sync must be opt-in and pauseable per device. ## 4. Architecture Use HTTPS REST for setup and WSS for live sync: ```text Android Xime <--- HTTPS/WSS ---> Sync Relay Server <--- HTTPS/WSS ---> WinXime ``` The server is a relay, not an editor. It authenticates devices, tracks sync chains, forwards clipboard events, and keeps short-lived replay data for reconnects. Recommended backend stack: - Rust with `tokio`, `axum`, `tower`, `serde`, and `sqlx`/SQLite for a small self-hosted binary. - Docker image exposing one port, with TLS handled either by the service or by a reverse proxy such as Caddy/Nginx. - WebSocket heartbeat, reconnect support, and event replay by last acknowledged sequence. ## 5. Protocol and Data Model REST endpoints: ```text GET /healthz POST /v1/chains POST /v1/chains/join POST /v1/chains/{chainId}/sync-code/rotate GET /v1/ws ``` Minimum tables/entities: ```text chains(id, code_hash, code_expires_at, created_at) devices(id, chain_id, name, platform, token_hash, last_seen_at) clipboard_events(id, chain_id, source_device_id, seq, content_type, content_hash, encrypted_payload, created_at, expires_at) ``` WebSocket event shape: ```json { "type": "clipboard.publish", "eventId": "uuid", "chainId": "uuid", "sourceDeviceId": "uuid", "sequence": 42, "contentType": "text/plain", "contentHash": "sha256:...", "payload": "base64 encrypted or encoded text", "createdAt": "2026-06-09T00:00:00Z", "ttlSeconds": 86400 } ``` Client requirements: - Ignore events from the same `deviceId`. - Cache recent `eventId` and `contentHash` values to prevent duplicate imports. - Suppress the next local clipboard-change callback after writing a remote event to avoid echo loops. - Limit payload size, for example 64 KiB for MVP. ## 6. Security Requirements - Relay URL validation must require `https://`; WebSocket connections must use `wss://`. - Store only token hashes and sync code hashes on the server. - Use TLS in all production deployments. - Prefer end-to-end encryption for clipboard payloads. At minimum, server-side event storage must be short-lived with a configurable TTL. - Sync codes should expire by default, for example after 10 minutes or after first successful join. Provide a manual rotate/revoke action. - Never log raw clipboard content on clients or server. ## 7. Android Implementation Plan 1. Add settings fields: enable sync, relay server URL, sync code, device name, connection status, pause/resume, and disconnect. 2. Persist config in `SettingsPreferences.kt` or a dedicated sync preferences class. 3. Add a `ClipboardSyncClient` responsible for HTTPS join, WSS connection, heartbeats, reconnects, and event acknowledgements. 4. Add a clipboard bridge that publishes local text copies and writes remote text via Android `ClipboardManager`. 5. Add a local synced-item state source consumed by `CandidateBar.kt` or the relevant keyboard UI layer. 6. When remote text arrives, update system clipboard and display it as a candidate. Tapping the candidate commits the text. 7. Add unit tests for URL validation, dedupe, echo-loop suppression, and event parsing. ## 8. Windows Implementation Plan 1. Add sync configuration to the existing Windows settings/config layer. 2. Implement a WebSocket sync client inside `winxime-server`. 3. Watch local clipboard changes from the server process and publish text changes. 4. Write remote text into the Windows clipboard using the existing server/background process. 5. Prevent loops by tagging remote writes and suppressing the resulting local notification. 6. Surface connection status in tray/setup UI if practical. 7. Validate with `cargo build --quiet`; do not use `unwrap()` or `expect()`. ## 9. Backend Implementation Plan 1. Scaffold `sync-server` with health check, config loading, structured logging, and Dockerfile. 2. Implement chain creation, sync-code join, device token issuance, and code rotation. 3. Implement authenticated WebSocket sessions with heartbeat and reconnect. 4. Implement event fan-out to online devices in the same chain. 5. Persist recent events for replay after reconnect, bounded by TTL and size limits. 6. Add Docker Compose example with a reverse proxy HTTPS configuration. 7. Add integration tests for join, auth failure, event fan-out, replay, TTL expiry, and duplicate suppression expectations. ## 10. Acceptance Criteria - A user can deploy the relay with Docker and access it over HTTPS. - Android and Windows settings reject plain `http://` relay URLs outside debug/local mode. - Device A can create or rotate a sync code; Device B can join using that code. - Copying text on Windows updates Android clipboard and shows the text in the Android candidate bar. - Copying text on Android updates the Windows clipboard. - The same event is not re-broadcast indefinitely. - Reconnect after network loss resumes sync without requiring a new sync code. - Raw clipboard content does not appear in logs. ## 11. Implementation Order for Agents 1. Protocol agent: finalize event schema, sync-code lifecycle, error codes, and protocol doc. 2. Backend agent: implement relay, Docker image, tests, and deployment README. 3. Windows agent: implement local clipboard watcher/writer and WSS client. 4. Android agent: implement settings, WSS client, clipboard bridge, and candidate bar display. 5. Integration agent: run end-to-end tests across one Android device/emulator, one Windows client, and the Docker relay.