Files
vnidrop/shared/docs/saved-devices-ui-contract.md
Hammed Abass b9884b566a feat(shared): enable experimental saved-devices on desktop
Surface Settings → Experimental on Windows/Linux Compose, keep generic
Desktop hosts gated off, and assert path-based targeted receive when no
output sink is available.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-11 19:51:48 +02:00

47 lines
2.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Saved devices UI contract (KMP + Apple)
Experimental product UI for saved devices and targeted transfers. Rust UniFFI is the source of behaviour; this document keeps Apple and KMP interaction semantics aligned.
Status: experimental (default off in KMP Settings).
## Vocabulary
Use **saved device**, **device relationship**, **targeted transfer**, **invitation transfer**. Do not say contact, person, or account in UI copy.
## Experimental gate
- KMP Android / Windows / Linux: Settings → Experimental → Saved devices, preference default **off**, persisted.
- KMP generic desktop host (`UiPlatform.Desktop`, e.g. macOS JVM): experimental UI **hidden**.
- Apple: gate shape is platform-owned; semantics below still apply when the feature is enabled.
## Events are wake-ups
`pairing` and `targeted_transfer` core events (and KMP `CoreSignal.PairingChanged` / `TargetedTransferChanged`) mean: refresh durable state via list/get APIs. Do not treat event payloads as authoritative storage. Deduplicate by event id/revision when needed.
Relevant kinds:
- **pairing:** `eligibility-available`, `eligibility-removed`, `relationship-changed`, `relationship-grant-rotated`, `saved-device-forgotten`, `device-blocked`
- **targeted_transfer:** `offer-received`, `offer-accepted`, `offer-declined`
## Pairing
After a completed invitation transfer, eligibility may exist. The user may accept or decline. Mutual consent yields a saved device. Pending eligibility/relationship state must remain reachable if an in-flow prompt is dismissed.
## Targeted approve / pull
1. List pending targeted offers (or react to `offer-received`).
2. `respond_to_targeted_offer(transfer_id, accepted)` → typed outcome only:
- `Approved { transfer_id }`
- `Declined`
- `AlreadySettled { transfer_id }`
3. Never accept or display authorization/grant strings across the public binding.
4. Pull / resume with **transfer id + destination** (path or output sink).
- Android KMP: invitation MediaStore Downloads sink for the experimental MVP receive.
- Windows / Linux KMP: configured filesystem receive folder path when no output sink is provided.
## Out of this contracts MVP chrome
Resume / cancel / delete / grant-rotate UI, background notifications, and mid-transfer progress polish may follow without changing the approve/pull rules above.
Block is available from the Saved devices area. Unblock is not required for the KMP MVP chrome when the product surface does not already expose blocked-device management.