# PRD: Swap & Handoff, v2

| Field | Value |
|---|---|
| Status | Approved for build (week 6), reconciled to **v2.1** after release (see `08-release-validation.md`) |
| Replaces | v1 (`prd-v1.md`, kept) because of SI-1. See `decision-log.md` DL-1 |
| Owner | Ana (product) · reviewers: Ravi (trust & safety), Jo (platform), design |
| SIM | `sim-v2.html` (open the **Changes vs v1** button to see every difference) |
| Apps / roles / platforms | ShelfShare mobile · requester, owner · iOS + Android (phones) |

## Summary
Two neighbours agree a swap, pick a **Swap Spot** (a public venue) and a **1-hour time window**, check in on arrival and confirm the handoff with a one-time code. No member location ever leaves the phone.

## Use cases
| ID | Use case | Expected behaviour | SIM scenario | Status |
|---|---|---|---|---|
| UC-1 | Browse nearby | Books are grouped by **area** ("In your area", "Next area"). No metres and no "online now" dot. | `browse` | Decided (DL-1) |
| UC-2 | Request with a book | Pick one of your books to offer, plus an optional note. | `request` | Decided |
| UC-2b | Request with a credit | If you have ≥1 credit, offer a credit instead. The owner earns it when the handoff completes. | `credit` | Decided (competitive) |
| UC-3 | Accept / decline | Accepting **holds** both books (hidden from others). Declining releases the offered book or credit. | `accept`, `decline` | Decided |
| UC-3c | Counter-offer | The owner suggests a different book from the requester's shelf. | `counter` | Decided → **omitted at release, backlog BL-1** |
| UC-4 | Pick Swap Spot + time window | The owner proposes a spot (≤2 areas from both members) and a 1-hour window; the requester confirms. A window at capacity can't be chosen. **2.1:** fixed 30-min slots replace the windows (DL-4); the 1-hour design is kept in history. | `spot` | Decided → **Reconciled 2.1** |
| UC-5 | Check in + handoff code | Check-in is allowed inside the window. The on-device geofence sends `arrived:true` only. Once both are in, the requester shows a code and the owner enters it. The books change shelves. | `handoff` | Decided |
| UC-6 | Cancel / no-show | Cancelling more than 2 h before the window is free. A no-show (one side checked in, the other didn't by the end of the window) is logged privately; 3 no-shows trigger a reminder. | `noshow` | Decided (T&S) |
| UC-7 | Nothing nearby | Empty state: "List a book" + "Suggest a Swap Spot". | state: empty | Decided |
| UC-8 | Error / timeout | Error: inline message with Retry; held items stay held. Timeout: "Still trying…" with Cancel. | state: error / timeout | Decided |
| UC-9 | Report a problem | Private report from a completed or no-show swap, sent to trust & safety. | `report` | Decided (review R2) |
| UC-10 | Want list | ♡ on a book card adds it to the Want list; a push arrives when a matching title is listed nearby. Added during development and found by release validation. | `wantlist` | **Shipped, under privacy review** (V3) |

## Technical interactions
| Call / event | Status |
|---|---|
| `books.nearby {cell, rings}` | Exists (Places cells) |
| `swaps.create {bookId, offer:{bookId}|{credit:1}, note}` · `swaps.respond {id, accept|decline}` | New service, defined (week 7) |
| `spots.list {cells}` | Exists (Places venues, filter `hasShelf`) |
| `spots.slots {spotId, day}` | **Needs eng definition** at PRD time → defined as fixed 30 min slots (see v2.1) |
| `checkin.arrived {swapId}` | New. Boolean only, geofence on the device |
| `handoff.code.issue / verify` | Accounts one-time code, 10 min expiry (review R3) |
| events `swap.requested · swap.accepted · swap.spot_set · checkin.arrived · swap.completed · swap.no_show` | Event bus → Notify |

## Constraints and decisions
- Policy P-7 is respected by design: no coordinates leave the device. **[DECISION]** DL-1
- The "Quiet profile" PRD conflict is gone: no activity status is shown. **[FACT]** I1 closed
- Ratings: none, only private reports. **[DECISION]** competitive, not copied

## Versions
| Version | Week | Change |
|---|---|---|
| 1.0 | 2 | Outline, live "Meet now" (superseded) |
| 2.0 | 5 | Restructure: Swap Spots, credits, holds |
| 2.0.1 | 6 | Review: code expiry 10 min, report a problem, accessible code entry |
| 2.1 | 12 | Reconciled with release: fixed 30 min slots; UC-3c → backlog; UC-10 want-list documented |
