# 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)