# Phase 8: Stack Upgrade & Backend Decomposition — Context

**Gathered:** 2026-06-07
**Status:** Ready for planning

<domain>
## Phase Boundary

Phase 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.

</domain>

<decisions>
## Implementation Decisions

### 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 a `skip_token_hash` param; the function is wired into `change_password`, `enable_totp`, and `disable_totp` with a `sessions_revoked` field in each response shape; audit log entries written for each revocation.
- **D-03:** Frontend toast implementation: create an empty `useToastStore` Pinia store stub during Phase 7.1. Phase 7.1 components (`SettingsAccountTab.vue`, `TotpEnrollment.vue`) call `toastStore.show(...)` when `sessions_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 in `main.py` propagates. 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 in `services/auth.py` for 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 within `api/documents/` is researcher/planner's choice.

### Shared Pydantic Schemas (CODE-08)

- **D-09:** Pydantic models shared within a single package → `shared.py` inside that package.
- **D-10:** Pydantic models referenced by 2+ packages (e.g., a `UserOut` used by both `api/admin/` and `api/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 appropriate `services/` module during the split. This enforces the CLAUDE.md rule that the service layer raises `ValueError`, and API files never define validators. Researcher identifies which validators qualify.

### Frontend API Client Decomposition (CODE-04)

- **D-12:** `client.js` becomes HTTP transport layer + re-export barrel only. `request()` and `noRefreshPaths` stay in `client.js`. Zero changes to any of the 35+ consumer files.
- **D-13:** `fetchWithRetry()` (consolidating the 3 blob-download 401-retry duplicates) lives in a new `frontend/src/api/utils.js`. `client.js` re-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.js` and 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 in `tailwind.config.js` or `vite.config.js` vs 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.txt` must 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 reads `api/documents.py` and chooses names that reflect the actual endpoint groupings)
- Exact file names for `api/auth/` sub-modules (researcher mirrors `services/auth.py` logical groupings)
- Re-classify endpoint placement within `api/documents/`
- Which validators in router files qualify for migration to `services/`
- Domain grouping of each `client.js` function (researcher maps all 35+ consumer import sites)
- Which PERF-01 packages need config wiring vs install-only

</decisions>

<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 in `api/` vs `services/`
- `.planning/codebase/CONVENTIONS.md` — import organization, naming patterns, service-vs-API error handling separation; the rule that validators live in `services/`
- `CLAUDE.md` §"Backend: shared module map" — `deps/utils.py`, `storage/exceptions.py`, `ai/utils.py`, `services/auth.py` shared 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 stores
- `CLAUDE.md` §"Frontend: shared module map" — `utils/formatters.js`, `TreeItem.vue`, `StorageBrowser.vue` rules
- `CLAUDE.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 boundaries
- `frontend/src/api/client.js` (635L) — the frontend client being decomposed; researcher must read all import sites
- `backend/services/auth.py` — structure mirrors how `api/auth/` sub-modules should be named

### Established Patterns
- `backend/api/admin.py` already contains AI config endpoints added in Phase 7 — `api/admin/ai.py` absorbs this
- `backend/main.py` router registration pattern: `app.include_router(router, prefix="/api/...")` — each new package `__init__.py` must aggregate sub-routers and export a single `router` object
- `asyncio.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.py` intentionally avoids importing `config`; 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__.py` files
- `frontend/src/api/client.js` — must re-export every function from domain sub-modules; no consumer file changes
- `backend/deps/auth.py` — `get_current_user`, `get_current_admin`, `get_regular_user` imported by all router sub-modules; dependency imports must work from new sub-package paths
- `frontend/src/stores/` — all 5 stores import from `api/client.js`; barrel re-export must preserve all named exports

</code_context>

<specifics>
## 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 `useToastStore` stub created in Phase 7.1 is a deliberate forward-reference contract: Phase 10's toast implementation must honor the same `show()` API shape
- `backend/api/schemas.py` is a NEW file — it doesn't exist yet; researcher should identify exact cross-package model candidates before planning

</specifics>

<deferred>
## Deferred Ideas

- 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

</deferred>

---

*Phase: 8-Stack-Upgrade-Backend-Decomposition*
*Context gathered: 2026-06-07*
