Add priority queue to ai-service and STATUS.md workflow
- Introduce async priority queue service in ai-service; all /chat calls now route through it - Refactor chat router to separate execute_chat (core logic) from the HTTP handler - Add /queue endpoints (status, pause, resume, cancel) for queue management - Update ai-service config to use Pydantic v2 model_config style - Add STATUS.md files for backend, ai-service, doc-service, and frontend - Document STATUS.md workflow in CLAUDE.md - Update doc-service documents router and schemas; frontend DocumentsPage and API client Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
# Backend — Status
|
||||
|
||||
## What it is
|
||||
|
||||
Central FastAPI gateway. Handles authentication, user management, admin settings, and proxies feature-service traffic. It is the only container that has host-level port exposure (`8000`, internal) — all browser traffic arrives via the Vite/nginx frontend proxy.
|
||||
|
||||
Port: `8000` (on `backend-net`, no direct host binding in prod).
|
||||
Database: PostgreSQL 16 (`postgres_data` named volume).
|
||||
|
||||
---
|
||||
|
||||
## Current functionality
|
||||
|
||||
### Auth (`/api/auth`)
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `POST` | `/api/auth/register` | Create account; password policy enforced (uppercase, special char, no "test") |
|
||||
| `POST` | `/api/auth/login` | OAuth2 password flow; returns RS256 JWT (8-hour expiry) |
|
||||
|
||||
JWT signing uses a 4096-bit RSA key pair (`RS256`). Keys are generated by `scripts/generate_jwt_keys.py` and stored in `backend/.env` (gitignored). Token stored in `localStorage` on the client.
|
||||
|
||||
### Users (`/api/users`)
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `GET` | `/api/users/me` | Current user info |
|
||||
|
||||
### Profile (`/api/profile`)
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `GET` | `/api/profile` | Fetch profile (separate `profiles` table) |
|
||||
| `PUT` | `/api/profile` | Update profile fields |
|
||||
|
||||
### Admin (`/api/admin`)
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `GET` | `/api/admin/users` | List all users (admin only) |
|
||||
| `PATCH` | `/api/admin/users/{id}` | Update user (role, active flag) |
|
||||
|
||||
### Settings (`/api/settings`)
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| `GET` | `/api/settings/ai` | AI service config (masked — API keys redacted) |
|
||||
| `PATCH` | `/api/settings/ai` | Update AI provider / credentials |
|
||||
| `POST` | `/api/settings/ai/test` | Test AI connection (proxies a minimal /chat call) |
|
||||
| `GET` | `/api/settings/documents/limits` | Doc service upload limits |
|
||||
| `PATCH` | `/api/settings/documents/limits` | Update max PDF size |
|
||||
|
||||
Settings are persisted to JSON files on the `app_config` Docker named volume and read by the respective feature services.
|
||||
|
||||
### Feature proxies
|
||||
|
||||
All `/api/documents/*` and `/api/documents/categories/*` requests are transparently proxied to `doc-service:8001` via `httpx.AsyncClient`. The proxy:
|
||||
- Validates the JWT (`get_current_user`)
|
||||
- Injects `x-user-id` header (UUID from `users.id`)
|
||||
- Strips hop-by-hop headers + `content-length`, `accept-encoding`, `content-type`
|
||||
- Returns `Response` (not `StreamingResponse`) to avoid content-length/chunked conflicts
|
||||
|
||||
### Database models
|
||||
|
||||
| Model | Table | Notes |
|
||||
|-------|-------|-------|
|
||||
| `User` | `users` | email, hashed_password, role (`user`\|`admin`), is_active |
|
||||
| `Profile` | `profiles` | one-to-one with User; full_name, phone, etc. |
|
||||
|
||||
Alembic migrations in `backend/alembic/versions/` — version table: `alembic_version`.
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Browser (port 5173 dev / 80 prod)
|
||||
│
|
||||
└── Vite dev proxy / nginx
|
||||
│
|
||||
└── /api/* → backend:8000 (FastAPI)
|
||||
│
|
||||
┌───────────┼────────────┐
|
||||
/auth /settings /documents/*
|
||||
/users (JSON │
|
||||
/admin volume) └── proxy → doc-service:8001
|
||||
/profile
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security notes
|
||||
|
||||
- JWT stored in `localStorage` — XSS risk. Migration to `httpOnly` cookie planned.
|
||||
- No refresh token — after 8h the user must log in again.
|
||||
- Admin routes use `get_current_admin` dependency (checks `role == "admin"`).
|
||||
- All backend routes require authentication except `/api/auth/*`.
|
||||
- `backend-net` is marked `internal: true` — containers on it cannot reach the internet directly.
|
||||
|
||||
---
|
||||
|
||||
## Known limitations / not implemented
|
||||
|
||||
- **No refresh tokens** — 8h hard expiry; adding refresh requires `httpOnly` cookie + rotation
|
||||
- **No `httpOnly` cookie** — JWT in `localStorage` is XSS-exposed
|
||||
- **App permissions** — no per-user, per-app access control. Currently all authenticated users can use all apps. Planned: `user_app_permissions` table, admin UI to grant/revoke
|
||||
- **Groups / sharing** — no group model yet; blocks document sharing in doc-service
|
||||
- **Email verification** — accounts are active immediately after registration
|
||||
- **Password reset** — no flow implemented
|
||||
|
||||
---
|
||||
|
||||
## Future work
|
||||
|
||||
- [ ] Groups + permissions system: `groups`, `group_memberships`, `group_app_permissions` tables; admin CRUD; doc sharing via group membership
|
||||
- [ ] App permissions registry: `user_app_permissions (user_id, app_key)`; AppsPage filtered by grants
|
||||
- [ ] `httpOnly` cookie migration for JWT
|
||||
- [ ] Refresh token flow (paired with cookie migration)
|
||||
- [ ] Email verification on registration
|
||||
- [ ] Password reset flow
|
||||
- [ ] Rate limiting on auth endpoints
|
||||
Reference in New Issue
Block a user