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