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>
171 lines
8.1 KiB
Markdown
171 lines
8.1 KiB
Markdown
---
|
|
phase: 08-stack-upgrade-backend-decomposition
|
|
plan: "03"
|
|
subsystem: frontend-toast-store
|
|
tags: [frontend, toast, pinia, session-revocation, xfail-promotion, cr-01, cr-02, cr-03, wave-1]
|
|
dependency_graph:
|
|
requires:
|
|
- "08-01: xfail stubs for CR-01/CR-02/CR-03 (decorators to remove)"
|
|
provides:
|
|
- "frontend/src/stores/toast.js: locked show(message, type, duration) contract for Phase 10"
|
|
- "SettingsAccountTab.vue: uses toastStore.show() in changePassword + disableTotp"
|
|
- "TotpEnrollment.vue: uses toastStore.show() in confirmEnrollment"
|
|
- "CR-01/CR-02/CR-03 tests passing strictly (not xfail)"
|
|
affects:
|
|
- "frontend/src/components/settings/SettingsAccountTab.vue — inline toast removed"
|
|
- "frontend/src/components/auth/TotpEnrollment.vue — inline toast removed"
|
|
- "backend/tests/test_auth.py — xfail decorators removed from 3 tests"
|
|
tech_stack:
|
|
added: []
|
|
patterns:
|
|
- "setup-store Pinia pattern: defineStore('toast', () => { ... return { show } })"
|
|
- "vi.mock('../../stores/toast.js', ...) pattern for isolating toast calls in component tests"
|
|
key_files:
|
|
created:
|
|
- path: "frontend/src/stores/toast.js"
|
|
description: "Phase 7.1 stub — show(message, type='success', duration=4000) no-op; Phase 10 implements rendering"
|
|
modified:
|
|
- path: "frontend/src/components/settings/SettingsAccountTab.vue"
|
|
description: "Removed sessionRevokedToast ref + setTimeout + inline HTML; wired to toastStore.show()"
|
|
- path: "frontend/src/components/auth/TotpEnrollment.vue"
|
|
description: "Removed sessionRevokedToast ref + setTimeout + inline HTML; wired to toastStore.show()"
|
|
- path: "frontend/src/components/settings/__tests__/SettingsAccountTab.test.js"
|
|
description: "Replaced DOM text assertions with mockShow spy assertions"
|
|
- path: "frontend/src/components/auth/__tests__/TotpEnrollment.test.js"
|
|
description: "Replaced DOM text assertions with mockShow spy assertions"
|
|
- path: "backend/tests/test_auth.py"
|
|
description: "Removed @pytest.mark.xfail from 3 tests; all now PASSED"
|
|
decisions:
|
|
- "toast.js uses positional parameters only per UI-SPEC.md — object-argument shape (show({message, type})) explicitly forbidden"
|
|
- "Frontend tests updated to mock useToastStore and assert on show() spy rather than DOM text — the stub is a no-op so DOM assertions would always fail"
|
|
- "The node_modules symlink created during testing was removed before commit — only the worktree src/ files are modified"
|
|
metrics:
|
|
duration: "~6m"
|
|
completed: "2026-06-08"
|
|
tasks_completed: 3
|
|
tasks_total: 3
|
|
files_created: 1
|
|
files_modified: 5
|
|
---
|
|
|
|
# Phase 8 Plan 03: useToastStore Stub + CR Session-Revocation Wire-Up Summary
|
|
|
|
**One-liner:** Pinia toast stub with locked show(message, type, duration) contract wired to session-revocation call sites in SettingsAccountTab + TotpEnrollment, with CR-01/CR-02/CR-03 backend tests promoted from xfail to strictly passing.
|
|
|
|
## What Was Built
|
|
|
|
### Task 1: useToastStore Pinia stub (commit e417b71)
|
|
|
|
Created `frontend/src/stores/toast.js` as a setup-store Pinia stub:
|
|
|
|
```js
|
|
export const useToastStore = defineStore('toast', () => {
|
|
function show(message, type = 'success', duration = 4000) {
|
|
// No-op stub — Phase 10 implements rendering.
|
|
}
|
|
return { show }
|
|
})
|
|
```
|
|
|
|
The signature matches UI-SPEC.md exactly. Phase 10 (UX-10) must implement rendering without modifying any call site.
|
|
|
|
### Task 2: Component refactor (commit 3b8e2c1)
|
|
|
|
Removed from both components:
|
|
- `const sessionRevokedToast = ref(false)` declaration
|
|
- Inline `<div v-if="sessionRevokedToast" ...>` toast HTML block
|
|
- `setTimeout(() => { sessionRevokedToast.value = false }, 5000)` auto-dismiss pattern
|
|
|
|
Added to both components:
|
|
- `import { useToastStore } from '../../stores/toast.js'`
|
|
- `const toastStore = useToastStore()`
|
|
- `toastStore.show('Other sessions have been terminated.', 'success')` in each relevant handler
|
|
|
|
Updated frontend tests to mock `useToastStore` via `vi.mock` and assert on the `show` spy instead of DOM text (the stub is a no-op, so DOM text assertions would always fail after migration).
|
|
|
|
### Task 3: xfail promotion (commit 44ec28d)
|
|
|
|
Removed `@pytest.mark.xfail(reason="Wave 0 stub — promoted to passing in 08-03", strict=False)` from all three tests:
|
|
|
|
```
|
|
tests/test_auth.py::test_change_password_revokes_other_sessions PASSED
|
|
tests/test_auth.py::test_enable_totp_revokes_other_sessions PASSED
|
|
tests/test_auth.py::test_disable_totp_revokes_other_sessions PASSED
|
|
```
|
|
|
|
## Final Test Output
|
|
|
|
### Backend — three CR tests (pytest -v)
|
|
|
|
```
|
|
tests/test_auth.py::test_change_password_revokes_other_sessions PASSED [ 33%]
|
|
tests/test_auth.py::test_enable_totp_revokes_other_sessions PASSED [ 66%]
|
|
tests/test_auth.py::test_disable_totp_revokes_other_sessions PASSED [100%]
|
|
|
|
======================== 3 passed, 10 warnings in 2.51s ========================
|
|
```
|
|
|
|
All three show PASSED (not XPASS, not XFAIL, not SKIPPED).
|
|
|
|
### Frontend — component tests
|
|
|
|
```
|
|
Test Files 15 passed (15 directly relevant)
|
|
Tests 134 passed (component tests all pass)
|
|
2 pre-existing failures in tests/api.spec.js (testAiConnection) — unrelated to this plan, pre-existed before Plan 08-03
|
|
```
|
|
|
|
## Components Not Touched
|
|
|
|
No other components were modified. The only files changed are:
|
|
- `frontend/src/stores/toast.js` (new)
|
|
- `frontend/src/components/settings/SettingsAccountTab.vue`
|
|
- `frontend/src/components/auth/TotpEnrollment.vue`
|
|
- `frontend/src/components/settings/__tests__/SettingsAccountTab.test.js`
|
|
- `frontend/src/components/auth/__tests__/TotpEnrollment.test.js`
|
|
- `backend/tests/test_auth.py`
|
|
|
|
## Forward Reference: Phase 10 Toast Contract (Locked)
|
|
|
|
The `show(message, type, duration)` signature defined in `frontend/src/stores/toast.js` is now locked. Phase 10 (UX-10) must:
|
|
|
|
1. Implement rendering in the same store without modifying the method signature
|
|
2. NOT change any call site — the 3 call sites in SettingsAccountTab and TotpEnrollment must remain unchanged
|
|
3. Honor `type='success'` for the sessions-revoked notification
|
|
4. Apply the visual spec from UI-SPEC.md §"Sessions-Revoked Notification" (fixed `top-4 right-4 z-50`, `border-green-200`, `duration=4000`)
|
|
|
|
## Deviations from Plan
|
|
|
|
### Auto-fixed Issues
|
|
|
|
**1. [Rule 1 - Bug] Frontend component tests assert on DOM text that becomes absent after toast migration**
|
|
|
|
- **Found during:** Task 2 — identified before writing code
|
|
- **Issue:** Existing `SettingsAccountTab.test.js` and `TotpEnrollment.test.js` tests used `expect(wrapper.text()).toContain('Other sessions have been terminated.')` — assertions relying on the inline DOM block that was removed by the migration. After migration, the toast store is a no-op, so the text never appears in the DOM.
|
|
- **Fix:** Updated both test files to mock `useToastStore` via `vi.mock` and assert on the mock's `show` spy: `expect(mockShow).toHaveBeenCalledWith('Other sessions have been terminated.', 'success')`.
|
|
- **Files modified:** `SettingsAccountTab.test.js`, `TotpEnrollment.test.js`
|
|
- **Commits:** 3b8e2c1
|
|
|
|
## Threat Surface Scan
|
|
|
|
No new network endpoints, auth paths, file access patterns, or schema changes introduced. The toast store is an in-process Pinia store with no I/O.
|
|
|
|
## Known Stubs
|
|
|
|
The `useToastStore.show()` method is intentionally a stub in this phase. This is documented as a forward reference to Phase 10 (UX-10). The stub does not prevent the plan's goal (wiring the call contract) — it only defers rendering.
|
|
|
|
## Self-Check: PASSED
|
|
|
|
- [x] `frontend/src/stores/toast.js` exists
|
|
- [x] `grep -c "export const useToastStore"` = 1
|
|
- [x] `grep -c "defineStore('toast'"` = 1
|
|
- [x] `grep -c "function show(message, type = 'success', duration = 4000)"` = 1
|
|
- [x] `grep -c "sessionRevokedToast" frontend/src/` = 0 (clean)
|
|
- [x] `grep -c "toastStore.show('Other sessions have been terminated.', 'success')" SettingsAccountTab.vue` = 2
|
|
- [x] `grep -c "toastStore.show('Other sessions have been terminated.', 'success')" TotpEnrollment.vue` = 1
|
|
- [x] Commit e417b71 exists (toast store)
|
|
- [x] Commit 3b8e2c1 exists (component refactor)
|
|
- [x] Commit 44ec28d exists (xfail promotion)
|
|
- [x] Three backend tests show PASSED (not XPASS)
|
|
- [x] No xfail decorators on the three promoted tests
|