# Next.js Full-Stack CRUD, RBAC, and Audit Logs ## Goal Turn the current static/local-storage Next.js app into a minimal real full-stack application for the first operational slice: account setup/login, built-in RBAC, elder profile CRUD, and auditable administrative actions. The first release should remove mock/local-only behavior from the core flow and persist data through server-side APIs so the app can be exercised end-to-end without browser localStorage state. ## Confirmed Facts - The repository is already a Next.js 15 App Router project with routes under `app/`. - Protected app screens are currently guarded by `modules/auth/components/AuthGate.tsx`, which reads localStorage through `modules/auth/lib/local-auth.ts`. - Login/register/setup UI exists in `modules/auth/components/AuthPanel.tsx`, but password input is not validated server-side and accounts are browser-local. - The "老人档案" route at `app/(app)/app/elders/page.tsx` is currently a static `ModulePage`. - The "权限设置" route at `app/(app)/app/settings/page.tsx` is currently a static `ModulePage`. - The project has no installed database/auth dependencies such as Drizzle, PostgreSQL client, oRPC, Zod, or better-auth. - Current `package.json` already supports `pnpm lint`, `pnpm type-check`, and `pnpm build`. ## MVP Scope - Implement a real server-side persistence layer using JSON files under a server-owned data directory for this milestone. This is not mock data: API mutations must write durable data on disk during local/runtime execution. - Use Next.js Route Handlers for the first API surface instead of adding oRPC/Drizzle/better-auth in this milestone. - Replace localStorage authentication with server-side account/session APIs and HTTP-only cookie sessions. - Provide built-in roles and permission groups without user-defined custom role creation in this milestone. - Implement full CRUD for elder profiles as the first business entity. - Implement a permissions/settings page that shows accounts, roles, permission coverage, and audit logs from server data. - Record audit log entries for login, logout, account creation, elder create/update/delete, and permission-sensitive denied actions. ## Requirements ### Authentication - Setup must create the first administrator account on the server. - Login must validate account credentials on the server and set an HTTP-only session cookie. - Logout must clear the session cookie and record an audit event when possible. - App routes must no longer depend on localStorage for authentication. ### Roles and Permissions - The system must include built-in roles: - `admin`: full access to accounts, permissions, audit logs, and elder CRUD. - `manager`: elder CRUD and audit log viewing, but no account/role administration. - `caregiver`: elder read/update access for care-facing fields, no delete or account administration. - `viewer`: read-only elder access. - Permission checks must run on the server for all protected APIs. - UI navigation or controls may hide unavailable actions, but hidden UI must not be the only enforcement. ### Elder CRUD - Users with permission can list, create, update, and delete elder profiles. - Elder records must include at minimum: name, gender, birth date or age, care level, room/bed, status, primary contact, phone, medical notes, created/updated timestamps. - The elder page must show real server data and support create/edit/delete interactions. - Invalid input must return structured API errors and show usable feedback in the UI. ### Audit Logs - Audit logs must be persisted server-side and visible in the settings page. - Each audit record must include timestamp, actor account ID/email when available, action, target type, target ID when available, result, and human-readable reason. - Failed permission checks must be logged without exposing sensitive internals to the client. ### Data and API - API responses must use a consistent `{ success, reason, ... }` shape. - Server-side data helpers must avoid browser APIs. - All file persistence operations must be centralized so future Drizzle/Postgres migration has a single boundary to replace. - Do not use hard-coded UI counters for the implemented CRUD/settings/audit areas once server data exists. ### Quality - Keep TypeScript strict without `any`, non-null assertions, or `@ts-ignore`/`@ts-expect-error`. - Prefer Server Components for initial data loading and small Client Components only for forms/mutations. - `pnpm lint`, `pnpm type-check`, and `pnpm build` should pass before marking implementation complete. ## Acceptance Criteria - [ ] First-run setup creates a server-persisted admin account and redirects into the app. - [ ] Login/logout uses server APIs and an HTTP-only cookie session, not localStorage. - [ ] Visiting `/app/elders` while authenticated loads elder records from the server persistence layer. - [ ] An authorized user can create, edit, and delete elder records from the UI, and changes survive page reloads. - [ ] Unauthorized role attempts against protected elder/account/audit APIs return a forbidden response and create audit log entries. - [ ] `/app/settings` displays built-in roles, account list, and recent audit log entries from server data. - [ ] Audit logs are written for account creation, login, logout, elder create/update/delete, and denied permission checks. - [ ] Existing static module pages outside the MVP continue to render. - [ ] `pnpm lint` passes. - [ ] `pnpm type-check` passes. - [ ] `pnpm build` passes. ## Out of Scope - PostgreSQL/Drizzle migration. - oRPC adoption. - better-auth adoption. - Password reset, email verification, OAuth, multi-factor authentication, or account invitations. - Custom role builder UI. - CRUD implementation for every module in the sidebar. - Production-grade password hashing beyond Node built-in cryptographic hashing suitable for this local MVP. ## Open Questions - None blocking. The MVP assumes "basic CRUD" means the first core business entity, elder profiles, plus real account/session/audit support. ## Notes - Next.js documentation confirms App Router Route Handlers support `GET`, `POST`, `PATCH`, and `DELETE`, `Response.json`, `request.json()`, and async `cookies()` from `next/headers` for cookie reads/writes in current versions.