docs(02): add root causes from diagnosis
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
---
|
||||
status: complete
|
||||
status: diagnosed
|
||||
phase: 02-users-authentication
|
||||
source: [02-01-SUMMARY.md, 02-02-SUMMARY.md, 02-03-SUMMARY.md, 02-04-SUMMARY.md, 02-05-SUMMARY.md]
|
||||
started: 2026-05-31T00:00:00Z
|
||||
@@ -116,53 +116,96 @@ blocked: 2
|
||||
reason: "User reported: I don't see an option to activate or setup a 2FA method."
|
||||
severity: major
|
||||
test: 4
|
||||
artifacts: []
|
||||
missing: []
|
||||
root_cause: "AccountView.vue (which contains TotpEnrollment) is registered at /account but unreachable through the UI. The sidebar links to /settings (SettingsView.vue), which has only Preferences/AI/Cloud tabs — no Account or Security tab. /account is an orphaned route."
|
||||
artifacts:
|
||||
- path: "frontend/src/components/layout/AppSidebar.vue"
|
||||
issue: "No navigation link to /account — sidebar only links to /settings"
|
||||
- path: "frontend/src/views/SettingsView.vue"
|
||||
issue: "No Account/Security tab that would surface AccountView's TOTP content"
|
||||
missing:
|
||||
- "Add Account/Security tab to SettingsView.vue (or sidebar link to /account)"
|
||||
- "User account page should be discoverable from main navigation"
|
||||
|
||||
- truth: "Auth/login pages use AuthLayout (no sidebar, no user identity) so previously logged-in user info is never shown on public pages"
|
||||
status: failed
|
||||
reason: "User reported: I do see the sidebar every time when I login. I do not want the sidebar on the login page and I do not want to leak this information of the previous logged in user when no one is logged in. Confirmed again on logout: sidebar still visible while logged out."
|
||||
severity: major
|
||||
test: 6
|
||||
artifacts: []
|
||||
missing: []
|
||||
root_cause: "App.vue renders <AppSidebar /> unconditionally in the root template — no route-meta check, no layout switching. AuthLayout.vue exists and is correctly implemented but is never imported or used anywhere. Auth routes only have meta: { public: true }; there is no meta.layout hint and App.vue never reads it."
|
||||
artifacts:
|
||||
- path: "frontend/src/App.vue"
|
||||
issue: "<AppSidebar /> is an unconditional child in the root template — no v-if or layout switch"
|
||||
- path: "frontend/src/router/index.js"
|
||||
issue: "Auth routes missing meta: { layout: 'auth' } — no layout hint for App.vue to consume"
|
||||
- path: "frontend/src/layouts/AuthLayout.vue"
|
||||
issue: "Correctly implemented but dead — never imported or activated by any code path"
|
||||
missing:
|
||||
- "App.vue must become layout-aware: read route.meta.layout and conditionally render AuthLayout vs app shell"
|
||||
- "Auth routes (/login, /register, /password-reset, /password-reset/confirm) need meta: { layout: 'auth' }"
|
||||
|
||||
- truth: "After logout, the sidebar (including user identity footer) is no longer visible — user is on the login page with AuthLayout only"
|
||||
status: failed
|
||||
reason: "User reported: I am logged out right now but I still see the sidebar, which is not a desired behaviour."
|
||||
severity: major
|
||||
test: 7
|
||||
artifacts: []
|
||||
missing: []
|
||||
root_cause: "Same root cause as test 6 — App.vue always renders AppSidebar regardless of route. Fixed by the same App.vue layout-aware change."
|
||||
artifacts:
|
||||
- path: "frontend/src/App.vue"
|
||||
issue: "Same as test 6 — AppSidebar always rendered"
|
||||
missing:
|
||||
- "Same fix as test 6 — covered by same plan task"
|
||||
|
||||
- truth: "TOTP enrollment flow: no QR code required (otpauth:// link + manual secret is acceptable), but the manual secret must be valid and correctly rendered so users can add it to an authenticator app"
|
||||
- truth: "TOTP enrollment flow: QR code rendered so desktop users can scan without manually typing a 32-char secret"
|
||||
status: failed
|
||||
reason: "User reported: no QR code visible (expected — known MVP stub), security key doesn't work (possibly misspelled in display), otpauth:// link opens macOS Passwords app (expected behavior on Mac)."
|
||||
reason: "User reported: no QR code visible, security key doesn't work (possibly misspelled in display), otpauth:// link opens macOS Passwords app instead of working on desktop."
|
||||
severity: major
|
||||
test: 9
|
||||
artifacts: []
|
||||
missing: []
|
||||
root_cause: "TotpEnrollment.vue renders a plain <a href='otpauth://...'> hyperlink instead of a QR image. No QR library is installed (package.json has no qrcode/qr.js). The otpauth:// protocol has no default handler on desktop browsers. The backend secret is correct (valid base32, correct URI) — only the frontend rendering is wrong."
|
||||
artifacts:
|
||||
- path: "frontend/src/components/auth/TotpEnrollment.vue"
|
||||
issue: "Renders <a href='otpauth://...'> text link instead of QR image — comment says 'no QR library dependency' confirming intentional omission"
|
||||
- path: "frontend/package.json"
|
||||
issue: "No QR code library installed (qrcode, qr.js, etc.)"
|
||||
missing:
|
||||
- "Add qrcode npm package"
|
||||
- "Render QR image from qrUri in TotpEnrollment.vue step 1"
|
||||
|
||||
- truth: "Account settings (/account) is presented as a tab within a unified Settings page, not a standalone route"
|
||||
status: failed
|
||||
reason: "User requested: account page should be a tab inside a settings page (UX improvement)"
|
||||
severity: minor
|
||||
test: 9
|
||||
artifacts: []
|
||||
missing: []
|
||||
root_cause: "AccountView.vue is a standalone route at /account. SettingsView.vue exists but has no Account/Security tab. User wants a unified settings experience."
|
||||
artifacts:
|
||||
- path: "frontend/src/views/SettingsView.vue"
|
||||
issue: "Missing Account/Security tab"
|
||||
- path: "frontend/src/views/AccountView.vue"
|
||||
issue: "Standalone orphaned view — should be merged into settings as a tab"
|
||||
missing:
|
||||
- "Merge AccountView content into SettingsView as a new Account/Security tab"
|
||||
- "Update router to redirect /account to /settings (account tab)"
|
||||
|
||||
- truth: "Non-admin users are blocked from /admin (redirected or shown 403); the Admin link is hidden in the sidebar for non-admins"
|
||||
status: failed
|
||||
reason: "User reported: can navigate to /admin as a non-admin user; all tabs visible but no data shown (backend blocks data but frontend does not block the route)"
|
||||
severity: major
|
||||
test: 14
|
||||
artifacts: []
|
||||
missing: []
|
||||
root_cause: "The /admin route in router/index.js has no meta field at all. The beforeEach guard only checks accessToken — it never reads user.role. Any authenticated user passes through. The authStore.user (including role) is reliably populated before the guard completes, so there is no timing issue — the guard simply never checks role."
|
||||
artifacts:
|
||||
- path: "frontend/src/router/index.js"
|
||||
issue: "/admin route definition has no meta property; beforeEach guard has zero role-checking logic"
|
||||
missing:
|
||||
- "Add meta: { requiresAdmin: true } to /admin route"
|
||||
- "Add admin role check in beforeEach: if to.meta.requiresAdmin && user.role !== 'admin' → redirect to /"
|
||||
|
||||
- truth: "Admin can create a new user via the Users tab form — POST /api/admin/users returns 201 and the new user appears in the table"
|
||||
status: failed
|
||||
reason: "User reported: cannot create a new user as admin; form returns HTTP 500 error."
|
||||
severity: blocker
|
||||
test: 15
|
||||
artifacts: []
|
||||
missing: []
|
||||
root_cause: "Missing 'await session.flush()' before write_audit_log() in the admin create_user handler. Three pending objects (User, Quota, AuditLog) flush without guaranteed ordering — on PostgreSQL, the FK constraint on audit_log.user_id causes an IntegrityError when AuditLog is flushed before the User row exists. SQLite (used in tests) has FK enforcement disabled by default, so all unit tests pass silently."
|
||||
artifacts:
|
||||
- path: "backend/api/admin.py"
|
||||
issue: "Missing 'await session.flush()' after session.add(quota) and before write_audit_log() — User+Quota not persisted when AuditLog FK references users.id"
|
||||
missing:
|
||||
- "Add 'await session.flush()' after session.add(quota) in create_user handler — matches pattern already used in auth/register and bootstrap_admin"
|
||||
|
||||
Reference in New Issue
Block a user