From 373e009ed820d97ec6c93b58396c169676e4fe1d Mon Sep 17 00:00:00 2001 From: curo1305 Date: Fri, 12 Jun 2026 13:35:34 +0200 Subject: [PATCH] =?UTF-8?q?docs(09):=20research=20phase=20=E2=80=94=20admi?= =?UTF-8?q?n=20panel=20rearchitecture?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- .../09-RESEARCH.md | 796 ++++++++++++++++++ 1 file changed, 796 insertions(+) create mode 100644 .planning/phases/09-admin-panel-rearchitecture/09-RESEARCH.md diff --git a/.planning/phases/09-admin-panel-rearchitecture/09-RESEARCH.md b/.planning/phases/09-admin-panel-rearchitecture/09-RESEARCH.md new file mode 100644 index 0000000..9b1d79f --- /dev/null +++ b/.planning/phases/09-admin-panel-rearchitecture/09-RESEARCH.md @@ -0,0 +1,796 @@ +# Phase 9: Admin Panel Rearchitecture - Research + +**Researched:** 2026-06-12 +**Domain:** Vue Router 4 nested routes, layout components, FastAPI sub-module pattern, Tailwind safelist +**Confidence:** HIGH (all findings sourced directly from the live codebase) + +--- + + +## User Constraints (from CONTEXT.md) + +### Locked Decisions + +- **D-01:** Overview layout: 3-4 stat cards top row (total users, total storage, document status: processing/ready/failed), then a table of the last 10 audit entries. +- **D-02:** Backend: new `overview.py` sub-module in `backend/api/admin/`. Single `GET /api/admin/overview` endpoint, one payload with all stats. +- **D-03:** Audit entries inline in the overview response — no separate `/api/audit` call from the overview component. +- **D-04:** SVG icons for each sidebar nav item, consistent with `AppSidebar.vue`. +- **D-05:** "Admin" label/badge below "DocuVault" logo in sidebar header. Same indigo brand color. +- **D-06:** No "Back to app" link. Admin accounts are operators only. Overrides ADMIN-09 requirement text. +- **D-07:** Nav items (in order): Overview, Users, Quotas, AI Config, Audit Log. +- **D-08:** After login, `user.role === 'admin'` → router redirects to `/admin` instead of `/`. +- **D-09:** `beforeEach` guard: admin on non-admin route → redirect to `/admin`. Admin cannot navigate to user routes. +- **D-10:** Two guard branches in `beforeEach`: (a) non-admin → `/admin/*` → redirect `/`; (b) admin → non-admin route → redirect `/admin`. Both use `to.matched.some(r => r.meta.requiresAdmin)`. +- **D-11:** Four existing tab components become standalone view files in `frontend/src/views/admin/`: `AdminUsersView.vue`, `AdminQuotasView.vue`, `AdminAiView.vue`, `AdminAuditView.vue`. Structural rename only — strip top-level padding. +- **D-12:** Original `components/admin/AdminXxxTab.vue` files and `AdminView.vue` deleted after extraction. +- **D-13:** `AuditLogTab.vue` promoted as-is. No new features for the audit view in Phase 9. +- **D-14:** Tailwind safelist pattern: + ```js + safelist: [ + { pattern: /bg-(blue|green|purple|orange|gray|indigo|red)-(50|100|500|600)/ }, + { pattern: /text-(blue|green|purple|orange|gray|indigo|red)-(500|600|700)/ }, + ] + ``` + Researcher verifies which color families `formatters.js` actually uses. +- **D-15:** CODE-09 comment purge covers all Phase 9 files + retroactive purge of Phase 8 backend sub-packages. +- **D-16:** Purge criterion: remove "what" comments (generic docstrings, "this does X"). Keep "why" comments (constraints, pitfall notes, non-obvious invariants). + +### Claude's Discretion + +- Exact SVG icon choices for each admin sidebar nav item (researcher picks from the same icon family used in `AppSidebar.vue`). +- Exact Python queries for the overview aggregate endpoint. +- Naming of the new view files if `views/admin/` directory structure is adopted. + +### Deferred Ideas (OUT OF SCOPE) + +None — discussion stayed within phase scope. + + + + +## Phase Requirements + +| ID | Description | Research Support | +|----|-------------|------------------| +| ADMIN-08 | Admin panel moved to `/admin/*` route subtree with `AdminLayout.vue` as route component. `AdminView.vue` deleted. | Router restructure in §Architecture Patterns; AuthLayout.vue pattern; App.vue analysis | +| ADMIN-09 | Admin sidebar nav links (D-06 overrides "Back to app" item). | AppSidebar.vue deep-read; nav-link CSS classes documented | +| ADMIN-10 | Each admin section is its own deep-linkable URL. Browser back button works. | Vue Router 4 nested routes pattern; child route structure | +| ADMIN-11 | Admin overview page at `/admin` showing platform stats + last 10 audit entries. New backend endpoint. | ORM models for aggregate query; audit.py query pattern reuse; `overview.py` design | +| ADMIN-12 | `requiresAdmin` guard uses `to.matched.some(r => r.meta.requiresAdmin)`. | PITFALLS.md §Pitfall 3 — exact guard fix documented; current guard code shown | +| CODE-06 | Tailwind safelist for dynamic `providerColor`/`providerBg`/`providerLabel` patterns. | formatters.js fully read — exact color families documented | +| CODE-09 | Comment purge over Phase 9 files + retroactive purge of Phase 8 backend sub-packages. | Phase 8 backend sub-packages inspected; purge criterion from D-16 | + + + +--- + +## Summary + +Phase 9 is a structural rearchitecture of the admin interface. The existing `AdminView.vue` (tabs-on-user-layout pattern) is replaced with `AdminLayout.vue` (its own Vue Router parent route whose `` renders child views). Four existing tab components are promoted to standalone views under `frontend/src/views/admin/`. A new admin overview route at `/admin` needs a new backend aggregate endpoint (`GET /api/admin/overview`). The `requiresAdmin` guard must switch from `to.meta.requiresAdmin` to `to.matched.some(r => r.meta.requiresAdmin)` — the current flat check is a security regression waiting to happen once children are added. Strict admin role separation (admins redirected away from user routes) is a new guard enhancement. The Tailwind safelist is a one-file configuration change. The comment purge is the final cleanup pass. + +All changes are structural — no behavior changes to existing admin functionality. The planner should organize work as: (1) backend `overview.py` new endpoint, (2) router restructure + guard updates, (3) AdminLayout + admin views extraction, (4) Tailwind safelist, (5) comment purge. + +**Primary recommendation:** Follow the `AuthLayout.vue` pattern exactly for `AdminLayout.vue` — a minimal wrapper with ``. Use `to.matched.some()` as the single source of truth for admin route detection everywhere in the guard. + +--- + +## Architectural Responsibility Map + +| Capability | Primary Tier | Secondary Tier | Rationale | +|------------|-------------|----------------|-----------| +| Admin layout shell (sidebar + content area) | Frontend (new `AdminLayout.vue`) | — | Route component that owns the admin chrome | +| Admin route protection | Frontend (router `beforeEach`) | — | Guard runs before any component mounts | +| Admin role redirect on login | Frontend (`LoginView.vue` / router guard) | — | Role from `authStore.user.role` after token refresh | +| Admin overview stats | API / Backend (`overview.py`) | — | Aggregate query across users, quotas, documents | +| Admin overview data fetch | Frontend (`AdminOverviewView.vue`) | — | Single-fetch view, no store needed | +| Existing admin CRUD | API / Backend (unchanged) | — | users.py, quotas.py, ai.py, audit.py unchanged | +| Dynamic color class rendering | Frontend (Tailwind safelist in `tailwind.config.js`) | — | Build-time config, no runtime code | + +--- + +## Standard Stack + +No new packages are installed in Phase 9. All work uses the existing stack. + +### Existing Stack Used + +| Component | File | How Used in Phase 9 | +|-----------|------|---------------------| +| Vue Router 4 | Already installed | Nested route with `AdminLayout` as parent component | +| FastAPI / SQLAlchemy 2.0 | Already installed | New `overview.py` endpoint with async aggregate queries | +| Tailwind CSS + Vite | Already configured | Add `safelist` array to `tailwind.config.js` | +| `@tailwindcss/forms` | Already installed (Phase 8) | No change needed | + +**No package installs required for Phase 9.** + +--- + +## Package Legitimacy Audit + +Not applicable — Phase 9 installs no new packages. + +--- + +## Architecture Patterns + +### System Architecture Diagram + +``` +Browser (Vue 3 SPA) +│ +├── /login → AuthLayout → LoginView +│ └── on success: user.role === 'admin' → push('/admin') +│ user.role === 'user' → push(redirect || '/') +│ +├── / (user routes) +│ ├── App.vue renders: flex h-screen + AppSidebar + +│ └── beforeEach guard: admin role on non-admin route → redirect /admin +│ +└── /admin (admin routes — NEW) + ├── App.vue renders: AdminLayout (resolves as /admin route's component) + │ AdminLayout: w-64 AdminSidebar + for child content + │ + ├── /admin → AdminOverviewView (new, single fetch from /api/admin/overview) + ├── /admin/users → AdminUsersView (extracted from AdminUsersTab.vue) + ├── /admin/quotas → AdminQuotasView (extracted from AdminQuotasTab.vue) + ├── /admin/ai → AdminAiView (extracted from AdminAiConfigTab.vue) + └── /admin/audit → AdminAuditView (extracted from AuditLogTab.vue) + +Backend API (unchanged URL surface) +│ +└── GET /api/admin/overview (NEW) + ├── SELECT COUNT(*) FROM users WHERE role = 'user' + ├── SELECT SUM(used_bytes) FROM quotas + ├── SELECT status, COUNT(*) FROM documents GROUP BY status + └── Last 10 audit entries (reuse _build_filtered_query_with_handles, limit=10) +``` + +### Recommended Project Structure + +``` +frontend/src/ +├── layouts/ +│ ├── AuthLayout.vue # existing — reference pattern +│ └── AdminLayout.vue # NEW — mirrors AuthLayout structure +├── views/ +│ ├── AdminView.vue # DELETED after extraction +│ └── admin/ # NEW directory +│ ├── AdminOverviewView.vue # NEW — stats cards + audit table +│ ├── AdminUsersView.vue # extracted from AdminUsersTab.vue +│ ├── AdminQuotasView.vue # extracted from AdminQuotasTab.vue +│ ├── AdminAiView.vue # extracted from AdminAiConfigTab.vue +│ └── AdminAuditView.vue # extracted from AuditLogTab.vue +├── components/admin/ +│ ├── AdminUsersTab.vue # DELETED (dead code after extraction) +│ ├── AdminQuotasTab.vue # DELETED +│ ├── AdminAiConfigTab.vue # DELETED +│ └── AuditLogTab.vue # DELETED + +backend/api/admin/ +├── __init__.py # add overview_router import + include_router call +├── shared.py # unchanged +├── users.py # unchanged +├── quotas.py # unchanged +├── ai.py # unchanged +└── overview.py # NEW — GET /api/admin/overview +``` + +### Pattern 1: AdminLayout follows AuthLayout pattern exactly + +`AuthLayout.vue` is 12 lines. It is a plain `