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:
2026-04-05 13:13:12 +02:00
parent eb8f4b7cb2
commit 95143826ed
3 changed files with 156 additions and 20 deletions

View File

@@ -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*