initial commit

This commit is contained in:
2026-08-27 15:38:55 +02:00
commit 0426b6eeec
23 changed files with 1635 additions and 0 deletions
+133
View File
@@ -0,0 +1,133 @@
# clipsync Protocol v1 (MVP)
This document defines an implementation-friendly first protocol for clipboard sync.
## Transport
- Discovery: UDP broadcast on port `45821`
- Session: TCP on port `45821`
- Payload encoding: UTF-8 JSON frames
- Frame format on TCP: 4-byte big-endian length prefix + JSON bytes
## Versioning
Each message includes:
- `version`: protocol version string, initially `"1"`
- `type`: message type
- `request_id`: unique string per request/response pair where relevant
- `device_id`: sender stable ID
- `timestamp_ms`: unix epoch milliseconds
## Discovery message (UDP)
`DISCOVERY_ANNOUNCE`
```json
{
"version": "1",
"type": "DISCOVERY_ANNOUNCE",
"device_id": "desktop-uuid",
"device_name": "workstation",
"platform": "linux|windows",
"tcp_port": 45821,
"capabilities": ["clipboard:text"],
"timestamp_ms": 0
}
```
Android listens for these packets and shows peers.
## Pairing flow (TCP)
### 1) HELLO
Both peers exchange:
- protocol version
- device info
- ephemeral nonce
### 2) PAIR_REQUEST
Unpaired side sends pairing request including:
- public key
- pairing method (`"pin"` or `"qr"`)
### 3) PAIR_CHALLENGE
Responder sends short code metadata (or QR payload hash) and challenge nonce.
### 4) PAIR_CONFIRM
Requester returns challenge response.
### 5) PAIR_ACCEPT
Responder confirms trust and stores remote public key.
After `PAIR_ACCEPT`, both devices persist:
- `peer_device_id`
- `peer_public_key`
- `paired_at`
## Session messages
### `CLIP_UPDATE`
```json
{
"version": "1",
"type": "CLIP_UPDATE",
"request_id": "req-123",
"device_id": "android-uuid",
"timestamp_ms": 0,
"origin_device_id": "android-uuid",
"content_type": "text/plain",
"encoding": "utf-8",
"content_hash": "sha256:...",
"content": "clipboard text",
"sequence": 42
}
```
Rules:
- Only sync `text/plain` in MVP.
- Ignore messages with known `content_hash` from recent history.
- Ignore message if `origin_device_id` equals local device id (echo prevention).
### `ACK`
Acknowledges accepted `request_id`.
### `ERROR`
Contains error code and message (`UNPAIRED`, `UNSUPPORTED_VERSION`, `INVALID_MESSAGE`, `RATE_LIMITED`).
### `PING` / `PONG`
Keepalive every 15 seconds. Drop and reconnect after timeout.
## Security baseline
- Reject non-paired peers for clipboard writes.
- Encrypt session channel (TLS or Noise).
- Enforce max payload size (e.g., 1 MiB for MVP text).
- Apply rate limits per peer.
## Current daemon behavior (implemented)
- Server sends `HELLO` immediately on TCP connect.
- First client message must be `HELLO` (else `ERROR: INVALID_MESSAGE`).
- After `HELLO`, server accepts either:
- `PAIR_REQUEST` and responds with `PAIR_ACCEPT` (while persisting peer trust), or
- `CLIP_UPDATE` for already-paired peers.
- `CLIP_UPDATE` from unknown peers is rejected with `ERROR: UNPAIRED`.
- While connected, server polls local clipboard and emits `CLIP_UPDATE` to the connected paired peer when local text changes.
- Incoming paired `CLIP_UPDATE` (`content_type = text/plain`) is applied to local OS clipboard.
- Inbound `CLIP_UPDATE` messages are deduplicated using `content_hash` (with a fallback hash for missing values).
- Inbound `CLIP_UPDATE` messages are rate-limited per peer; over-limit updates return `ERROR: RATE_LIMITED`.
- Keepalive is implemented: server sends periodic `PING`, responds to inbound `PING` with `PONG`, and drops idle sessions after timeout.
+39
View File
@@ -0,0 +1,39 @@
# Proposed Repository Layout
## Top-level
- `android-app/`
- `desktop-daemon/`
- `docs/`
## Android app layout
- `android-app/app/src/main/java/.../`
- `discovery/` UDP discovery listener and peer cache
- `pairing/` pairing workflow and trust store
- `sync/` persistent session and clipboard sync engine
- `service/` foreground/background lifecycle service
- `ui/` peer list, pairing, status
## Desktop daemon layout (Odin)
- `desktop-daemon/src/main.odin`
- `desktop-daemon/src/net/`
- discovery broadcaster/listener
- tcp session + framing
- `desktop-daemon/src/protocol/`
- message schemas and handlers
- `desktop-daemon/src/pairing/`
- key management + pairing flow
- `desktop-daemon/src/clipboard/`
- Linux backend
- Windows backend
- `desktop-daemon/src/storage/`
- paired peers file/db persistence
- `desktop-daemon/src/runtime/`
- daemon loop, reconnect, retry policies
## Config files planned
- `desktop-daemon/clipsync.toml` (optional override)
- Android app settings screen for default port and discovery toggles