105 lines
4.8 KiB
Markdown
105 lines
4.8 KiB
Markdown
# Phase 36: Admin Role & Panel Foundation - Context
|
|
|
|
**Gathered:** 2026-04-19
|
|
**Status:** Ready for planning
|
|
|
|
<domain>
|
|
## Phase Boundary
|
|
|
|
Add an `isAdmin` boolean to the users table, protect the `/admin` route (server middleware + client guard), build a structured admin shell with sidebar navigation, and surface `isAdmin` to the client via `/api/auth/me`. Admin status is granted directly via SQL/Drizzle Studio — no CLI script needed.
|
|
|
|
</domain>
|
|
|
|
<decisions>
|
|
## Implementation Decisions
|
|
|
|
### Schema
|
|
- **D-01:** Add `isAdmin boolean NOT NULL DEFAULT false` to the `users` table via Drizzle migration.
|
|
- **D-02:** No Logto role claims — isAdmin lives entirely in the GearBox database.
|
|
|
|
### Admin Grant Mechanism
|
|
- **D-03:** No CLI script. Developers grant/revoke admin status via direct SQL (`UPDATE users SET is_admin = true WHERE ...`) or Drizzle Studio. This is acceptable for a single-admin app.
|
|
|
|
### Route Protection
|
|
- **D-04:** New `requireAdmin` middleware (extends `requireAuth`) — returns 403 JSON for any non-admin hitting `/api/admin/*` endpoints.
|
|
- **D-05:** TanStack Router `beforeLoad` guard on the `/admin` client route — redirects non-admin users to home (`/`). Belt-and-suspenders: server 403 + client redirect.
|
|
|
|
### Admin Nav Link
|
|
- **D-06:** Show a conditional "Admin" link for admin users in the **user avatar/menu area** of the top nav (not a top-level nav item). Keeps it scoped to account-level actions.
|
|
- **D-07:** `isAdmin` is surfaced to the client by adding it to the `/api/auth/me` response. No separate query needed.
|
|
|
|
### Admin Panel Layout
|
|
- **D-08:** `/admin` renders a structured shell with a sidebar nav — not an empty placeholder. The shell has two nav items: **Items** and **Tags** (matching phases 37 and 38 respectively). Both are disabled/coming-soon in this phase.
|
|
- **D-09:** This layout is the reusable admin frame — phases 37 and 38 replace the placeholder content areas without reworking the shell.
|
|
|
|
### Claude's Discretion
|
|
- Exact visual styling of the admin shell (consistent with app's light/minimal aesthetic)
|
|
- Whether to add a dedicated `/admin` server-side route handler or reuse the SPA catch-all
|
|
- How to structure the `requireAdmin` middleware relative to `requireAuth` (wrapping vs. separate)
|
|
|
|
</decisions>
|
|
|
|
<canonical_refs>
|
|
## Canonical References
|
|
|
|
**Downstream agents MUST read these before planning or implementing.**
|
|
|
|
### Auth & Middleware
|
|
- `src/server/middleware/auth.ts` — existing `requireAuth` middleware; `requireAdmin` should follow the same pattern
|
|
- `src/server/services/auth.service.ts` — `getOrCreateUser` and user DB patterns
|
|
|
|
### Database Schema
|
|
- `src/db/schema.ts` — `users` table definition; add `isAdmin` here
|
|
- `src/server/routes/auth.ts` — `/api/auth/me` endpoint; add `isAdmin` to response
|
|
|
|
### Client Routing & Nav
|
|
- `src/client/routes/__root.tsx` — root layout with top nav + user menu; add conditional Admin link
|
|
- `src/client/routes/` — TanStack Router file-based routes; create `admin.tsx` and `admin/` directory
|
|
|
|
### Requirements
|
|
- `.planning/REQUIREMENTS.md` — ROLE-01, ROLE-02, ADMN-01
|
|
|
|
</canonical_refs>
|
|
|
|
<code_context>
|
|
## Existing Code Insights
|
|
|
|
### Reusable Assets
|
|
- `requireAuth` middleware (`src/server/middleware/auth.ts`): `requireAdmin` follows the same Context/Next signature — call `requireAuth` first, then check `isAdmin` from the resolved user record
|
|
- Existing Hono route patterns in `src/server/routes/` — admin routes follow the same structure
|
|
- TanStack Router file-based routing — `/admin` becomes `src/client/routes/admin.tsx` (or `admin/index.tsx`)
|
|
|
|
### Established Patterns
|
|
- Auth middleware sets `userId` on Hono context; `requireAdmin` reads the `users` record to check `isAdmin`
|
|
- `/api/auth/me` already returns `{ user, authenticated }` — add `isAdmin` to the `user` object
|
|
- Light/airy design aesthetic — admin shell should match app visual style (white, minimal, no visual clutter)
|
|
|
|
### Integration Points
|
|
- `src/server/index.ts`: Register new `/api/admin/*` routes behind `requireAdmin`
|
|
- `src/client/routes/__root.tsx`: Conditional Admin link in user menu (reads `isAdmin` from auth query)
|
|
- `src/db/schema.ts` + migration: `isAdmin` column on `users` table
|
|
|
|
</code_context>
|
|
|
|
<specifics>
|
|
## Specific Ideas
|
|
|
|
- Admin sidebar: two sections "Items" (phase 37) and "Tags" (phase 38) — both greyed out / "Coming soon" in this phase
|
|
- The admin shell is the persistent frame; phases 37/38 inject content into a `<Outlet>` or equivalent
|
|
|
|
</specifics>
|
|
|
|
<deferred>
|
|
## Deferred Ideas
|
|
|
|
- Logto UI-based admin management — not possible without switching to Logto role claims (explicitly ruled out)
|
|
- Users section in admin sidebar — not in current roadmap, deferred to a future milestone if needed
|
|
- Formal CLI tool for admin grant — deemed unnecessary given direct SQL access
|
|
|
|
</deferred>
|
|
|
|
---
|
|
|
|
*Phase: 36-admin-role-panel-foundation*
|
|
*Context gathered: 2026-04-19*
|