- Options API component with segments/{id?,label}, rootLabel, showRoot props
- Emits navigate(segment.id) for intermediate clicks, navigate(null) for root
- Computed visibleSegments collapses >4 segments to first+ellipsis+last two
- Segments without id render as plain non-clickable spans (admin static segments)
- Uses AppIcon for chevronRight separator (no inline SVG)
- All 10 Vitest tests pass
- Also creates AppIcon.vue (Rule 3: BreadcrumbBar imports it)
- Options API component with props: icon, headline, subtext, size
- Computed containerClass/iconClass/headlineClass/subtextClass for md and sm variants
- Named #cta slot with no fallback content
- Imports AppIcon from ./AppIcon.vue (child component)
- Also creates AppIcon.vue (deviation Rule 3: required to resolve EmptyState import)
- All 7 EmptyState tests pass; all 144 tests pass
- toast.js: reactive toasts array, show/dismiss with auto-dismiss via setTimeout
- ToastContainer.vue: Options API, Teleport to body, TransitionGroup, data-test attr
- type-to-class maps: accentClass/iconName/iconColorClass for success/error/warning/info
- App.vue: import and mount <ToastContainer /> after layout div
- all 10 tests pass; SettingsAccountTab and TotpEnrollment regressions green
- Options API component with inheritAttrs: false for class forwarding
- 32 named icons: 31 single-path + 1 dual-path (cog as Array)
- resolvedPaths computed warns in DEV for unknown icon names
- v-if guard renders nothing for unknown names
- Array.isArray check renders v-for paths for dual-path icons
- All 6 AppIcon tests pass (GREEN)
- 6 tests covering name→path rendering, class forwarding, dual-path (cog), svg attrs, unknown-name warn, and path stroke attrs
- RED phase: AppIcon.vue does not exist yet; tests fail on import
All 9 UAT items verified via live API + source inspection:
- GET /api/admin/overview live data (78 users, 8MB storage, 10 audit rows)
- Auth guard: 401 unauthenticated, 403 non-admin on all protected endpoints
- Admin login redirect (D-08) confirmed in LoginView.vue line 212
- Sidebar: 5 nav links, indigo Admin badge, no back-to-app link
- 4-stat-card overview + When/Event/Actor/Target/IP audit table
- 5 standalone admin views (Users, Quotas, AI, Audit) with no Pinia stores
- API key write-only invariant confirmed in AdminAiView.vue
- Color-coded audit badges (auth=blue, admin=amber, folder/share=purple)
- to.matched.some() guard covers all /admin/* child routes
- No sensitive fields (password_hash, credentials_enc) in any response
Phase 9 marked complete. STATE.md and PROJECT.md updated for Phase 10.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- After successful login, admin users redirect to /admin; regular users to /
- Honors ?redirect= query param for non-admin users as before
- authStore.user.role is synchronously populated before handleLoginResult fires
- Created frontend/src/views/admin/AdminAiView.vue (extracted from AdminAiConfigTab.vue)
- Import path for SearchableModelSelect rewritten to ../../components/ui/SearchableModelSelect.vue
- System AI Providers (Global) section preserved above per-user table (Phase 7 constraint)
- Created frontend/src/views/admin/AdminAuditView.vue (verbatim from AuditLogTab.vue per D-13)
- actionTypeClass() helper preserved verbatim with all bg-amber-50, bg-purple-50 dynamic classes
- Filter bar, paginated table, CSV download, daily-export list all preserved as-is
- Both files have no defineProps, no top-level padding, identical line counts to sources
- Build succeeds: 143 modules transformed, no errors
- Created frontend/src/views/admin/AdminUsersView.vue (verbatim extraction of AdminUsersTab.vue)
- Created frontend/src/views/admin/AdminQuotasView.vue (verbatim extraction of AdminQuotasTab.vue)
- Both files have no defineProps, no top-level padding, identical import paths (../../api/client.js, ../../utils/formatters.js)
- Line counts match source exactly (480 and 182 lines respectively)
- Build succeeds with no Vite errors referencing new view files
- New backend/api/admin/overview.py: aggregate stats (user_count,
total_storage_bytes, doc_status) + last 10 audit entries in one payload
- Sub-router carries NO prefix (parent __init__.py carries /api/admin)
- Reuses _build_filtered_query_with_handles + _audit_to_dict_with_handles
from api.audit — no new serializer or query logic
- Registered overview_router on admin parent router in __init__.py
- All 8 ADMIN-11 tests pass; existing admin and audit suites stay green
- Single-fetch view calling getAdminOverview() on mount with loading/error states
- Four stat cards grid (Users, Storage, Processing, Ready) per ADMIN-11 and D-01
- Recent audit table with 5 columns (When/Event/Actor/Target/IP) matching AuditLogTab.vue structure
- Uses formatSize/formatDate from shared utils/formatters.js (no duplication)
- No top-level padding (AdminLayout owns p-8 max-w-5xl mx-auto)
- No Pinia store — single-fetch component consistent with admin tab pattern
- AdminLayout: flex h-screen shell with AdminSidebar + main content area (p-8 max-w-5xl mx-auto router-view)
- AdminSidebar: 5 nav links in D-07 order (Overview/Users/Quotas/AI Config/Audit Log) with SVG icons
- Admin badge subtitle ("Admin" in indigo-500 per D-05) replaces "Document Manager"
- No Back-to-app link (D-06 applied)
- User identity footer + sign-out reused verbatim from AppSidebar.vue pattern
- Scoped nav-link/nav-link-active CSS identical to AppSidebar.vue