From 3c39690f4ad2ea8b2c4c27957e9b4096106f3c89 Mon Sep 17 00:00:00 2001 From: Marko Djordjevic Date: Fri, 20 Feb 2026 08:59:17 +0100 Subject: [PATCH] Assign per-task model tags in user-accounts tasks.md Replace section-level model tags with individual task-level tags. Haiku for mechanical/config/boilerplate, sonnet for standard feature work, opus for 2.5 (data migration backfill) and 7.2 (user_id query permeation across all routes). Co-Authored-By: Claude Sonnet 4.6 --- openspec/changes/user-accounts/tasks.md | 93 +++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 openspec/changes/user-accounts/tasks.md diff --git a/openspec/changes/user-accounts/tasks.md b/openspec/changes/user-accounts/tasks.md new file mode 100644 index 0000000..407c05b --- /dev/null +++ b/openspec/changes/user-accounts/tasks.md @@ -0,0 +1,93 @@ +## 1. Dependencies & Configuration + +- [ ] 1.1 `[haiku]` Install npm dependencies: `next-auth@5`, `bcryptjs`, `@types/bcryptjs` +- [ ] 1.2 `[haiku]` Add environment variables to `.env.example`: `AUTH_SECRET`, `AUTH_GOOGLE_ID`, `AUTH_GOOGLE_SECRET`, `AUTH_TRUST_HOST`, `DEFAULT_ADMIN_EMAIL`, `DEFAULT_ADMIN_PASSWORD` +- [ ] 1.3 `[haiku]` Update `docker-compose.yml` to pass new auth env vars to the candle-annotator service + +## 2. Database Schema & Migration + +- [ ] 2.1 `[sonnet]` Add `users` table to Drizzle schema (`src/lib/db/schema.ts`) with UUID PK, email, password_hash, name, image, provider, provider_account_id, email_verified, created_at, updated_at +- [ ] 2.2 `[sonnet]` Add `user_id` (uuid, FK to users.id) column to `charts`, `annotations`, `annotation_types`, `span_annotations`, `span_label_types` in schema +- [ ] 2.3 `[sonnet]` Replace unique constraints: `charts.name` → `(user_id, name)`, `annotation_types.name` → `(user_id, name)`, `span_label_types.name` → `(user_id, name)` +- [ ] 2.4 `[haiku]` Generate Drizzle migration with `drizzle-kit generate` +- [ ] 2.5 `[opus]` Create data migration script (`scripts/migrate-users.ts`): create default admin user, backfill `user_id` on all existing rows, alter columns to NOT NULL + +## 3. Auth.js Configuration + +- [ ] 3.1 `[sonnet]` Create `src/auth.ts` with Auth.js v5 config: JWT strategy, Credentials provider (email/password with bcryptjs verify), Google OAuth provider +- [ ] 3.2 `[sonnet]` Add JWT callback to embed `user.id` in token and session callback to expose `session.user.id` +- [ ] 3.3 `[sonnet]` Handle Google OAuth sign-in callback: create user on first sign-in, find existing user on returning sign-in +- [ ] 3.4 `[haiku]` Create `src/app/api/auth/[...nextauth]/route.ts` exporting GET/POST handlers + +## 4. Registration API + +- [ ] 4.1 `[sonnet]` Create `POST /api/auth/register` endpoint: validate input (email required, password 8+ chars), check email uniqueness, hash password with bcryptjs, insert user, return 201 +- [ ] 4.2 `[sonnet]` Add default data seeding function: on new user creation, insert default annotation_types (break_up, break_down, line) and default span_label_types for the new user + +## 5. Auth Middleware & Helpers + +- [ ] 5.1 `[sonnet]` Create `proxy.ts` at project root: protect `/app/*` routes (redirect to `/login`), protect `/api/*` except `/api/auth/*` and `/api/health` (return 401), redirect authenticated users from `/login` and `/register` to `/app` +- [ ] 5.2 `[haiku]` Create `src/lib/auth.ts` with `getAuthUser()` helper that extracts user from Auth.js session + +## 6. User Settings API + +- [ ] 6.1 `[haiku]` Create `PUT /api/auth/profile` endpoint: update user display name +- [ ] 6.2 `[sonnet]` Create `PUT /api/auth/password` endpoint: verify current password, hash new password, update; reject for OAuth users +- [ ] 6.3 `[sonnet]` Create `DELETE /api/auth/account` endpoint: delete all user data (cascade) and user record + +## 7. Update Existing API Routes + +- [ ] 7.1 `[sonnet]` Add `getAuthUser()` check to all data API routes: `/api/upload`, `/api/candles`, `/api/charts`, `/api/annotations`, `/api/annotation-types`, `/api/span-annotations`, `/api/span-label-types`, `/api/export` +- [ ] 7.2 `[opus]` Update all Drizzle queries to filter by `user_id` from authenticated session (SELECT, INSERT, DELETE) +- [ ] 7.3 `[sonnet]` Add `getAuthUser()` check to all proxy API routes: `/api/predict`, `/api/predict/batch`, `/api/model/info`, `/api/model/load`, `/api/patterns/detect`, `/api/patterns/available`, `/api/training/start`, `/api/training/runs` +- [ ] 7.4 `[haiku]` Add `X-User-ID` header to all fetch calls from proxy routes to the FastAPI ML service + +## 8. Frontend Routing Restructure + +- [ ] 8.1 `[haiku]` Create `src/app/(public)/layout.tsx` — minimal layout for public pages (shared fonts/theme, no sidebar) +- [ ] 8.2 `[haiku]` Move current `src/app/page.tsx` to `src/app/app/page.tsx` (workspace at `/app`) +- [ ] 8.3 `[sonnet]` Create `src/app/app/layout.tsx` — protected layout with `SessionProvider`, user menu nav bar, sidebar with settings link +- [ ] 8.4 `[haiku]` Update any hardcoded `/` links in existing components to `/app` + +## 9. Landing Page + +- [ ] 9.1 `[sonnet]` Create `src/app/(public)/page.tsx` — landing page matching Lovable design: navbar with login/register links, hero section, features grid (6 cards), stats bar, footer CTA +- [ ] 9.2 `[haiku]` Add auth-aware navbar: show "Log in"/"Get Started" when unauthenticated, "Go to App" when authenticated + +## 10. Login Page + +- [ ] 10.1 `[sonnet]` Create `src/app/(public)/login/page.tsx` — login form matching Lovable design: email/password inputs, "Sign In" button calling `signIn("credentials")`, "Continue with Google" button calling `signIn("google")` +- [ ] 10.2 `[haiku]` Add error state display for invalid credentials +- [ ] 10.3 `[haiku]` Add "Forgot password?" link (shows toast: "Not yet available"), "Sign up" link to `/register` + +## 11. Register Page + +- [ ] 11.1 `[sonnet]` Create `src/app/(public)/register/page.tsx` — register form matching Lovable design: name/email/password inputs, "Create Account" button posting to `/api/auth/register` then auto-signing in +- [ ] 11.2 `[haiku]` Add error state display for duplicate email, short password +- [ ] 11.3 `[haiku]` Add "Continue with Google" button, "Sign in" link to `/login` + +## 12. Settings Page + +- [ ] 12.1 `[sonnet]` Create `src/app/app/settings/page.tsx` — Profile section: display name input with save, read-only email +- [ ] 12.2 `[sonnet]` Add Security section: change password form (current/new/confirm) for credentials users, "Signed in via Google" for OAuth users +- [ ] 12.3 `[sonnet]` Add Danger Zone section: delete account button with confirmation dialog (type "DELETE" to confirm) +- [ ] 12.4 `[haiku]` Add back navigation link to `/app` + +## 13. App Layout & User Menu + +- [ ] 13.1 `[sonnet]` Create user menu component: avatar/initial, dropdown with "Settings" and "Sign Out" links +- [ ] 13.2 `[haiku]` Add settings gear icon to sidebar (near theme toggle) +- [ ] 13.3 `[haiku]` Wire `signOut()` in user menu to destroy session and redirect to `/login` + +## 14. ML Service User Scoping + +- [ ] 14.1 `[haiku]` Update FastAPI service to read `X-User-ID` header from incoming requests +- [ ] 14.2 `[haiku]` Scope MLflow experiment names to include user ID (e.g., `user_{uuid}_training`) +- [ ] 14.3 `[sonnet]` Scope training run queries in FastAPI to filter by user ID + +## 15. Documentation & Deployment + +- [ ] 15.1 `[haiku]` Update `DEPLOYMENT.md` with new env vars, migration steps, Google OAuth setup instructions +- [ ] 15.2 `[haiku]` Update `README.md` with user accounts feature description +- [ ] 15.3 `[haiku]` Update `CLAUDE_DESCRIPTION.md` with new routing, auth system, and schema changes +- [ ] 15.4 `[haiku]` Update `.env.example` with all new environment variables and comments