--- phase: 02-users-authentication plan: "06" subsystem: frontend-auth-ux tags: [gap-closure, auth-layout, admin-guard, qr-code, settings-ux] dependency_graph: requires: ["02-05"] provides: ["auth-layout-switching", "admin-role-guard", "account-settings-tab", "totp-qr-image"] affects: ["frontend/src/App.vue", "frontend/src/router/index.js", "frontend/src/views/SettingsView.vue"] tech_stack: added: ["qrcode@1.5.4"] patterns: ["layout-switching via route.meta.layout", "role guard in beforeEach", "AccountView content extracted to SettingsAccountTab"] key_files: created: - frontend/src/components/settings/SettingsAccountTab.vue modified: - frontend/src/App.vue - frontend/src/router/index.js - frontend/src/views/SettingsView.vue - frontend/src/components/auth/TotpEnrollment.vue - frontend/package.json decisions: - "AuthLayout rendered unconditionally by App.vue via v-if on route.meta.layout — AuthLayout owns its own router-view" - "requiresAdmin guard appended to existing beforeEach after silent refresh — non-admin redirected to /" - "SettingsAccountTab created as standalone component (not inline in SettingsView) to keep SettingsView manageable" - "/account route redirects to /settings; AccountView.vue kept on disk but unreachable from router" metrics: duration: "~25 minutes" completed: "2026-05-31T18:40:52Z" tasks_completed: 3 tasks_total: 3 files_created: 1 files_modified: 5 --- # Phase 02 Plan 06: UAT Gap Closure — Auth Layout + Admin Guard + Account Tab + QR Code One-liner: Five UAT gaps closed — layout-aware App.vue, admin route guard, Account settings tab extracted from AccountView, and TOTP QR image via qrcode library. ## Tasks Completed | Task | Description | Commit | Files | |------|-------------|--------|-------| | 1 | Verify backend fix + regression test for admin create_user (GAP 1) | (verify-only, no code change) | backend/api/admin.py (confirmed), backend/tests/test_admin_api.py (confirmed) | | 2 | Auth route layout switching + admin role guard (GAPs 2, 3, 4) | aa957d6 | frontend/src/App.vue, frontend/src/router/index.js | | 3 | AccountView merged into SettingsView as Account tab + QR code in TotpEnrollment (GAPs 3 and 5) | c08ea42 | frontend/package.json, frontend/src/components/auth/TotpEnrollment.vue, frontend/src/views/SettingsView.vue, frontend/src/components/settings/SettingsAccountTab.vue | ## What Was Built ### Task 1: Backend verification (GAP 1 — admin create_user HTTP 500) Confirmed `await session.flush()` at admin.py:247 (before `write_audit_log()`) and `test_create_user_writes_audit_log` test in test_admin_api.py. Both were already present from plan 02-04. Test passed on first run. No code changes made — verification only. ### Task 2: Auth layout switching + admin role guard (GAPs 2, 3, 4) **App.vue** refactored to layout-aware root component: - `v-if="route.meta.layout === 'auth'"` renders `` which owns its own `` - `v-else` renders the full app shell (AppSidebar + router-view) - Added `useRoute` import; `AuthLayout` import from `./layouts/AuthLayout.vue` **router/index.js** three changes: - All four auth routes (`/login`, `/register`, `/password-reset`, `/password-reset/confirm`) updated with `meta: { public: true, layout: 'auth' }` - `/admin` route updated with `meta: { requiresAdmin: true }` - `beforeEach` extended with role check: `if (to.meta.requiresAdmin && authStore.user?.role !== 'admin') return { path: '/' }` - `/account` route changed to `{ path: '/account', redirect: '/settings' }` — AccountView now embedded in SettingsView ### Task 3: AccountView merged into SettingsView + QR code (GAPs 3 and 5) **qrcode@1.5.4** installed as runtime dependency (verified 20M+ weekly downloads, canonical npm package). **TotpEnrollment.vue** updated: - Added `import QRCode from 'qrcode'` - Added `qrDataUrl` ref - In `startSetup()`: `qrDataUrl.value = await QRCode.toDataURL(qrUri.value, { width: 200, margin: 1 })` - Replaced `` link block with `TOTP QR code` - Manual secret display (`` block) kept as fallback **SettingsAccountTab.vue** created at `frontend/src/components/settings/`: - Full AccountView content without the outer page wrapper (`
` and `

` heading removed) - All four sections: Account information, Two-factor authentication (TotpEnrollment), Change password (PasswordStrengthBar), Sessions (sign-out-all) - All script setup logic ported: changePassword, disableTotp, onTotpEnrolled, signOutAll, all refs - Import paths adjusted for new location (`../../stores/auth.js`, `../auth/...`, `../ui/...`) **SettingsView.vue** updated: - Added `{ id: 'account', label: 'Account' }` to tabs array - Added `` panel - Added `import SettingsAccountTab from '../components/settings/SettingsAccountTab.vue'` ## Verification Results | Check | Result | |-------|--------| | `pytest tests/test_admin_api.py::test_create_user_writes_audit_log -v` | PASSED | | `npm run build` | Exit 0, 156 modules transformed | | `npm test` | 107/107 passed (11 test files) | | `pytest -v` (full backend) | 343 passed, 1 pre-existing failure (test_extract_docx — missing docx module, unrelated) | | 4 auth routes have `meta.layout:'auth'` | Confirmed (grep count = 4) | | `/admin` has `meta.requiresAdmin` | Confirmed | | `requiresAdmin` role check in `beforeEach` | Confirmed | | `qrcode` in package.json dependencies | Confirmed (`"qrcode": "^1.5.4"`) | | `QRCode.toDataURL` + `img` tag in TotpEnrollment | Confirmed | | `SettingsAccountTab` imported and rendered in SettingsView | Confirmed | ## Deviations from Plan None — plan executed exactly as written. Task 1 was verify-only; the fix was already present from plan 02-04 execution. ## Known Stubs None. All functional paths are wired. ## Threat Flags No new threat surface introduced. Changes are frontend-only layout/UX routing (Task 1 is backend verify-only with no code changes). The requiresAdmin guard closes T-02-GAP-01 (elevation of privilege). The auth layout conditional closes T-02-GAP-02 (information disclosure via sidebar on public routes). ## Self-Check: PASSED Files confirmed present: - frontend/src/App.vue (modified) - frontend/src/router/index.js (modified) - frontend/src/components/settings/SettingsAccountTab.vue (created) - frontend/src/views/SettingsView.vue (modified) - frontend/src/components/auth/TotpEnrollment.vue (modified) - frontend/package.json (modified) Commits confirmed: - aa957d6 feat(02-06): auth layout switching + admin role guard (GAPs 2, 3, 4) - c08ea42 feat(02-06): Account tab in SettingsView + QR code in TotpEnrollment (GAPs 3, 5)