13 KiB
DocuVault
What This Is
DocuVault is a self-hosted, multi-user SaaS document management platform. Users upload documents (PDF, DOCX, images, text), which are automatically text-extracted and classified by AI into user-defined topics. Each user has isolated, quota-enforced storage, can organize documents in folders, connect external cloud storage backends (OneDrive, Google Drive, Nextcloud, etc.), and share documents with other users by handle. A privacy-first admin model gives administrators platform control without any access to user document content.
Core Value
Every user's documents — and the credentials they use to store them — are inaccessible to everyone except that user, while the platform scales horizontally and supports pluggable storage backends.
Last Milestone: v0.2 — UI Overhaul and Optimization (shipped 2026-06-17)
Delivered: Polished, production-quality frontend with mobile-responsive layout, full UX interaction layer, decomposed backend/frontend codebase, and standalone admin panel.
See .planning/MILESTONES.md and .planning/milestones/v0.2-ROADMAP.md for full archive.
Current Milestone: v0.3 Reimagining Cloud Storage integration
Goal: Make connected cloud storage behave like first-class DocuVault storage: users can browse and manage cloud files as if they were local, analyze all or selected cloud documents, and search them by keywords, sentences, or ideas while minimizing DocuVault-owned local storage.
Target features:
- Native-feeling cloud file navigation and actions: open, preview, upload, move, delete, rename, and organize files from connected providers.
- Provider setup, health, reconnect, credential lifecycle, and error handling that make cloud connections feel reliable and understandable.
- Analyze all cloud documents or a selected subset without requiring manual local upload.
- Classify and index cloud documents so they become smart-searchable like locally uploaded documents.
- Cache and offload cloud file bytes on demand, similar to a desktop sync client, preserving local-like navigation while minimizing local storage use.
- Rework storage architecture where needed: provider capabilities, background jobs, sync/import/index state, conflict handling, and test coverage.
Requirements
Validated (v0.1 — shipped 2026-06-06)
- ✓ Document upload and text extraction (PDF, DOCX, image, plain text)
- ✓ AI-based topic classification via configurable provider
- ✓ Multiple AI provider support (Anthropic, OpenAI, GenericOpenAI-compat, Ollama, LMStudio)
- ✓ Topic CRUD management (per-user namespace)
- ✓ Docker containerization (Compose) with PostgreSQL + MinIO
- ✓ User registration with email/password (Argon2id, strength enforcement, HaveIBeenPwned check)
- ✓ JWT session management (ES256 asymmetric, 15 min access token, 16h/30d refresh, token fingerprinting, JTI revocation)
- ✓ TOTP 2FA with backup codes; session revocation on privilege change
- ✓ Admin: create, deactivate, reset password, assign AI provider per user
- ✓ Admin cannot access user documents or cloud credentials
- ✓ Per-user isolated storage with 100 MB free-tier quota (atomic enforcement)
- ✓ Folder creation, rename, delete, move documents between folders
- ✓ Document sharing by handle (view/edit permission, revocable, no recipient quota charge)
- ✓ "Shared with me" virtual folder
- ✓ Cloud storage backends: OneDrive, Google Drive, Nextcloud, WebDAV (HKDF-encrypted credentials)
- ✓ PDF in-browser preview (proxied, no presigned URL exposure)
- ✓ Full-text search and sorting on document list
- ✓ Audit log (metadata only): logins, uploads, deletes, shares, quota changes
- ✓ Admin audit log viewer with date/user/action filters and CSV export
- ✓ Structured JSON logging (structlog + correlation IDs)
- ✓ Container hardening (non-root user, read-only filesystem, dropped capabilities)
- ✓ AI provider settings in
system_settingsDB table (HKDF-encrypted API keys) - ✓ Celery retry backoff (30 s / 90 s / 270 s) on classification failure
- ✓ Backend stateless — all state in PostgreSQL and MinIO
Validated (v0.2 — shipped 2026-06-17)
- ✓ Backend monolith decomposition (api/admin/, api/documents/, api/auth/ sub-packages) — v0.2
- ✓ Frontend API client decomposition (7 domain modules + barrel re-export) — v0.2
- ✓ Admin panel standalone route subtree (/admin/*) with AdminLayout, AdminSidebar, 5 deep-linkable views — v0.2
- ✓ requiresAdmin guard via to.matched.some() — v0.2
- ✓ Admin overview aggregate endpoint (user count, storage, doc status, recent audit) — v0.2
- ✓ EmptyState.vue in all zero-content contexts — v0.2
- ✓ Skeleton loaders for all async-populated tables/lists/sidebars — v0.2
- ✓ Keyboard shortcuts: / (search), U (upload), N (new folder), Escape (close/clear) — v0.2
- ✓ OS drag-drop overlay (full-screen, file-type discriminated) — v0.2
- ✓ Toast notification system (auto-dismiss, stacking, non-blocking) — v0.2
- ✓ BreadcrumbBar.vue shared across all views — v0.2
- ✓ Drag-to-move document to folder with Teleport-based dropdowns — v0.2
- ✓ AppIcon.vue centralizing all SVG path data (66 instances) — v0.2
- ✓ Mobile-responsive layout: hamburger sidebar drawer (below lg), touch targets ≥36px — v0.2
- ✓ @tailwindcss/forms cross-browser form baseline — v0.2
- ✓ Consistent Tailwind-only spacing/typography/focus-visible/hover states — v0.2
- ✓ Bundle −81 kB (−30.6%) via lazy-loaded admin routes — v0.2
- ✓ Dead code deleted (FolderRow.vue, AccountView.vue, stale test files) — v0.2
- ✓ WHY-only comment policy enforced (CODE-09) — v0.2
Active (v0.3 — Reimagining Cloud Storage integration)
- Cloud files can be browsed and managed with the same core actions as local files: open, preview, upload, move, delete, and rename.
- Cloud provider setup and maintenance includes health status, reconnect flows, credential lifecycle handling, and useful error states.
- Users can analyze all cloud documents or a selected subset from connected storage.
- Analyzed cloud documents are classified and indexed for smart search by keywords, sentences, and semantic ideas.
- DocuVault minimizes local storage by caching cloud file bytes only when needed and offloading them when safe.
- Storage architecture models provider capabilities, sync/index state, background jobs, and conflict/error handling explicitly.
Out of Scope
- Subscription billing / payment processing — future milestone (quota table designed for it)
- SSO (Microsoft, Google, Apple) — future; auth layer designed for extension
- Keycloak / SAML / OAuth enterprise federation — future
- Group admin roles — future; groups table seeded in schema
- Document annotation or in-app editing — not planned
- Mobile native app — not planned (responsive web only in v0.2)
- Public document sharing (unauthenticated link) — not planned for v0.x
Context
- Current state: v0.3 in progress — Phase 12 (cloud-resource-foundation) complete 2026-06-19. Provider-neutral CloudResourceAdapter contract, durable CloudItem/CloudFolderState ORM, connection-ID browse API, stale-while-revalidate Celery refresh task, and capability-aware StorageBrowser frontend all shipped. v0.2.0 released. Phase 13 (cloud mutations: create/rename/move/delete) is 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: Standalone /admin/* route subtree with AdminLayout as the route component, AdminSidebar with 5 nav links, and 5 dedicated view components. AdminView.vue and legacy tab components deleted. Admin users redirect to /admin on login; non-admin blocked by to.matched.some() guard.
- Privacy constraint: Admin role is a platform operator, not a content viewer. Cloud credentials encrypted with per-user HKDF key; API keys encrypted with separate HKDF domain. Neither is ever in an API response.
Constraints
- Tech stack: FastAPI (Python) + Vue 3 — keep existing stack, no framework switch
- Database: PostgreSQL (Alembic-managed schema, 5 migrations completed)
- Object storage: MinIO (S3-compatible, Docker-native)
- Auth: Argon2id passwords, ES256 JWT, TOTP 2FA (pyotp), HKDF key derivation
- Deployment: Docker Compose (primary deployment target, must remain so)
- No rewrites: Refactor, don't rewrite. Preserve all existing functionality and test coverage.
Key Decisions
| Decision | Rationale | Outcome |
|---|---|---|
| PostgreSQL + MinIO over flat files | Multi-user quotas + horizontal scaling require shared, consistent state | Shipped in v0.1 Phase 1 |
| Cloud storage adapter pattern | Mirrors AI provider pattern — consistent, extensible | Shipped in v0.1 Phase 5 |
| Privacy-first admin model | SaaS legal/trust requirement | Admin queries exclude document content; cloud creds encrypted with user-scoped key |
| Admin controls AI config, not users | Prevents cost overruns and model misuse | AI provider assignment stored per-user in DB, configurable by admin only |
| 100 MB free tier | Baseline for future subscription tiers | Quota table has limit_bytes column admin can override |
| TOTP 2FA before SSO | State-of-the-art security without third-party dependency | Via pyotp (RFC 6238), shipped v0.1 Phase 2 |
| ES256 over HS256 for JWT | Leaked public key cannot forge tokens; asymmetric signing | Shipped v0.1 Phase 7.3 |
| Token fingerprinting (fgp claim) | Limits stolen access token replay to original device context | HMAC of User-Agent + Accept-Language, shipped v0.1 Phase 7.4 |
| 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) |
| Admin login redirect (D-08) | Role check fires before router.push — admin → /admin, regular user → /; D-09 guard as belt-and-suspenders | Shipped Phase 9 |
| Tailwind safelist with regex patterns | Dynamic color classes (sky=OneDrive, amber=admin audit badges) are tree-shaken without explicit safelist | Regex patterns cover all provider and event-type color families in tailwind.config.js |
| GET /api/admin/overview as dedicated endpoint | Aggregated stats (user count, storage, doc status, recent audit) served in one request to avoid N+1 on admin load | ✓ Shipped Phase 9 (09-01) |
| AppIcon.vue SVG registry | 66 duplicate inline SVG blocks eliminated; single source of truth for all icon paths | ✓ Shipped Phase 10 (CODE-05) |
| Teleport + getBoundingClientRect for dropdowns | Viewport-edge clipping eliminated without complex position logic; prerequisite for virtual scrolling | ✓ Shipped Phase 10 (UX-13) |
| Admin routes lazy-loaded | All 5 admin views excluded from initial bundle; −81 kB (−30.6%) improvement | ✓ Shipped Phase 11 (PERF-03) |
| Vite 8 upgrade for npm audit | Closed high-severity esbuild CVE present in Vite 5/6; npm audit now clean | ✓ Shipped Phase 11 (11-07) |
| Virtual-local cloud storage model | Users already organize documents in their cloud provider; DocuVault should add local-like actions, analysis, and smart search without forcing full import | — Pending v0.3 |
Evolution
This document evolves at phase transitions and milestone boundaries.
Last updated: 2026-06-19
After each phase transition (via /gsd-transition):
- Requirements invalidated? → Move to Out of Scope with reason
- Requirements validated? → Move to Validated with phase reference
- New requirements emerged? → Add to Active
- Decisions to log? → Add to Key Decisions
- "What This Is" still accurate? → Update if drifted
After each milestone (via /gsd:complete-milestone):
- Full review of all sections
- Core Value check — still the right priority?
- Audit Out of Scope — reasons still valid?
- Update Context with current state
Last updated: 2026-06-17 — after starting v0.3 milestone