# PRD: Swap & Handoff, v1 (outline)

| Field | Value |
|---|---|
| Status | **Superseded by v2** (kept unchanged, see `decision-log.md` DL-1) |
| Version | 1.0 outline, week 2 |
| Owner | Ana (product) |
| SIM | `sim-v1.html` |
| Apps / roles / platforms | ShelfShare mobile app · requester, owner · iOS + Android (phones) |

## Summary
Help two neighbours meet *now* to swap books. Both see each other's live position on a map once a swap is accepted. A one-time code confirms the handoff.

## Use cases
| ID | Use case | Expected behaviour | SIM scenario | Status |
|---|---|---|---|---|
| UC-1 | Browse nearby | List of books sorted by distance (e.g. "120 m"). Each owner shows a green "nearby now" dot when the app is open. | `browse` | Proposed |
| UC-2 | Request a swap | On a book, tap *Request swap*, pick one of your books to offer, add an optional note. | `request` | Proposed |
| UC-3 | Accept / decline | The owner gets a notification and accepts or declines. A decline returns the offered book to available. | `accept`, `decline` | Proposed |
| UC-4 | Meet now (live) | After acceptance, both phones show a live map with both members' dots. Positions update every 5 s until the handoff or 60 min. | `meetnow` | Proposed |
| UC-5 | Handoff code | The requester shows a 6-digit code and the owner enters it. Both books swap shelves and both get "Swap complete". | `handoff` | Proposed |
| UC-6 | Cancel / no-show | Either side cancels. If the code is not entered within 60 min, the swap expires. | `cancel` | Proposed |
| UC-7 | Nothing nearby | Empty state with "Widen radius" and "List a book". | state: empty | Proposed |
| UC-8 | Error / timeout | Inline error with Retry. A timeout is shown separately from an error. | state: error / timeout | Proposed |

## Technical interactions (as drawn in SIM v1)
| Call / event | Exists? | Note |
|---|---|---|
| `books.nearby {lat, lon, radius}` | partly | The Places service returns *neighbourhood cells*, not metres. **[HYPOTHESIS]** can be extended |
| `swaps.create`, `swaps.respond` | no | New service; engineering to define |
| `location.stream.publish / subscribe` | **no** | **NEEDS ENG DEFINITION.** Real-time position sharing between two members |
| `handoff.code.issue / verify` | no | New. Code issued on the server |
| events `swap.requested`, `swap.accepted`, `location.updated`, `swap.completed` | partly | The Notifications service handles push; there is no live channel |

## Assumptions
- A1 Members accept sharing their live location with the other party during an accepted swap.
- A2 The platform can stream positions every 5 s at an acceptable battery and server cost.
- A3 Meeting "wherever we both are" is safe enough.

## Open questions
- Q1 Privacy of live location (Trust & safety). Q2 Swaps without a book in return.
