diff --git a/.planning/PROJECT.md b/.planning/PROJECT.md index a4c332c..ea7209f 100644 --- a/.planning/PROJECT.md +++ b/.planning/PROJECT.md @@ -65,7 +65,7 @@ Every user's documents — and the credentials they use to store them — are in ## Context -- **Current state**: v0.1 complete (2026-06-06). All foundation features shipped and security-hardened. App is functional for local/self-hosted use but not hardened for public internet deployment. +- **Current state**: v0.2 in progress — Phase 8 complete (2026-06-12). Backend routers decomposed into focused sub-packages, frontend API client decomposed into domain modules, Vite 6 shipped, CVEs resolved. Phase 9 (Admin Panel Rearchitecture) up next. - **Tech stack**: FastAPI 0.136+ (Python 3.12), SQLAlchemy 2.0 async, Alembic, MinIO SDK; Vue 3 (Options API), Pinia, Vue Router 4, Vite, Tailwind CSS. - **Code quality**: v0.1 was built feature-first under time pressure. Both backend and frontend contain duplication, inconsistent patterns, and components that grew beyond their original scope. v0.2 addresses this systematically. - **Admin panel**: AdminView.vue currently renders admin functionality as tabs appended to the main user layout. This is architecturally wrong — the admin interface needs its own route subtree, layout component, and nav. @@ -95,6 +95,10 @@ Every user's documents — and the credentials they use to store them — are in | JTI claim + Redis revocation | Closes 15-min window where revoked session's access token stays valid | Shipped v0.1 Phase 7.2 | | Options API preserved in v0.2 refactor | Composition API migration is scope-creep for a UX milestone; refactor within Options API | Decision logged to prevent scope drift | | Admin panel as standalone route subtree | AdminView.vue as tabs-on-user-layout is an architectural mistake | v0.2 introduces /admin/* routes with own layout | +| `client.js` barrel re-export pattern | Zero consumer churn — all 35+ import sites stay unchanged; domain modules hidden behind barrel | Shipped Phase 8 (CODE-04) | +| Sub-routers carry NO prefix | Parent `include_router(sub, prefix=...)` propagates; sub-router with own prefix causes double-segment URLs | Discovered during Phase 8 backend decomposition | +| FastAPI 0.128+ empty-path restriction | `@router.get("")` on a sub-router with empty include prefix raises `FastAPIError` — register root routes on parent aggregator directly | Discovered Phase 8; affects all future sub-router patterns | +| Vite 6 upgrade | Resolved two moderate CVEs (CVE-2026-39363/39364) present in Vite 5; build time unchanged | Shipped Phase 8 (PERF-01) | ## Evolution @@ -114,4 +118,4 @@ This document evolves at phase transitions and milestone boundaries. 4. Update Context with current state --- -*Last updated: 2026-06-07 — milestone v0.2 started* +*Last updated: 2026-06-12 — after Phase 8* diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index e2a9498..afa0704 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -529,7 +529,7 @@ _Started: 2026-06-07_ ## v0.2 Phases -- [ ] **Phase 8: Stack Upgrade & Backend Decomposition** — Dependency bumps land; all three backend router monoliths split into focused sub-packages; frontend API client decomposed into domain modules; shared Pydantic schemas extracted +- [x] **Phase 8: Stack Upgrade & Backend Decomposition** — Dependency bumps land; all three backend router monoliths split into focused sub-packages; frontend API client decomposed into domain modules; shared Pydantic schemas extracted _(2026-06-12)_ - [ ] **Phase 9: Admin Panel Rearchitecture** — Admin panel moves to `/admin/*` route subtree with its own layout, sidebar, and deep-linkable child routes; Tailwind safelist configured; redundant comments purged - [ ] **Phase 10: UX & Interaction** — Empty states, loading skeletons, keyboard shortcuts, drag-and-drop upload, toast notifications, breadcrumbs, and icon centralization land across the full UI - [ ] **Phase 11: Visual Design, Responsive Layout & Cleanup** — Consistent spacing, form styling, hover/focus states, and typography applied; mobile-responsive sidebar and layouts ship; dead code deleted; bundle measured @@ -566,11 +566,11 @@ _Started: 2026-06-07_ **Wave 2** *(blocked on Wave 1)* — Backend decomposition + frontend (parallel) -- [ ] 08-04-PLAN.md — Split `api/admin.py` → `api/admin/` package: users.py, quotas.py, ai.py, shared.py, __init__.py (CODE-01) -- [ ] 08-05-PLAN.md — Split `api/documents.py` → `api/documents/` package: upload.py, crud.py, content.py, shared.py, __init__.py (CODE-02) -- [ ] 08-06-PLAN.md — Split `api/auth.py` → `api/auth/` package: tokens.py, totp.py, password.py, sessions.py, shared.py, __init__.py (CODE-03) +- [x] 08-04-PLAN.md — Split `api/admin.py` → `api/admin/` package: users.py, quotas.py, ai.py, shared.py, __init__.py (CODE-01) +- [x] 08-05-PLAN.md — Split `api/documents.py` → `api/documents/` package: upload.py, crud.py, content.py, shared.py, __init__.py (CODE-02) +- [x] 08-06-PLAN.md — Split `api/auth.py` → `api/auth/` package: tokens.py, totp.py, password.py, sessions.py, shared.py, __init__.py (CODE-03) - [x] 08-07-PLAN.md — Frontend `client.js` decomposition: utils.js + 7 domain modules + barrel rewrite (CODE-04) -- [ ] 08-08-PLAN.md — PERF-01 dependency bump + tailwind/vite config wiring + requirements.txt exact pinning (PERF-01, D-17) +- [x] 08-08-PLAN.md — PERF-01 dependency bump + tailwind/vite config wiring + requirements.txt exact pinning (PERF-01, D-17) **Cross-cutting constraints:** diff --git a/.planning/STATE.md b/.planning/STATE.md index 207f6b7..f18aa81 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,21 +3,22 @@ gsd_state_version: 1.0 milestone: v0.2 milestone_name: Phases current_phase: 9 -status: ready -last_updated: "2026-06-12T00:00:00.000Z" +status: ready_to_plan +last_updated: 2026-06-12T09:27:34.436Z last_activity: 2026-06-12 progress: total_phases: 17 completed_phases: 14 total_plans: 73 completed_plans: 73 - percent: 80 + percent: 82 +stopped_at: Phase 08 complete (8/8) — ready to discuss Phase 9 --- # Project State **Project:** DocuVault -**Status:** Phase 8 complete — ready for Phase 9 +**Status:** Ready to plan **Current Phase:** 9 **Last Updated:** 2026-06-12 @@ -60,6 +61,8 @@ Last activity: 2026-06-12 | Sub-routers carry NO prefix | Parent APIRouter prefix propagates — sub-routers with prefix cause double-segment URLs | | AdminLayout as route component, not App.vue branch | Router resolves AdminLayout as the /admin component; its router-view renders children | | to.matched.some() for requiresAdmin guard | Vue Router 4 does not inherit meta to children; direct to.meta check is a security regression | +| FastAPI 0.128+ empty-path sub-router restriction | `@router.get("")` on sub-router with empty include prefix fails; register root routes on parent aggregator | +| Vite 6 upgrade resolves 2 CVEs | CVE-2026-39363/39364 closed; npm audit now clean | ### Roadmap Evolution diff --git a/.planning/phases/08-stack-upgrade-backend-decomposition/.continue-here.md b/.planning/phases/08-stack-upgrade-backend-decomposition/.continue-here.md deleted file mode 100644 index a64dd28..0000000 --- a/.planning/phases/08-stack-upgrade-backend-decomposition/.continue-here.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -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. -