docs(02-06): complete UAT gap closure plan summary
- SUMMARY.md for plan 02-06 (5 UAT gaps closed) - Backend fix verified; frontend auth layout, admin guard, Account tab, QR code implemented
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
---
|
||||
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 `<AuthLayout />` which owns its own `<router-view />`
|
||||
- `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 `<a :href="qrUri">` link block with `<img v-if="qrDataUrl" :src="qrDataUrl" alt="TOTP QR code" ...>`
|
||||
- Manual secret display (`<code>` block) kept as fallback
|
||||
|
||||
**SettingsAccountTab.vue** created at `frontend/src/components/settings/`:
|
||||
- Full AccountView content without the outer page wrapper (`<div class="p-8 max-w-2xl mx-auto">` and `<h2>` 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 `<SettingsAccountTab v-if="activeTab === 'account'" />` 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)
|
||||
Reference in New Issue
Block a user