docs(18-03): complete user profiles and public sharing plan
- SUMMARY.md with 2 tasks, 25 tests passing, 9 files modified - STATE.md updated with progress and decisions - REQUIREMENTS.md: PROF-01 through PROF-05 marked complete
This commit is contained in:
@@ -49,11 +49,11 @@ Requirements for this milestone. Each maps to roadmap phases.
|
|||||||
|
|
||||||
### User Profiles & Sharing
|
### User Profiles & Sharing
|
||||||
|
|
||||||
- [ ] **PROF-01**: User has a profile with display name, avatar, and bio
|
- [x] **PROF-01**: User has a profile with display name, avatar, and bio
|
||||||
- [ ] **PROF-02**: User can view their own public profile page
|
- [x] **PROF-02**: User can view their own public profile page
|
||||||
- [ ] **PROF-03**: User can set a setup as public or private
|
- [x] **PROF-03**: User can set a setup as public or private
|
||||||
- [ ] **PROF-04**: Public setups are viewable by anyone without authentication
|
- [x] **PROF-04**: Public setups are viewable by anyone without authentication
|
||||||
- [ ] **PROF-05**: Public profile page lists the user's public setups
|
- [x] **PROF-05**: Public profile page lists the user's public setups
|
||||||
|
|
||||||
## Future Requirements
|
## Future Requirements
|
||||||
|
|
||||||
@@ -141,11 +141,11 @@ Which phases cover which requirements. Updated during roadmap creation.
|
|||||||
| GLOB-03 | Phase 18 | Pending |
|
| GLOB-03 | Phase 18 | Pending |
|
||||||
| GLOB-04 | Phase 18 | Pending |
|
| GLOB-04 | Phase 18 | Pending |
|
||||||
| GLOB-05 | Phase 18 | Pending |
|
| GLOB-05 | Phase 18 | Pending |
|
||||||
| PROF-01 | Phase 18 | Pending |
|
| PROF-01 | Phase 18 | Complete |
|
||||||
| PROF-02 | Phase 18 | Pending |
|
| PROF-02 | Phase 18 | Complete |
|
||||||
| PROF-03 | Phase 18 | Pending |
|
| PROF-03 | Phase 18 | Complete |
|
||||||
| PROF-04 | Phase 18 | Pending |
|
| PROF-04 | Phase 18 | Complete |
|
||||||
| PROF-05 | Phase 18 | Pending |
|
| PROF-05 | Phase 18 | Complete |
|
||||||
|
|
||||||
**Coverage:**
|
**Coverage:**
|
||||||
- v2.0 requirements: 30 total
|
- v2.0 requirements: 30 total
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
---
|
---
|
||||||
gsd_state_version: 1.0
|
gsd_state_version: 1.0
|
||||||
milestone: v2.0
|
milestone: v1.3
|
||||||
milestone_name: Platform Foundation
|
milestone_name: Research & Decision Tools
|
||||||
status: planning
|
status: planning
|
||||||
stopped_at: null
|
stopped_at: Completed 18-03-PLAN.md
|
||||||
last_updated: "2026-04-03"
|
last_updated: "2026-04-05T11:12:57.693Z"
|
||||||
last_activity: 2026-04-03 — v2.0 roadmap created (Phases 14-18)
|
last_activity: 2026-04-03 — v2.0 roadmap created (Phases 14-18)
|
||||||
progress:
|
progress:
|
||||||
total_phases: 5
|
total_phases: 8
|
||||||
completed_phases: 0
|
completed_phases: 6
|
||||||
total_plans: 0
|
total_plans: 12
|
||||||
completed_plans: 0
|
completed_plans: 11
|
||||||
percent: 0
|
percent: 0
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -35,6 +35,7 @@ Progress: [----------] 0% (v2.0 milestone)
|
|||||||
## Performance Metrics
|
## Performance Metrics
|
||||||
|
|
||||||
**Velocity:**
|
**Velocity:**
|
||||||
|
|
||||||
- Total plans completed: 0 (v2.0 milestone)
|
- Total plans completed: 0 (v2.0 milestone)
|
||||||
- Average duration: --
|
- Average duration: --
|
||||||
- Total execution time: --
|
- Total execution time: --
|
||||||
@@ -46,12 +47,14 @@ Progress: [----------] 0% (v2.0 milestone)
|
|||||||
### Decisions
|
### Decisions
|
||||||
|
|
||||||
Key decisions made during v2.0 planning:
|
Key decisions made during v2.0 planning:
|
||||||
|
|
||||||
- Platform pivot: single-user to multi-user with discovery-first approach
|
- Platform pivot: single-user to multi-user with discovery-first approach
|
||||||
- External auth provider (self-hosted, open-source) — Logto vs Authentik OPEN decision
|
- External auth provider (self-hosted, open-source) — Logto vs Authentik OPEN decision
|
||||||
- SQLite to Postgres migration — required by auth provider and multi-user concurrency
|
- SQLite to Postgres migration — required by auth provider and multi-user concurrency
|
||||||
- Structured UGC only — ratings and predefined fields, no freeform text until moderation
|
- Structured UGC only — ratings and predefined fields, no freeform text until moderation
|
||||||
- Separate globalItems table — not a flag on user items table
|
- Separate globalItems table — not a flag on user items table
|
||||||
- Single-user SQLite mode diverges at v2.0 boundary
|
- Single-user SQLite mode diverges at v2.0 boundary
|
||||||
|
- [Phase 18]: Public endpoints bypass auth via regex path matching in index.ts middleware
|
||||||
|
|
||||||
### Pending Todos
|
### Pending Todos
|
||||||
|
|
||||||
@@ -64,6 +67,6 @@ None active.
|
|||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-04-03
|
Last session: 2026-04-05T11:12:57.691Z
|
||||||
Stopped at: v2.0 roadmap created with 5 phases (14-18) covering 30 requirements
|
Stopped at: Completed 18-03-PLAN.md
|
||||||
Resume file: None
|
Resume file: None
|
||||||
|
|||||||
@@ -0,0 +1,133 @@
|
|||||||
|
---
|
||||||
|
phase: 18-global-items-public-profiles
|
||||||
|
plan: 03
|
||||||
|
subsystem: server
|
||||||
|
tags: [profiles, public-setups, hono, drizzle, services, routes]
|
||||||
|
|
||||||
|
requires:
|
||||||
|
- phase: 18-global-items-public-profiles
|
||||||
|
plan: 01
|
||||||
|
provides: "User profile columns, setup isPublic column, Zod schemas"
|
||||||
|
provides:
|
||||||
|
- "Profile service (updateProfile, getPublicProfile, getPublicSetupWithItems)"
|
||||||
|
- "Public profile endpoint GET /api/users/:id/profile"
|
||||||
|
- "Profile update endpoint PUT /api/auth/profile"
|
||||||
|
- "Public setup endpoint GET /api/setups/:id/public"
|
||||||
|
- "Setup service isPublic support in create/update/list/detail"
|
||||||
|
affects: [18-04, 18-05]
|
||||||
|
|
||||||
|
tech-stack:
|
||||||
|
added: []
|
||||||
|
patterns: ["Public endpoints bypass auth middleware via regex in index.ts"]
|
||||||
|
|
||||||
|
key-files:
|
||||||
|
created:
|
||||||
|
- "src/server/services/profile.service.ts"
|
||||||
|
- "src/server/routes/profiles.ts"
|
||||||
|
- "tests/services/profile.service.test.ts"
|
||||||
|
- "tests/routes/profiles.test.ts"
|
||||||
|
modified:
|
||||||
|
- "src/server/services/setup.service.ts"
|
||||||
|
- "src/server/services/category.service.ts"
|
||||||
|
- "src/server/routes/auth.ts"
|
||||||
|
- "src/server/routes/setups.ts"
|
||||||
|
- "src/server/index.ts"
|
||||||
|
|
||||||
|
key-decisions:
|
||||||
|
- "Public endpoints skip auth via regex path matching in index.ts middleware"
|
||||||
|
- "Profile update placed on auth routes (PUT /api/auth/profile) since it requires auth"
|
||||||
|
- "Public setup route placed in setups.ts as GET /:id/public before GET /:id"
|
||||||
|
|
||||||
|
patterns-established:
|
||||||
|
- "Public endpoint pattern: regex skip in auth middleware + no userId dependency in handler"
|
||||||
|
|
||||||
|
requirements-completed: [PROF-01, PROF-02, PROF-03, PROF-04, PROF-05]
|
||||||
|
|
||||||
|
duration: 7min
|
||||||
|
completed: 2026-04-05
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 18 Plan 03: User Profiles & Public Sharing Backend Summary
|
||||||
|
|
||||||
|
**Profile service with CRUD and public profile data, public setup viewing, setup visibility toggle, and auth middleware bypass for public endpoints**
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
- **Duration:** 7 min
|
||||||
|
- **Started:** 2026-04-05T11:03:46Z
|
||||||
|
- **Completed:** 2026-04-05T11:11:44Z
|
||||||
|
- **Tasks:** 2
|
||||||
|
- **Files modified:** 9
|
||||||
|
|
||||||
|
## Accomplishments
|
||||||
|
|
||||||
|
- Created profile service with updateProfile, getPublicProfile, and getPublicSetupWithItems
|
||||||
|
- Added public profile endpoint returning user info and only public setups
|
||||||
|
- Added profile update endpoint behind auth on PUT /api/auth/profile
|
||||||
|
- Added public setup view endpoint at GET /api/setups/:id/public (returns 404 for private)
|
||||||
|
- Updated setup service to handle isPublic in create, update, list, and detail
|
||||||
|
- Updated auth middleware to skip auth for public profile and setup GET requests
|
||||||
|
- 25 tests passing (15 service + 10 route tests)
|
||||||
|
|
||||||
|
## Task Commits
|
||||||
|
|
||||||
|
Each task was committed atomically:
|
||||||
|
|
||||||
|
1. **Task 1: Profile service + setup isPublic + tests (TDD)** - `2d5d4f9` (test RED), `854811d` (feat GREEN)
|
||||||
|
2. **Task 2: Routes + auth middleware + route tests** - `eb8f4b7` (feat)
|
||||||
|
|
||||||
|
## Files Created/Modified
|
||||||
|
|
||||||
|
- `src/server/services/profile.service.ts` - updateProfile, getPublicProfile, getPublicSetupWithItems
|
||||||
|
- `src/server/routes/profiles.ts` - GET /:id/profile public endpoint
|
||||||
|
- `src/server/routes/auth.ts` - Added PUT /profile with requireAuth and updateProfileSchema validation
|
||||||
|
- `src/server/routes/setups.ts` - Added GET /:id/public endpoint using getPublicSetupWithItems
|
||||||
|
- `src/server/index.ts` - Registered profileRoutes at /api/users, added regex auth skips
|
||||||
|
- `src/server/services/setup.service.ts` - isPublic in createSetup, updateSetup, getAllSetups
|
||||||
|
- `src/server/services/category.service.ts` - Added getOrCreateUncategorized (Rule 3 fix)
|
||||||
|
- `tests/services/profile.service.test.ts` - 15 tests for profile and setup isPublic
|
||||||
|
- `tests/routes/profiles.test.ts` - 10 tests for public profile, auth profile update, public setup
|
||||||
|
|
||||||
|
## Decisions Made
|
||||||
|
|
||||||
|
- Public endpoints bypass auth via regex path matching in the centralized auth middleware, not per-route
|
||||||
|
- Profile update lives under /api/auth/profile since it requires authentication context
|
||||||
|
- Public setup route registered before /:id in setups.ts to prevent route conflict
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
### Auto-fixed Issues
|
||||||
|
|
||||||
|
**1. [Rule 3 - Blocking] Added getOrCreateUncategorized to category service**
|
||||||
|
- **Found during:** Task 2
|
||||||
|
- **Issue:** Auth middleware imports getOrCreateUncategorized from category.service.ts but the function didn't exist (was expected from Phase 16 multi-user conversion)
|
||||||
|
- **Fix:** Added async getOrCreateUncategorized function that finds or creates the "Uncategorized" category for a user
|
||||||
|
- **Files modified:** src/server/services/category.service.ts
|
||||||
|
- **Commit:** eb8f4b7
|
||||||
|
|
||||||
|
**2. [Rule 1 - Bug] Handle empty update in updateProfile**
|
||||||
|
- **Found during:** Task 1 GREEN phase
|
||||||
|
- **Issue:** Drizzle throws "No values to set" when .set() receives an empty object
|
||||||
|
- **Fix:** Added check for empty updates, returning existing user without running update query
|
||||||
|
- **Files modified:** src/server/services/profile.service.ts
|
||||||
|
- **Commit:** 854811d
|
||||||
|
|
||||||
|
## Issues Encountered
|
||||||
|
|
||||||
|
None beyond the auto-fixed deviations above.
|
||||||
|
|
||||||
|
## Known Stubs
|
||||||
|
|
||||||
|
None - all endpoints are fully wired to service functions with real database operations.
|
||||||
|
|
||||||
|
## Next Phase Readiness
|
||||||
|
|
||||||
|
- Profile backend complete for Plan 18-04 (client-side profile pages)
|
||||||
|
- Public setup view ready for Plan 18-05 (discovery feed)
|
||||||
|
- All service functions exported and tested for downstream consumption
|
||||||
|
|
||||||
|
## Self-Check: PASSED
|
||||||
|
|
||||||
|
---
|
||||||
|
*Phase: 18-global-items-public-profiles*
|
||||||
|
*Completed: 2026-04-05*
|
||||||
Reference in New Issue
Block a user