6.5 KiB
6.5 KiB
Phase 32: Setup Sharing System - Context
Gathered: 2026-04-13 Status: Ready for planning
## Phase BoundarySetup owners can toggle visibility between private, link-shared, and public. Share links use secret tokens with configurable expiration and revocation. Schema includes full future-proofing for person-specific shares, write permissions, and collaborative editing — but only read-only link sharing is enforced in this phase.
## Implementation DecisionsVisibility Model
- D-01: Three visibility levels:
private(owner only),link(accessible via share token, not discoverable),public(discoverable on feed/profiles) - D-02: Replace
isPublic: booleancolumn onsetupstable withvisibility: textcolumn (private/link/public). Column on table for query speed — discovery feed queriesWHERE visibility = 'public' - D-03: Setting visibility to
privatedeactivates (does not delete) all share links. Switching back tolinkreactivates them - D-04: Share links use secret tokens — the setup's numeric ID alone is not sufficient for link-shared access
Share Links
- D-05: Multiple share links can coexist per setup, each independent with its own token, expiration, and revocation status
- D-06: Share URLs:
/s/{token}(short URL for sharing) AND/setups/:id?share={token}(both work, short URL is primary for sharing) - D-07: Default link expiration: 14 days. Options when creating: 7 days, 14 days, 30 days, infinite
- D-08: Each link can be individually revoked without affecting other links
- D-09: Only read-only link shares are functional in this phase. Write permission exists in schema but is not enforced
Schema
- D-10: Full
sharestable created now: id, setupId, token, permission (read/write), expiresAt (nullable = infinite), userId (nullable — null = link share, set = person-specific share), createdAt, revokedAt (nullable) - D-11: Person-specific shares (userId column) exist in schema but are not used in this phase
- D-12: Write permission column exists but write-access is not enforced — no mutation permission checks
Share UX
- D-13: Share modal (Google Docs style) is the single UI for managing visibility AND share links
- D-14: Share icon button replaces the current globe public/private toggle on setup detail page. Icon reflects current visibility state via color/icon variation
- D-15: Modal contains: visibility picker (private/link/public), create share link with expiration picker, active share links list with copy/revoke actions
- D-16: Desktop and mobile use the same share icon button opening the same modal
Public Setup Presentation
- D-17: Link-shared setup viewer UX: Claude's discretion — will pick based on existing setup detail page patterns (subtle shared context vs. identical to public view)
- D-18: No changes to discovery feed or profile page visuals in this phase
- D-19: Discovery feed query updated from
isPublic = truetovisibility = 'public'— same behavior, new column
Claude's Discretion
- Viewer experience for link-shared setups (shared banner/badge vs. clean view) — pick what fits the existing design patterns
Folded Todos
None — no relevant todos matched this phase's scope.
<canonical_refs>
Canonical References
Downstream agents MUST read these before planning or implementing.
No external specs — requirements fully captured in decisions above.
Existing Implementation
src/db/schema.ts— Currentsetupstable withisPublicboolean (line 118-127)src/server/services/setup.service.ts— Setup CRUD withisPublichandlingsrc/server/services/discovery.service.ts— Discovery feed query usingisPublic = truesrc/server/services/profile.service.ts—getPublicSetupWithItems()for public viewingsrc/client/routes/setups/$setupId.tsx— Setup detail page with current globe toggle (lines 177-203)src/client/hooks/useSetups.ts—usePublicSetuphook (line 67)src/shared/schemas.ts— Zod schemas withisPublicfield (lines 88, 93)
</canonical_refs>
<code_context>
Existing Code Insights
Reusable Assets
- Setup detail page (
setups/$setupId.tsx): Has desktop + mobile button patterns for the share button replacement useSetupshooks: Mutation patterns forupdateSetup— extend for visibility changesLucideIconcomponent: Icons likeshare-2,link,globe,lockavailable for visibility states- Modal patterns: Used elsewhere in the app (thread creation, item add) — reuse for share modal
Established Patterns
- Service layer with DI (
dbas first param) for testability - Zod validation on route handlers via
@hono/zod-validator - React Query mutations with cache invalidation
- Detail pages (not panels) for complex interactions
Integration Points
src/db/schema.ts: Newsharestable + modifysetupstable (isPublic → visibility)src/server/routes/setups.ts: New share link CRUD endpointssrc/server/routes/: New/s/:tokenroute for short share URLssrc/server/services/setup.service.ts: Update queries from isPublic to visibilitysrc/server/services/discovery.service.ts: Update feed querysrc/server/services/profile.service.ts: Update public setup querysrc/client/routes/setups/$setupId.tsx: Replace globe toggle with share button + modalsrc/shared/schemas.ts: New share schemas, update setup schemas
</code_context>
## Specific Ideas- Share modal inspired by Google Docs share dialog — visibility picker at top, share links list below
- When visibility is set to
private, share links become inactive but aren't deleted — switching back tolinkreactivates them - Multiple shares coexist: e.g., one permanent read link + one 14-day read link simultaneously
- Future: person-specific shares should influence discovery algorithm (deferred)
- Person-specific shares influencing discovery feed algorithm — when direct shares exist between users, factor that into feed ranking. Belongs in a future personalization/social phase.
- Write-access share enforcement — collaborative editing requires conflict resolution, real-time sync, and mutation permission checks. Belongs in a dedicated collaborative editing phase.
- Person-specific share UI — inviting specific users by username/email to a setup. Needs user search/lookup. Future phase.
Phase: 32-setup-sharing-system Context gathered: 2026-04-13