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>
9.9 KiB
Phase 8: Stack Upgrade & Backend Decomposition — Context
Gathered: 2026-06-07 Status: Ready for planning
## Phase BoundaryPhase 8 delivers: (1) Phase 7.1 session-revocation work completed first as Wave 1, (2) three backend router monoliths split into focused sub-packages (api/admin/, api/documents/, api/auth/), (3) the frontend API client decomposed into domain modules behind a re-export barrel, (4) shared Pydantic schemas extracted to api/schemas.py, (5) router-defined validators migrated to services/, (6) requirements.txt pinned to exact versions, and (7) PERF-01 frontend dependencies installed. Zero URL changes, zero behavior changes — invisible to consumers and tests except for Phase 7.1's new session-revocation behavior.
Phase 7.1 — Session Revocation (Wave 1, before decomposition)
- D-01: Phase 7.1 is absorbed into Phase 8 as the first wave. It must complete (backend + tests + frontend) before the decomposition work begins.
- D-02: Phase 7.1 scope:
revoke_all_refresh_tokens()gets askip_token_hashparam; the function is wired intochange_password,enable_totp, anddisable_totpwith asessions_revokedfield in each response shape; audit log entries written for each revocation. - D-03: Frontend toast implementation: create an empty
useToastStorePinia store stub during Phase 7.1. Phase 7.1 components (SettingsAccountTab.vue,TotpEnrollment.vue) calltoastStore.show(...)whensessions_revoked > 0. Phase 10 fills in the full toast implementation — Phase 7.1 only creates the stub and wires the call sites.
Backend Router Decomposition
- D-04: Sub-routers in all three new packages MUST have NO prefix on
APIRouter(). The parent prefix registered inmain.pypropagates. Any sub-router prefix causes doubled URL segments (confirmed pitfall from v0.1). - D-05:
api/admin/split:users.py,quotas.py,ai.py— exact names already locked by ROADMAP. - D-06:
api/documents/split: 4 sub-modules matching the ROADMAP's 4 functional areas (upload flow, content proxy, document CRUD, search/listing). Exact file names are researcher/planner's choice based on reading the actual code. - D-07:
api/auth/split: 4 sub-modules (login/tokens, TOTP, password management, session management). Module names must mirror the logical groupings found inservices/auth.pyfor navigability. The JTI revocation (7.2), ES256 key handling (7.3), and fgp fingerprint validation (7.4) code goes wherever the researcher determines it fits cleanest within those groupings. - D-08: Re-classify endpoint (
POST /api/documents/{id}/classify) placement withinapi/documents/is researcher/planner's choice.
Shared Pydantic Schemas (CODE-08)
- D-09: Pydantic models shared within a single package →
shared.pyinside that package. - D-10: Pydantic models referenced by 2+ packages (e.g., a
UserOutused by bothapi/admin/andapi/auth/) →backend/api/schemas.py(new top-level schemas module). This eliminates circular imports between packages. - D-11: Any validators currently defined inline in router files (rather than in
services/) must be migrated to the appropriateservices/module during the split. This enforces the CLAUDE.md rule that the service layer raisesValueError, and API files never define validators. Researcher identifies which validators qualify.
Frontend API Client Decomposition (CODE-04)
- D-12:
client.jsbecomes HTTP transport layer + re-export barrel only.request()andnoRefreshPathsstay inclient.js. Zero changes to any of the 35+ consumer files. - D-13:
fetchWithRetry()(consolidating the 3 blob-download 401-retry duplicates) lives in a newfrontend/src/api/utils.js.client.jsre-exports it. - D-14: Domain sub-modules:
documents.js,auth.js,admin.js,folders.js,shares.js,cloud.js,topics.js. Each function lives in exactly one domain file (researcher picks the most specific domain; no duplication). Researcher maps all consumer import sites to determine grouping.
Frontend Dependencies (PERF-01)
- D-15: Vite 5→6 is a major version bump requiring research before execution. Researcher must check the Vite 6 migration guide against the existing
frontend/vite.config.jsand identify any required config changes before the bump is applied. - D-16: For the remaining PERF-01 packages (
@vueuse/core@^14,@vueuse/integrations@^14,sortablejs,@tailwindcss/forms,rollup-plugin-visualizer, dev type packages): researcher determines which packages require config wiring intailwind.config.jsorvite.config.jsvs which are install-only.
Backend Dependency Pinning
- D-17: Backend dep version bumping (FastAPI, SQLAlchemy, etc.) is out of scope for Phase 8. However,
requirements.txtmust be converted from floating>=ranges to exact==pins for reproducible builds. Pin the currently-installed versions (no version changes).
Claude's Discretion
- Exact file names for
api/documents/sub-modules (researcher readsapi/documents.pyand chooses names that reflect the actual endpoint groupings) - Exact file names for
api/auth/sub-modules (researcher mirrorsservices/auth.pylogical groupings) - Re-classify endpoint placement within
api/documents/ - Which validators in router files qualify for migration to
services/ - Domain grouping of each
client.jsfunction (researcher maps all 35+ consumer import sites) - Which PERF-01 packages need config wiring vs install-only
<canonical_refs>
Canonical References
Downstream agents MUST read these before planning or implementing.
Phase Goals and Requirements
.planning/ROADMAP.md§"Phase 8: Stack Upgrade & Backend Decomposition" — goal, implementation notes, success criteria, PITFALLS.planning/REQUIREMENTS.md§CODE-01, CODE-02, CODE-03, CODE-04, CODE-08, PERF-01 — formal requirement definitions
Phase 7.1 Scope (absorbed into this phase)
.planning/ROADMAP.md§"Phase 7.1: Security: session revocation on privilege change (CR-01..03)" — the two plan descriptions; requirements CR-01, CR-02, CR-03
Backend Architecture and Conventions
.planning/codebase/ARCHITECTURE.md— component responsibilities, layer boundaries, data flow; identifies what lives inapi/vsservices/.planning/codebase/CONVENTIONS.md— import organization, naming patterns, service-vs-API error handling separation; the rule that validators live inservices/CLAUDE.md§"Backend: shared module map" —deps/utils.py,storage/exceptions.py,ai/utils.py,services/auth.pyshared module rules (must not be violated during split)CLAUDE.md§"Key Architectural Rules" — ownership checks, atomic quota pattern, JWT memory-only rules (must be preserved through refactor)
Frontend Architecture
.planning/codebase/ARCHITECTURE.md§"Frontend Store Layer" — stores own data-fetching, views delegate to storesCLAUDE.md§"Frontend: shared module map" —utils/formatters.js,TreeItem.vue,StorageBrowser.vuerulesCLAUDE.md§"Component architecture" — View → Smart component → Presentational component layering
Stack Details
.planning/codebase/STACK.md— current package versions (for pinning to exact == in requirements.txt)
</canonical_refs>
<code_context>
Existing Code Insights
Reusable Assets
backend/api/admin.py(934L),backend/api/documents.py(852L),backend/api/auth.py(825L) — the three monoliths being decomposed; researcher must read these to determine sub-module boundariesfrontend/src/api/client.js(635L) — the frontend client being decomposed; researcher must read all import sitesbackend/services/auth.py— structure mirrors howapi/auth/sub-modules should be named
Established Patterns
backend/api/admin.pyalready contains AI config endpoints added in Phase 7 —api/admin/ai.pyabsorbs thisbackend/main.pyrouter registration pattern:app.include_router(router, prefix="/api/...")— each new package__init__.pymust aggregate sub-routers and export a singlerouterobjectasyncio.run()bridge in Celery tasks — never import from router modules; this constraint applies to the new sub-packages too- Circular import constraint:
backend/celery_app.pyintentionally avoids importingconfig; new sub-packages must not create import cycles
Integration Points
backend/main.py— only file that registers routers; must be updated to import from new package__init__.pyfilesfrontend/src/api/client.js— must re-export every function from domain sub-modules; no consumer file changesbackend/deps/auth.py—get_current_user,get_current_admin,get_regular_userimported by all router sub-modules; dependency imports must work from new sub-package pathsfrontend/src/stores/— all 5 stores import fromapi/client.js; barrel re-export must preserve all named exports
</code_context>
## Specific Ideas- Wave ordering: Phase 7.1 completion → backend decomposition (CODE-01/02/03 in parallel) + CODE-04 (independent) → requirements.txt pinning + PERF-01 deps
- The
useToastStorestub created in Phase 7.1 is a deliberate forward-reference contract: Phase 10's toast implementation must honor the sameshow()API shape backend/api/schemas.pyis a NEW file — it doesn't exist yet; researcher should identify exact cross-package model candidates before planning
- Backend package version bumps (FastAPI to 0.136+, SQLAlchemy, PyJWT, etc.) — deferred; only exact-pin the current versions
- Composition API migration (Vue components) — explicitly out of scope for all v0.2 phases per PROJECT.md decision
- Virtual scrolling, dark mode, folder reordering, multi-select batch ops — already in REQUIREMENTS.md "Future" section
Phase: 8-Stack-Upgrade-Backend-Decomposition Context gathered: 2026-06-07