Moves phases 08–11 execution artifacts from .planning/phases/ to .planning/milestones/v0.2-phases/ to keep .planning/phases/ clean for the next milestone. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
175 lines
13 KiB
Markdown
175 lines
13 KiB
Markdown
---
|
|
phase: 09-admin-panel-rearchitecture
|
|
plan: 03
|
|
type: execute
|
|
wave: 2
|
|
depends_on:
|
|
- 09-02
|
|
files_modified:
|
|
- frontend/src/views/admin/AdminUsersView.vue
|
|
- frontend/src/views/admin/AdminQuotasView.vue
|
|
- frontend/src/views/admin/AdminAiView.vue
|
|
- frontend/src/views/admin/AdminAuditView.vue
|
|
autonomous: true
|
|
requirements:
|
|
- ADMIN-08
|
|
- ADMIN-10
|
|
user_setup: []
|
|
|
|
must_haves:
|
|
truths:
|
|
- "Each of the four extracted views (Users, Quotas, AI, Audit) is a self-contained .vue file under frontend/src/views/admin/"
|
|
- "Each extracted view behaves identically to its Phase 8 tab component — same data fetches, same actions, same template DOM"
|
|
- "Top-level template element of each view is a plain <div> with NO p-8, p-6, or max-w- class (AdminLayout owns the content padding)"
|
|
artifacts:
|
|
- path: "frontend/src/views/admin/AdminUsersView.vue"
|
|
provides: "Standalone /admin/users view extracted from AdminUsersTab.vue"
|
|
- path: "frontend/src/views/admin/AdminQuotasView.vue"
|
|
provides: "Standalone /admin/quotas view extracted from AdminQuotasTab.vue"
|
|
- path: "frontend/src/views/admin/AdminAiView.vue"
|
|
provides: "Standalone /admin/ai view extracted from AdminAiConfigTab.vue"
|
|
- path: "frontend/src/views/admin/AdminAuditView.vue"
|
|
provides: "Standalone /admin/audit view extracted from AuditLogTab.vue"
|
|
key_links:
|
|
- from: "frontend/src/views/admin/*View.vue"
|
|
to: "frontend/src/api/admin.js"
|
|
via: "named imports preserved from source tab components"
|
|
pattern: "from '../../api/"
|
|
---
|
|
|
|
<objective>
|
|
Promote the four existing admin tab components (`AdminUsersTab.vue`, `AdminQuotasTab.vue`, `AdminAiConfigTab.vue`, `AuditLogTab.vue`) into standalone view files in `frontend/src/views/admin/` (D-11). Extraction is **structural and behavior-preserving** — same template, same script, same data fetches, same emitted actions, with import paths rewritten for the new location and the component renamed in the script setup.
|
|
|
|
Purpose: D-11 mandates the tab components become views. D-13 mandates AuditLog is promoted as-is (no new features). The Phase 9 architecture (D-09/D-10/D-11) requires each admin section be a standalone deep-linkable view component — `AdminLayout`'s `<router-view />` must render them.
|
|
|
|
Output: 4 new view files. Original tab components and `AdminView.vue` are deleted in 09-04 (after router rewiring). This plan does NOT delete anything and does NOT touch the router — those land in 09-04 to keep the codebase in a buildable state between waves.
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
|
|
@$HOME/.claude/get-shit-done/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@.planning/phases/09-admin-panel-rearchitecture/09-CONTEXT.md
|
|
@.planning/phases/09-admin-panel-rearchitecture/09-RESEARCH.md
|
|
@.planning/phases/09-admin-panel-rearchitecture/09-PATTERNS.md
|
|
@CLAUDE.md
|
|
@frontend/src/components/admin/AdminUsersTab.vue
|
|
@frontend/src/components/admin/AdminQuotasTab.vue
|
|
@frontend/src/components/admin/AdminAiConfigTab.vue
|
|
@frontend/src/components/admin/AuditLogTab.vue
|
|
@frontend/src/views/AdminView.vue
|
|
|
|
<interfaces>
|
|
From RESEARCH.md §Pattern 4 (codebase audit):
|
|
- `AdminUsersTab.vue` — top element `<div>`, no padding.
|
|
- `AdminQuotasTab.vue` — top element `<div>`, no padding.
|
|
- `AdminAiConfigTab.vue` — top element `<div>`, no padding.
|
|
- `AuditLogTab.vue` — top element `<div>`, no padding.
|
|
|
|
Tab components currently live at depth `frontend/src/components/admin/` (two levels deep from `src/`). Extracted views live at `frontend/src/views/admin/` (also two levels deep). Therefore relative imports of the form `../../api/...`, `../../stores/...`, `../../utils/...` resolve identically from the new location — **no relative import paths need adjustment**. Any imports that go through `../layout/...` (one level up to `components/`) would break, but these tab components do NOT import any sibling component under `components/`.
|
|
|
|
Verify before extracting each file: `grep -E "^import" frontend/src/components/admin/<TabFile>.vue` — every import path should already start with `../../` (relative to `components/admin/`). If any import uses a different depth, document the rewrite in the SUMMARY.
|
|
</interfaces>
|
|
</context>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Extract AdminUsersTab.vue and AdminQuotasTab.vue to views/admin/</name>
|
|
<files>frontend/src/views/admin/AdminUsersView.vue, frontend/src/views/admin/AdminQuotasView.vue</files>
|
|
<read_first>
|
|
- frontend/src/components/admin/AdminUsersTab.vue (entire file — this is the source being promoted)
|
|
- frontend/src/components/admin/AdminQuotasTab.vue (entire file — this is the source being promoted)
|
|
- frontend/src/views/AdminView.vue (current parent — confirm which props/events these tab components rely on so the standalone views can drop the prop-passing layer)
|
|
</read_first>
|
|
<behavior>
|
|
- `AdminUsersView.vue` template + script behave identically to `AdminUsersTab.vue` for the user CRUD flows (create user, deactivate user, set quota, set AI provider, etc.).
|
|
- `AdminQuotasView.vue` template + script behave identically to `AdminQuotasTab.vue` for the quota management flows.
|
|
- Both files compile under Vite with no warnings about unused imports or unresolved paths.
|
|
- No prop is required to mount either view (AdminLayout passes nothing to its children).
|
|
</behavior>
|
|
<action>Copy the entire contents of `frontend/src/components/admin/AdminUsersTab.vue` into a new file `frontend/src/views/admin/AdminUsersView.vue`. Rename the component if the script defines a `name:` field (Options-API style) or sets `defineOptions({ name: 'AdminUsersTab' })` (Composition-API) — change `'AdminUsersTab'` to `'AdminUsersView'`. If neither convention is used, no rename is needed. Verify every import line resolves from the new path (use the rule in `<interfaces>`: `../../<segment>` resolves identically). If `AdminUsersTab.vue` declares props that were used to receive data from `AdminView.vue` and they are no longer relevant (e.g. a `currentUser` prop), remove the `defineProps` block AND audit where those props were referenced — if a prop was only used as a passthrough, replace its template references with direct store reads (`useAuthStore().user`). Do NOT change template DOM, do NOT change `onMounted` fetches, do NOT change emitted events (emitted events are dropped at the view boundary — they no longer have a parent listening; check whether any emit was the sole trigger of a fetch on the parent — if so, replace the emit with a direct re-fetch inside the view). Repeat the same extraction for `AdminQuotasTab.vue` → `frontend/src/views/admin/AdminQuotasView.vue`.</action>
|
|
<verify>
|
|
<automated>cd frontend && [ -f src/views/admin/AdminUsersView.vue ] && [ -f src/views/admin/AdminQuotasView.vue ] && diff <(sed -n '/<template>/,/<\/template>/p' src/components/admin/AdminUsersTab.vue | wc -l) <(sed -n '/<template>/,/<\/template>/p' src/views/admin/AdminUsersView.vue | wc -l) && npm run build 2>&1 | grep -E "AdminUsersView|AdminQuotasView" | grep -i error | wc -l</automated>
|
|
</verify>
|
|
<acceptance_criteria>
|
|
- `frontend/src/views/admin/AdminUsersView.vue` exists.
|
|
- `frontend/src/views/admin/AdminQuotasView.vue` exists.
|
|
- First non-comment template element of each is `<div>` (no `p-8`, `p-6`, `max-w-` class on the root).
|
|
- Line count of each new view is within ±10% of its source tab (no large unintended changes).
|
|
- `cd frontend && npm run build` succeeds with no Vite errors referencing the new view files.
|
|
- `grep -E "defineProps|props:" frontend/src/views/admin/AdminUsersView.vue` either returns no match OR every declared prop is also USED inside the template (no dead prop declarations).
|
|
- Same check for `AdminQuotasView.vue`.
|
|
- All existing API client calls in the source files appear identically in the new files (`grep -E "from '../../api/" frontend/src/views/admin/AdminUsersView.vue` returns the same count as the source).
|
|
</acceptance_criteria>
|
|
<done>AdminUsersView and AdminQuotasView are standalone views that build cleanly; behavior preserved; no top-level padding.</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 2: Extract AdminAiConfigTab.vue and AuditLogTab.vue to views/admin/</name>
|
|
<files>frontend/src/views/admin/AdminAiView.vue, frontend/src/views/admin/AdminAuditView.vue</files>
|
|
<read_first>
|
|
- frontend/src/components/admin/AdminAiConfigTab.vue (entire file)
|
|
- frontend/src/components/admin/AuditLogTab.vue (entire file — D-13: promote as-is, no feature changes)
|
|
- frontend/src/views/AdminView.vue (confirm prop-passing pattern)
|
|
</read_first>
|
|
<behavior>
|
|
- `AdminAiView.vue` template + script behave identically to `AdminAiConfigTab.vue` for the AI provider configuration flows (global system AI providers section + per-user AI assignment table, both preserved exactly per Phase 7 plan-05 pitfall 6).
|
|
- `AdminAuditView.vue` template + script behave identically to `AuditLogTab.vue` for the audit log view: filter bar, paginated table, CSV download, daily-export list (all Phase 6.2 features preserved exactly).
|
|
- Both files compile under Vite with no warnings.
|
|
- Dynamic color classes used in `AuditLogTab.vue` (`bg-blue-50 text-blue-600`, `bg-purple-50 text-purple-600`, `bg-amber-50 text-amber-700`, `bg-gray-100 text-gray-600`) continue to be generated via the same `actionTypeClass()` helper in the new view — DO NOT inline these classes or hardcode them.
|
|
</behavior>
|
|
<action>Copy `frontend/src/components/admin/AdminAiConfigTab.vue` to `frontend/src/views/admin/AdminAiView.vue`. Apply the same rules as Task 1: rename component name if explicit, drop dead `defineProps`, replace orphaned `emit` calls with direct re-fetch where the emit was the only refresh trigger. Note: the cross-cutting constraint from Phase 7 (AdminAiConfigTab.vue per-user assignment table is preserved untouched; global system section is ABOVE it) must remain — do not reorder sections. Copy `frontend/src/components/admin/AuditLogTab.vue` to `frontend/src/views/admin/AdminAuditView.vue`. D-13 mandates **as-is** promotion — no new features, no template tweaks. The `actionTypeClass()` function MUST be preserved verbatim (its `bg-amber-50 text-amber-700` etc. drive the safelist requirement closed in 09-04). Verify the import paths still resolve from `views/admin/` (the depth is unchanged from `components/admin/`).</action>
|
|
<verify>
|
|
<automated>cd frontend && [ -f src/views/admin/AdminAiView.vue ] && [ -f src/views/admin/AdminAuditView.vue ] && grep -c "actionTypeClass" src/views/admin/AdminAuditView.vue && npm run build 2>&1 | grep -E "AdminAiView|AdminAuditView" | grep -i error | wc -l</automated>
|
|
</verify>
|
|
<acceptance_criteria>
|
|
- `frontend/src/views/admin/AdminAiView.vue` exists.
|
|
- `frontend/src/views/admin/AdminAuditView.vue` exists.
|
|
- First non-comment template element of each is `<div>` (no top-level padding).
|
|
- `grep -c "actionTypeClass" frontend/src/views/admin/AdminAuditView.vue` returns at least 1 (helper preserved).
|
|
- `grep -c "bg-amber-50" frontend/src/views/admin/AdminAuditView.vue` returns at least 1 (D-13 as-is preservation).
|
|
- `grep -c "bg-purple-50" frontend/src/views/admin/AdminAuditView.vue` returns at least 1.
|
|
- `grep -c "System AI" frontend/src/views/admin/AdminAiView.vue` returns at least 1 (global system section title preserved from Phase 7).
|
|
- `cd frontend && npm run build` succeeds.
|
|
- Line counts within ±10% of source tab components.
|
|
</acceptance_criteria>
|
|
<done>AdminAiView + AdminAuditView are standalone, build cleanly, preserve all Phase 6.2/7 behavior; dynamic color classes still produced through `actionTypeClass()`.</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<threat_model>
|
|
## Trust Boundaries
|
|
|
|
| Boundary | Description |
|
|
|----------|-------------|
|
|
| (none new) | Behavior-preserving extraction; no new ingress, egress, or trust transitions |
|
|
|
|
## STRIDE Threat Register
|
|
|
|
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|
|
|-----------|----------|-----------|-------------|-----------------|
|
|
| T-09-03-01 | Tampering | Tab-to-view extraction | mitigate | Verbatim copy of template + script preserves behavior; line-count check ±10% catches accidental edits; `npm run build` catches resolution errors |
|
|
| T-09-03-02 | Information Disclosure | Orphaned emit handlers | mitigate | Action step audits every `emit(...)` for orphaned parent listeners and replaces them with direct re-fetches so no admin action silently no-ops (e.g., user creation modal closing without triggering list refresh) |
|
|
</threat_model>
|
|
|
|
<verification>
|
|
- `cd frontend && npm run build` → succeeds.
|
|
- All four new view files exist under `frontend/src/views/admin/`.
|
|
- Each view's first template element is `<div>` with no top-level padding class.
|
|
- Original tab components in `frontend/src/components/admin/` are untouched (deletion happens in 09-04).
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- ADMIN-08: Four standalone admin view files exist under `frontend/src/views/admin/`.
|
|
- ADMIN-10: Each view is a self-contained component that the router can mount as a child of `/admin` (router wiring lands in 09-04).
|
|
- Behavior preserved: every admin CRUD/filter/download interaction continues to work after wiring in 09-04.
|
|
</success_criteria>
|
|
|
|
<output>
|
|
Create `.planning/phases/09-admin-panel-rearchitecture/09-03-SUMMARY.md` when done. List the four new files, any dead-prop removals, and any orphaned-emit-to-fetch replacements made during extraction.
|
|
</output>
|