Files

6.5 KiB

Phase 32: Setup Sharing System - Context

Gathered: 2026-04-13 Status: Ready for planning

## Phase Boundary

Setup 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 Decisions

Visibility 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: boolean column on setups table with visibility: text column (private/link/public). Column on table for query speed — discovery feed queries WHERE visibility = 'public'
  • D-03: Setting visibility to private deactivates (does not delete) all share links. Switching back to link reactivates them
  • D-04: Share links use secret tokens — the setup's numeric ID alone is not sufficient for link-shared access
  • 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 shares table 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 = true to visibility = '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 — Current setups table with isPublic boolean (line 118-127)
  • src/server/services/setup.service.ts — Setup CRUD with isPublic handling
  • src/server/services/discovery.service.ts — Discovery feed query using isPublic = true
  • src/server/services/profile.service.tsgetPublicSetupWithItems() for public viewing
  • src/client/routes/setups/$setupId.tsx — Setup detail page with current globe toggle (lines 177-203)
  • src/client/hooks/useSetups.tsusePublicSetup hook (line 67)
  • src/shared/schemas.ts — Zod schemas with isPublic field (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
  • useSetups hooks: Mutation patterns for updateSetup — extend for visibility changes
  • LucideIcon component: Icons like share-2, link, globe, lock available for visibility states
  • Modal patterns: Used elsewhere in the app (thread creation, item add) — reuse for share modal

Established Patterns

  • Service layer with DI (db as 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: New shares table + modify setups table (isPublic → visibility)
  • src/server/routes/setups.ts: New share link CRUD endpoints
  • src/server/routes/: New /s/:token route for short share URLs
  • src/server/services/setup.service.ts: Update queries from isPublic to visibility
  • src/server/services/discovery.service.ts: Update feed query
  • src/server/services/profile.service.ts: Update public setup query
  • src/client/routes/setups/$setupId.tsx: Replace globe toggle with share button + modal
  • src/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 to link reactivates 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)
## Deferred Ideas
  • 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