feat(core): id-centric targeted approve/receive with output sinks

Stop returning grant strings across UniFFI; approve yields typed outcomes and
pull/resume use transfer id plus path or ReceiveOutputSink. Document the
pairing/targeted event catalog and cover Android MediaStore-style sink contracts.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-11 16:50:10 +02:00
parent 3b7fd3d468
commit d91820b867
14 changed files with 620 additions and 122 deletions

View File

@@ -429,6 +429,33 @@ wake-up notifications, not authoritative storage. They may be delivered at
least once; consumers deduplicate by stable ID and revision, then query current
state after reconnect or restart.
### 13.1 Pairing and targeted-transfer event catalog
Canonical kinds emitted on `CoreEvent` (phase → kind). Treat every event as a
wake-up: refresh durable state via list/get APIs. Mid-transfer progress polish
(live `verified_bytes` updates) may follow; this catalog is the readiness bar.
**`pairing`**
| Kind | Meaning |
|---|---|
| `eligibility-available` | Pairing eligibility exists for a peer after a completed authenticated invitation transfer. |
| `eligibility-removed` | Eligibility expired or was consumed/removed. |
| `relationship-changed` | Device-relationship state changed (pending, saved, revoked, blocked). Payload includes peer id and state. |
| `relationship-grant-rotated` | Local relationship grant generation advanced for a peer. |
| `saved-device-forgotten` | Local forget completed for a saved peer. |
| `device-blocked` | Peer was blocked locally. |
**`targeted_transfer`**
| Kind | Meaning |
|---|---|
| `offer-received` | A pre-approval offer is pending local approve/decline. |
| `offer-accepted` | Local approval completed; authorization is in core custody. |
| `offer-declined` | Local decline completed. |
See also [`crates/vnidrop/CORE_FLOW.md`](crates/vnidrop/CORE_FLOW.md) (same catalog, linked so the lists cannot fork).
Failures remain typed where callers can act differently, including:
- Device unavailable or offer timeout.