diff --git a/.planning/HANDOFF.json b/.planning/HANDOFF.json
new file mode 100644
index 0000000..4aeab04
--- /dev/null
+++ b/.planning/HANDOFF.json
@@ -0,0 +1,57 @@
+{
+ "version": "1.0",
+ "timestamp": "2026-06-12T08:33:19.724Z",
+ "phase": "08",
+ "phase_name": "stack-upgrade-backend-decomposition",
+ "phase_dir": ".planning/phases/08-stack-upgrade-backend-decomposition",
+ "plan": 8,
+ "task": 0,
+ "total_tasks": 3,
+ "status": "paused",
+ "completed_tasks": [
+ {"id": "08-01", "name": "xfail stubs + CR contract locks", "status": "done", "commit": "c636ac9"},
+ {"id": "08-02", "name": "CloudConnectionOut migration + schemas.py", "status": "done", "commit": "98dcf80"},
+ {"id": "08-03", "name": "CR-01/02/03 session-revocation + toastStore stub", "status": "done", "commit": "aa1c5ee"},
+ {"id": "08-04", "name": "Admin API decomposition → admin/ package", "status": "done", "commit": "f01fb0e"},
+ {"id": "08-05", "name": "Documents API decomposition → documents/ package", "status": "done", "commit": "81337bd"},
+ {"id": "08-06", "name": "Auth API decomposition → auth/ package (CR-01/02/03 preserved)", "status": "done", "commit": "5117e25"},
+ {"id": "08-07", "name": "Frontend api/client.js → 7 domain modules + utils.js", "status": "done", "commit": "7e99b6e"}
+ ],
+ "remaining_tasks": [
+ {
+ "id": "08-08",
+ "name": "Dependency upgrades — vite@6, @vueuse/core, tailwind-forms, backend == pins",
+ "status": "not_started",
+ "autonomous": false,
+ "requires_human": "User must verify packages on npmjs.com before execution (see plan frontmatter user_setup)"
+ }
+ ],
+ "blockers": [],
+ "human_actions_pending": [
+ {
+ "action": "Verify npm packages on npmjs.com before executing plan 08-08",
+ "context": "Plan 08-08 is autonomous:false and requires manual package verification: @vueuse/core, @vueuse/integrations, sortablejs, @tailwindcss/forms, rollup-plugin-visualizer, @types/sortablejs, vite@^6.4.3, @vitejs/plugin-vue — each must show legitimate maintainer, weekly downloads > 10k, no recent malware advisories",
+ "blocking": true
+ }
+ ],
+ "decisions": [
+ {
+ "decision": "list_documents registered directly on parent router in documents/__init__.py (not via include_router)",
+ "rationale": "FastAPI 0.128 raises 'Prefix and path cannot be both empty' when include_router gets prefix='' and route.path=''. Direct router.add_api_route('') on parent avoids the check.",
+ "phase": "08"
+ },
+ {
+ "decision": "extract_and_classify and get_storage_backend_for_document re-exported from api.documents.__init__",
+ "rationale": "Test monkeypatching targets api.documents.X names. After decomposition these lived in sub-modules. Re-exporting from __init__ + late import in handler preserves the patch target without changing tests.",
+ "phase": "08"
+ },
+ {
+ "decision": "Wave 2 agents committed directly to main (not worktree branches) due to permission lockdown in worktrees",
+ "rationale": "Spawned agents with isolation=worktree were denied write access inside their worktree paths. The commits still landed on main in a non-isolated way. Recovery was done inline by orchestrator.",
+ "phase": "08"
+ }
+ ],
+ "uncommitted_files": [],
+ "next_action": "Execute plan 08-08: /gsd:execute-phase 8 (after user verifies npm packages on npmjs.com)",
+ "context_notes": "Wave 2 (plans 08-04 through 08-07) is fully done. Full backend suite 405/406 passed (1 pre-existing docx env skip). Wave 3 is plan 08-08 only, which is autonomous:false and needs npm package supply-chain verification before execution."
+}
diff --git a/.planning/phases/08-stack-upgrade-backend-decomposition/.continue-here.md b/.planning/phases/08-stack-upgrade-backend-decomposition/.continue-here.md
new file mode 100644
index 0000000..a64dd28
--- /dev/null
+++ b/.planning/phases/08-stack-upgrade-backend-decomposition/.continue-here.md
@@ -0,0 +1,82 @@
+---
+context: phase
+phase: 08-stack-upgrade-backend-decomposition
+plan: 8
+total_tasks: 8
+status: in_progress
+last_updated: 2026-06-12T08:33:19.724Z
+---
+
+# BLOCKING CONSTRAINTS — Read Before Anything Else
+
+> These are not suggestions. Each constraint below was discovered through failure.
+> Acknowledge each one explicitly before proceeding.
+
+- [ ] CONSTRAINT: FastAPI empty-path sub-router — `@router.get("")` on a sub-router included via `include_router(sub, prefix="")` raises `FastAPIError: Prefix and path cannot be both empty` in FastAPI 0.128+. Register the list route directly on the parent router using `router.add_api_route("", handler, methods=["GET"])` instead.
+- [ ] CONSTRAINT: Test monkeypatching after decomposition — Tests that patch `api.documents.X` break after decomposition because `X` moves to a sub-module. Fix: re-export `X` from `__init__.py` AND use a late import inside the handler so the call resolves through the package namespace at call time.
+- [ ] CONSTRAINT: Worktree permission lockdown — Spawned agents with `isolation="worktree"` were denied write access inside their worktree paths this session. If re-spawning agents, test write access first or run inline.
+
+**Do not proceed until all boxes are checked.**
+
+## Critical Anti-Patterns
+
+| Pattern | Description | Severity | Prevention Mechanism |
+|---------|-------------|----------|---------------------|
+| Empty-path sub-router | `@router.get("")` on a sub-router fails in FastAPI 0.128 when include prefix is also empty | blocking | Register root-path routes directly on the parent aggregator router, not on the sub-router |
+| Monkeypatch target drift | Test patches `api.documents.X` but `X` moved to `api.documents.upload` after decomposition | blocking | After decomposition: re-export patched names from `__init__.py`; use late import in handler |
+| Worktree write lockdown | Agents spawned with `isolation="worktree"` were denied write permission inside the worktree path | advisory | Verify write access or avoid worktrees; inline execution always has permissions |
+
+
+Phase 8, Wave 2 complete. Plans 08-01 through 08-07 all done with SUMMARY.md files. Only plan 08-08 remains (Wave 3 — dependency upgrades). Plan 08-08 is `autonomous: false` and requires user to manually verify npm packages on npmjs.com before execution. Full backend suite: 405/406 passed (1 pre-existing python-docx env skip).
+
+
+
+
+- Plan 08-01: xfail stubs + CR contract locks ✅
+- Plan 08-02: CloudConnectionOut migration + schemas.py ✅
+- Plan 08-03: CR-01/02/03 session-revocation + toastStore stub ✅
+- Plan 08-04: `backend/api/admin/` package (13 routes, monolith deleted) ✅
+- Plan 08-05: `backend/api/documents/` package (9 routes, monolith deleted) ✅
+- Plan 08-06: `backend/api/auth/` package (15 routes, CR-01/02/03 preserved, limiter re-exported) ✅
+- Plan 08-07: `frontend/src/api/` decomposed — `client.js` 20 lines, 7 domain modules + `utils.js` ✅
+
+
+
+
+- Plan 08-08 (Wave 3): Dependency upgrades
+ - Add @vueuse/core, @vueuse/integrations, sortablejs, @tailwindcss/forms, rollup-plugin-visualizer to frontend/package.json
+ - Upgrade vite to ^6.4.3
+ - Wire @tailwindcss/forms plugin in tailwind.config.js
+ - Pin all backend/requirements.txt to exact == versions
+ - Run pytest -v and npm run build to verify no regressions
+ - **REQUIRES user to verify packages on npmjs.com first** (see plan frontmatter `user_setup`)
+
+
+
+
+- `list_documents` registered directly on parent router in `documents/__init__.py` (not via `include_router`) — FastAPI 0.128 empty-path restriction
+- `extract_and_classify` and `get_storage_backend_for_document` re-exported from `api.documents.__init__` for test monkeypatching compatibility; late import used inside handlers
+- Wave 2 agents committed directly to main (permission lockdown in worktrees); recovery done inline
+
+
+
+
+- Plan 08-08 requires user npm package verification on npmjs.com before execution (see plan frontmatter `user_setup` section)
+
+
+## Required Reading (in order)
+1. `.planning/phases/08-stack-upgrade-backend-decomposition/08-08-PLAN.md` — the only remaining plan; read the `user_setup` section carefully before executing
+2. `CLAUDE.md` §"Backend: shared module map" and §"Frontend: shared module map" — non-negotiable rules
+
+## Infrastructure State
+- Docker services: not required for tests (SQLite used in tests)
+- Full backend suite baseline: 405 passed, 1 skipped (python-docx not installed locally — pre-existing)
+- All previous SUMMARY.md files committed
+
+
+Session executed Wave 2 (plans 08-04 through 08-07) in parallel worktrees, hit permission lockdowns, recovered inline. All backend API monoliths decomposed. Frontend client.js barrel pattern in place. Wave 3 is one plan (08-08) gated on user npm supply-chain verification.
+
+
+
+Start with: Ask user to verify npm packages on npmjs.com (see 08-08-PLAN.md `user_setup`), then run `/gsd:execute-phase 8` to execute plan 08-08.
+