89f8d5a654
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
184 lines
7.5 KiB
Markdown
184 lines
7.5 KiB
Markdown
# Technology Stack
|
|
|
|
**Analysis Date:** 2026-06-02
|
|
|
|
## Languages
|
|
|
|
**Primary:**
|
|
- Python 3.12 — backend API, services, Celery tasks, storage backends
|
|
- JavaScript (ES Modules, ES2022+) — Vue 3 frontend SPA
|
|
|
|
**Secondary:**
|
|
- SQL — PostgreSQL schema via Alembic migrations (`backend/migrations/`)
|
|
- HTML/CSS — Vue SFC templates, Tailwind utility classes
|
|
|
|
## Runtime
|
|
|
|
**Backend:**
|
|
- CPython 3.12 (pinned: `FROM python:3.12-slim` in `backend/Dockerfile`)
|
|
- ASGI server: Uvicorn `>=0.29` with `[standard]` extras
|
|
- Entry point: `backend/main.py` — `uvicorn main:app`
|
|
|
|
**Frontend:**
|
|
- Node.js 20 (pinned: `FROM node:20-alpine` in `frontend/Dockerfile`)
|
|
- Dev server: Vite 5 on port 5173, proxies `/api` → `http://backend:8000`
|
|
- Entry point: `frontend/index.html` → `frontend/src/main.js`
|
|
|
|
**Package Manager:**
|
|
- Backend: `pip` — `backend/requirements.txt`; no lockfile (floating `>=` ranges used throughout — see CONCERNS.md)
|
|
- Frontend: `npm` — lockfile: `frontend/package-lock.json`
|
|
|
|
## Frameworks
|
|
|
|
### Backend Core
|
|
|
|
| Package | Version | Purpose |
|
|
|---|---|---|
|
|
| `fastapi` | `>=0.111` | Async REST API framework — `backend/main.py` |
|
|
| `uvicorn[standard]` | `>=0.29` | ASGI server |
|
|
| `pydantic` | `>=2.0` with `[email]` | Request/response validation |
|
|
| `pydantic-settings` | `>=2.2` | Environment-based config — `backend/config.py` |
|
|
| `python-multipart` | `>=0.0.27` | Multipart file upload parsing |
|
|
|
|
### ORM / Database
|
|
|
|
| Package | Version | Purpose |
|
|
|---|---|---|
|
|
| `sqlalchemy[asyncio]` | `>=2.0.49` | Async ORM — `backend/db/session.py`, `backend/db/models.py` |
|
|
| `psycopg[binary]` | `>=3.3.4` | psycopg v3 async PostgreSQL driver |
|
|
| `alembic` | `>=1.18.4` | Schema migrations — `backend/migrations/` |
|
|
| `aiosqlite` | `>=0.20.0` | SQLite async driver (test isolation only) |
|
|
|
|
### Background Tasks
|
|
|
|
| Package | Version | Purpose |
|
|
|---|---|---|
|
|
| `celery[redis]` | `>=5.5.0` | Async task queue — `backend/celery_app.py` |
|
|
| `redis` | `>=4.6.0` | Redis async client; Celery broker + result backend + JTI token store |
|
|
|
|
### Auth / Security
|
|
|
|
| Package | Version | Purpose |
|
|
|---|---|---|
|
|
| `PyJWT` | `>=2.8.0` | JWT access token creation and verification — `backend/services/auth.py` |
|
|
| `pwdlib[argon2]` | `>=0.2.1` | Argon2id password hashing |
|
|
| `pyotp` | `>=2.9.0` | TOTP provisioning and verification (2FA) |
|
|
| `cryptography` | `>=41.0.0` | HKDF per-user key derivation; Fernet encryption for cloud credentials |
|
|
| `slowapi` | `>=0.1.9` | Rate limiting middleware on auth endpoints |
|
|
| `httpx` | `>=0.27` | Async HTTP client (HIBP k-anonymity checks, OneDrive Graph API) |
|
|
|
|
### Document Processing
|
|
|
|
| Package | Version | Purpose |
|
|
|---|---|---|
|
|
| `PyMuPDF` | `>=1.26.7` | PDF text extraction — `backend/services/extractor.py` |
|
|
| `python-docx` | `>=1.1` | DOCX text extraction — `backend/services/extractor.py` |
|
|
| `pytesseract` | `>=0.3` | OCR for image files — `backend/services/extractor.py` |
|
|
| `Pillow` | `>=10.3` | Image loading for OCR pipeline |
|
|
| `aiofiles` | `>=23.2` | Async file I/O |
|
|
|
|
### AI Classification
|
|
|
|
| Package | Version | Purpose |
|
|
|---|---|---|
|
|
| `anthropic` | `>=0.26` | Anthropic Claude SDK — `backend/ai/anthropic_provider.py` |
|
|
| `openai` | `>=1.30` | OpenAI SDK; also used as shim for Ollama and LM Studio — `backend/ai/openai_provider.py` |
|
|
|
|
### Cloud Storage SDKs
|
|
|
|
| Package | Version | Purpose |
|
|
|---|---|---|
|
|
| `minio` | `>=7.2.20` | MinIO/S3 object storage SDK — `backend/storage/minio_backend.py` |
|
|
| `google-auth-oauthlib` | `>=1.3.1` | Google OAuth2 flow — `backend/storage/google_drive_backend.py` |
|
|
| `google-api-python-client` | `>=2.196.0` | Google Drive v3 API — `backend/storage/google_drive_backend.py` |
|
|
| `msal` | `>=1.36.0` | Microsoft Auth Library for OneDrive — `backend/storage/onedrive_backend.py` |
|
|
| `webdavclient3` | `>=3.14.7` | Generic WebDAV + Nextcloud — `backend/storage/webdav_backend.py` |
|
|
| `cachetools` | `>=5.3.0` | Cloud connection caching — `backend/services/cloud_cache.py` |
|
|
|
|
### Frontend
|
|
|
|
| Package | Version | Purpose |
|
|
|---|---|---|
|
|
| `vue` | `^3.4.0` | UI framework (Options API) — `frontend/src/` |
|
|
| `vue-router` | `^4.3.0` | Client-side routing — `frontend/src/router/` |
|
|
| `pinia` | `^2.1.0` | State management (JWT access token stored in memory only) — `frontend/src/stores/` |
|
|
| `qrcode` | `^1.5.4` | TOTP QR code generation for 2FA enrollment UI |
|
|
| `tailwindcss` | `^3.4.0` | Utility-first CSS — `frontend/tailwind.config.js` |
|
|
|
|
### Frontend Dev / Build
|
|
|
|
| Tool | Version | Purpose |
|
|
|---|---|---|
|
|
| `vite` | `^5.2.0` | Dev server and bundler — `frontend/vite.config.js` |
|
|
| `@vitejs/plugin-vue` | `^5.0.0` | Vue SFC compilation |
|
|
| `postcss` | `^8.4.0` | CSS processing — `frontend/postcss.config.js` |
|
|
| `autoprefixer` | `^10.4.0` | CSS vendor prefixing |
|
|
|
|
### Testing
|
|
|
|
| Tool | Version | Purpose |
|
|
|---|---|---|
|
|
| `pytest` | `>=8.2` | Backend test runner — `backend/pytest.ini` |
|
|
| `pytest-asyncio` | `>=1.3.0` | Async test support (`asyncio_mode = auto`) |
|
|
| `vitest` | `^4.1.7` | Frontend test runner — `frontend/vitest.config.js` |
|
|
| `@vue/test-utils` | `^2.4.10` | Vue component test utilities |
|
|
| `happy-dom` | `^20.9.0` | DOM environment for Vitest |
|
|
|
|
## Infrastructure
|
|
|
|
### Docker Compose Services (`docker-compose.yml`)
|
|
|
|
| Service | Image | Port(s) | Notes |
|
|
|---|---|---|---|
|
|
| `postgres` | `postgres:17-alpine` | internal | Persistent `postgres_data` volume |
|
|
| `minio` | `minio/minio:latest` | `9000`, `9001` | S3-compatible object store; persistent `minio_data` volume |
|
|
| `redis` | `redis:7-alpine` | internal | Password-protected; Celery broker + JTI revocation store |
|
|
| `backend` | Built from `./backend` | `8000` | Hot-reload via volume mount; depends on postgres, minio, redis |
|
|
| `celery-worker` | Built from `./backend` | — | Processes `documents` queue |
|
|
| `celery-beat` | Built from `./backend` | — | Periodic task scheduler |
|
|
| `frontend` | Built from `./frontend` | `5173` | Vite dev server; proxies `/api` → `backend:8000` |
|
|
|
|
### Database Role Separation
|
|
|
|
- `docuvault_app` — DML only (SELECT/INSERT/UPDATE/DELETE); used by FastAPI app
|
|
- `docuvault_migrate` — DDL; used by Alembic migrations only
|
|
- Init script: `docker/postgres/initdb.d/01-init-users.sql`
|
|
|
|
### System Dependencies (backend Docker image)
|
|
|
|
Installed via `apt-get` in `backend/Dockerfile`:
|
|
- `tesseract-ocr` — OCR binary for `pytesseract`
|
|
- `libgl1`, `libglib2.0-0` — shared libraries required by PyMuPDF
|
|
|
|
## Configuration
|
|
|
|
**Environment variables** are the single source of truth, read by `pydantic-settings` in `backend/config.py`.
|
|
|
|
Required for core operation:
|
|
- `DATABASE_URL` — psycopg v3 async DSN for app user
|
|
- `DATABASE_MIGRATE_URL` — psycopg v3 DSN for migrate user
|
|
- `MINIO_ENDPOINT`, `MINIO_ACCESS_KEY`, `MINIO_SECRET_KEY`, `MINIO_BUCKET`
|
|
- `REDIS_URL` — used by both FastAPI (JTI store) and Celery
|
|
- `SECRET_KEY` — JWT signing secret
|
|
- `CLOUD_CREDS_KEY` — 32-byte master key for HKDF cloud credential encryption
|
|
|
|
Optional:
|
|
- `SMTP_HOST/PORT/USER/PASSWORD/FROM` — transactional email
|
|
- `GOOGLE_CLIENT_ID/SECRET`, `ONEDRIVE_CLIENT_ID/SECRET` — OAuth cloud storage
|
|
- `ADMIN_EMAIL`, `ADMIN_PASSWORD` — bootstrap admin account
|
|
- `SYSTEM_PROMPT`, `DEFAULT_AI_PROVIDER`, `DEFAULT_AI_MODEL` — AI defaults
|
|
- `CORS_ORIGINS`, `FRONTEND_URL`, `BACKEND_URL`
|
|
|
|
## Platform Requirements
|
|
|
|
**Development:**
|
|
- Docker + Docker Compose (preferred), or
|
|
- Python 3.12, Node.js 20 plus running PostgreSQL 17, MinIO, Redis instances locally
|
|
|
|
**Production:**
|
|
- Containerised via Docker Compose; no cloud-native manifests or reverse-proxy config detected in repo
|
|
|
|
---
|
|
|
|
*Stack analysis: 2026-06-02*
|