docs(32): capture phase context
This commit is contained in:
120
.planning/phases/32-setup-sharing-system/32-CONTEXT.md
Normal file
120
.planning/phases/32-setup-sharing-system/32-CONTEXT.md
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
# Phase 32: Setup Sharing System - Context
|
||||||
|
|
||||||
|
**Gathered:** 2026-04-13
|
||||||
|
**Status:** Ready for planning
|
||||||
|
|
||||||
|
<domain>
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
</domain>
|
||||||
|
|
||||||
|
<decisions>
|
||||||
|
## 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
|
||||||
|
|
||||||
|
### 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 `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.
|
||||||
|
|
||||||
|
</decisions>
|
||||||
|
|
||||||
|
<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.ts` — `getPublicSetupWithItems()` for public viewing
|
||||||
|
- `src/client/routes/setups/$setupId.tsx` — Setup detail page with current globe toggle (lines 177-203)
|
||||||
|
- `src/client/hooks/useSetups.ts` — `usePublicSetup` 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>
|
||||||
|
|
||||||
|
<specifics>
|
||||||
|
## 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)
|
||||||
|
|
||||||
|
</specifics>
|
||||||
|
|
||||||
|
<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.
|
||||||
|
|
||||||
|
</deferred>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Phase: 32-setup-sharing-system*
|
||||||
|
*Context gathered: 2026-04-13*
|
||||||
141
.planning/phases/32-setup-sharing-system/32-DISCUSSION-LOG.md
Normal file
141
.planning/phases/32-setup-sharing-system/32-DISCUSSION-LOG.md
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
# Phase 32: Setup Sharing System - Discussion Log
|
||||||
|
|
||||||
|
> **Audit trail only.** Do not use as input to planning, research, or execution agents.
|
||||||
|
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
|
||||||
|
|
||||||
|
**Date:** 2026-04-13
|
||||||
|
**Phase:** 32-Setup Sharing System
|
||||||
|
**Areas discussed:** Visibility model, Share UX & controls, Schema future-proofing, Public setup presentation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Visibility Model
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Unlisted link (no token) | Setup ID in URL is the 'key'. Simple but IDs are guessable. | |
|
||||||
|
| Secret token link | URL contains random token. More secure, requires generation/storage. | ✓ |
|
||||||
|
| Two levels only (private/public) | Keep current boolean. Skip link-sharing. | Rejected by user upfront |
|
||||||
|
|
||||||
|
**User's choice:** Secret token link
|
||||||
|
**Notes:** User explicitly stated "ditching the link share ain't it" — three levels are required.
|
||||||
|
|
||||||
|
### Follow-up: Share URL format
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| /setups/42?share=token | Query param on existing route | |
|
||||||
|
| /s/token (short URL) | Dedicated short route, cleaner for sharing | ✓ (both) |
|
||||||
|
|
||||||
|
**User's choice:** Both should work, but `/s/token` is primary for sharing because it's shorter.
|
||||||
|
|
||||||
|
### Follow-up: Token revocation
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Regenerate button (single token) | One token per setup, regenerate invalidates old | |
|
||||||
|
| Full shares list with management | Multiple shares per setup, each with permission/expiration/revocation | ✓ |
|
||||||
|
|
||||||
|
**User's choice:** Full shares management. Multiple coexisting shares with different permissions (read/write), expirations (default 14 days, settable, or infinite), individually revocable. Vision includes person-specific shares with write access.
|
||||||
|
|
||||||
|
### Follow-up: Scope check
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Read shares now, write schema only | Implement read link shares. Schema includes write/person columns unused. | ✓ |
|
||||||
|
| Full system now | Implement everything including write shares and person-specific shares. | |
|
||||||
|
| Minimal + schema | Single share link only. Full schema but minimal UI. | |
|
||||||
|
|
||||||
|
**User's choice:** Read shares now, write permission schema only.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Share UX & Controls
|
||||||
|
|
||||||
|
### Visibility control UI
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Dropdown selector | Replace globe with dropdown for visibility levels | |
|
||||||
|
| Visibility section in panel | Dedicated section below setup content | |
|
||||||
|
| Modal dialog | Share button opens Google Docs-style modal | ✓ |
|
||||||
|
|
||||||
|
**User's choice:** Modal dialog
|
||||||
|
|
||||||
|
### Share button appearance
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Share icon button | Replace globe toggle with share icon showing visibility state | ✓ |
|
||||||
|
| Keep globe + add share | Two buttons, two functions | |
|
||||||
|
| Text button with state | Labeled button showing current state | |
|
||||||
|
|
||||||
|
**User's choice:** Share icon button
|
||||||
|
|
||||||
|
### Default expiration
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| 14 days default | Safe default, options for 7d/30d/infinite | ✓ |
|
||||||
|
| No expiration default | Permanent by default, optional expiration | |
|
||||||
|
| You decide | Claude picks | |
|
||||||
|
|
||||||
|
**User's choice:** 14 days default
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Schema Future-Proofing
|
||||||
|
|
||||||
|
### Shares table design
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Full shares table now | Complete table with permission, userId, expiresAt, revokedAt | ✓ |
|
||||||
|
| Link shares only, extend later | Simpler table, add columns in future migrations | |
|
||||||
|
| You decide | Claude picks based on tradeoffs | |
|
||||||
|
|
||||||
|
**User's choice:** Full shares table now
|
||||||
|
|
||||||
|
### Visibility storage
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Column on setups table | Replace isPublic with visibility text column | ✓ |
|
||||||
|
| Derived from shares | No column, derive from shares table via JOINs | |
|
||||||
|
|
||||||
|
**User's choice:** Column on setups table — best for query speed, but must prevent conflicts with shares.
|
||||||
|
**Notes:** User emphasized "it must be done right to prevent conflicts with the shares"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Public Setup Presentation
|
||||||
|
|
||||||
|
### Link-shared viewer experience
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| Same as public view | Identical to public setup view | |
|
||||||
|
| Shared view with context | Subtle banner showing share status and expiration | |
|
||||||
|
| You decide | Claude picks based on existing patterns | ✓ |
|
||||||
|
|
||||||
|
**User's choice:** Claude's discretion
|
||||||
|
|
||||||
|
### Discovery feed changes
|
||||||
|
|
||||||
|
| Option | Description | Selected |
|
||||||
|
|--------|-------------|----------|
|
||||||
|
| No changes needed | Just update query from isPublic to visibility | ✓ |
|
||||||
|
| Add share count indicator | Show social proof on setup cards | |
|
||||||
|
|
||||||
|
**User's choice:** No changes for Phase 32.
|
||||||
|
**Notes:** Person-specific shares influencing feed algorithm is deferred to future.
|
||||||
|
|
||||||
|
## Claude's Discretion
|
||||||
|
|
||||||
|
- Viewer experience for link-shared setups (shared banner vs. clean view)
|
||||||
|
|
||||||
|
## Deferred Ideas
|
||||||
|
|
||||||
|
- Person-specific shares influencing discovery feed algorithm
|
||||||
|
- Write-access share enforcement (collaborative editing)
|
||||||
|
- Person-specific share UI (invite by username/email)
|
||||||
Reference in New Issue
Block a user