feat(api+client): projects feature (#26) #265
No reviewers
Labels
No labels
area:auth
area:ci
area:db
area:infra
area:native
area:pwa
area:service
epic
feature
foundation
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
james/carol!265
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "26-projects-feature"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Brings the Projects feature live across the full stack — a per-user list of independent / outside-of-work projects with name, optional description, and optional link. Mirrors the Notes / Education CRUD shape end to end:
projectstable (user-scoped, ON DELETE CASCADE).display_orderreserved for a future reordering ticket. Index onuser_id.ProjectsRepositoryships cursor-paginated list, unbounded list, findById, create, update, delete.GET/POST /api/projects+PATCH/DELETE /api/projects/{id}. Cursor pagination via the shared timestamp+id envelope. zod DTOs inlib/dto/project.tsvalidate name (1..200), description (≤2000, nullable), and link (http(s):// only, nullable —javascript:and friends rejected).lib/api/openapi-routes.ts;openapi.jsonregenerated; drift gate green; coverage 69 (path, method) pairs.useProjects,useCreateProject,useUpdateProject,useDeleteProject(mutations patch the list cache in place);keys.projectsadded to the central registry./projectsscreen replaces the placeholder. Inline create + edit-in-place, link tappable viaLinking.openURL, KeyboardAwareScrollView + Enter chains, theme-aware styles pre-flattened to plain objects per #239.projects.*namespace inen.json(sentence case, first person, voice-guide compliant).Routes
Test plan
pnpm install --frozen-lockfilepnpm -F @carol/api typecheckpnpm -F @carol/api lintpnpm -F @carol/api test— 680 passed (53 files; sqlite leg; postgres-leg tests skipped here, will run on CI)pnpm -F @carol/api openapi:check— up to datepnpm -F @carol/api openapi:coverage— 69 (path, method) pairs registeredpnpm -F @carol/api-client check— generated client up to datepnpm -F @carol/api-client typecheckpnpm -F @carol/api-client lintpnpm -F @carol/api-client testpnpm -F @carol/client typecheckpnpm -F @carol/client lintpnpm -F @carol/client testpnpm -F @carol/client export:web— 24 routes including/projectsNotes for the reviewer
projectsinKYSELY_TABLES: added BEFOREusersintests/db/_engines.tsto keep the Postgres drop order FK-safe (the trap from #259).http:///https://schemes (refine on top ofz.url()). The client mirrors that contract viaisValidProjectLinkinprojects.tsx. Tests cover both"not a url"and"javascript:alert(1)".display_order: defaulted to 0 by the repo on insert, untouched by update. Reserved for the eventual reordering feature; no client surface today.Linked: #26. See
idea.md→ Experience for the product context.Closes #26.
📊 Test coverage
Patch coverage: no testable lines changed.
Overall (
app/,lib/,db/, excluding UI per ADR-0019):Soft thresholds per ADR-0019. Coverage is informational and does not block merge.