# Plan 32-02 Summary: Share Link Backend

**Status:** Complete
**Commit:** da159d1

## What was done

1. **Share service** (`src/server/services/share.service.ts`):
   - `createShareLink`: 128-bit random base64url token, configurable expiration
   - `getShareLinks`: Lists all shares for a setup (ownership verified)
   - `revokeShareLink`: Sets revokedAt (ownership verified via join)
   - `validateShareToken`: Returns setupId/permission, rejects expired/revoked/nonexistent
   - `deactivateShareLinks`: Bulk revoke all active links for a setup
   - `reactivateShareLinks`: Clears revokedAt on non-expired shares

2. **Visibility transition side effects** (`src/server/services/setup.service.ts`):
   - `updateSetup` now detects visibility transitions and calls deactivate/reactivate
   - Uses dynamic import to avoid circular dependency

3. **New function** `getSetupWithItemsById` for share-token-authorized access (no user/visibility check)

4. **API routes** (added to `src/server/routes/setups.ts`):
   - `POST /api/setups/:id/shares` — Create share link (auth required)
   - `GET /api/setups/:id/shares` — List share links (auth required)
   - `DELETE /api/setups/:id/shares/:shareId` — Revoke share link (auth required)

5. **Public endpoints** (added to `src/server/index.ts`):
   - `GET /api/shared/:token` — Access setup via share token (no auth)
   - `GET /s/:token` — Short URL redirect to `/setups/:id?share=:token`
   - Auth middleware skip for `/api/shared/` and rate limiting applied

6. **Share schema** (`src/shared/schemas.ts`):
   - `createShareLinkSchema` with `expiresInDays: 7 | 14 | 30 | null`

7. **Tests** (`tests/services/share.service.test.ts`):
   - 16 tests covering all service functions and visibility transitions
   - All pass (62/62 across 5 affected test files)

## Verification

- `bun run lint`: Passes
- All share service tests pass (16/16)
- All affected tests pass (62/62 across 5 files)
