feat: Phase 4+5 — admin storage UI, backend proxy, CLAUDE.md enforcement

- backend/app/routers/storage_config.py: 5 admin-only endpoints proxying
  storage-service config + migration API (GET/PATCH/POST/DELETE)
- backend/app/main.py: register storage_config router
- frontend/src/api/client.ts: StorageStatus, MigrationStatus,
  StorageBackendConfig interfaces + 5 API functions
- frontend/src/pages/StorageAdminPage.tsx: full admin UI — backend health
  dot, driver selector (local/S3/WebDAV), conditional credential fields,
  Test & Migrate button, live 2s-poll migration progress bar, Cancel
- frontend/src/App.tsx: /admin/storage route (AdminRoute guard)
- CLAUDE.md: storage enforcement rule, updated Docker tables (6 services,
  3 volumes), §20 in merge checklist
- backend/CLAUDE.md, frontend/CLAUDE.md, doc-service/CLAUDE.md,
  ai-service/CLAUDE.md: updated to reflect storage-service integration
- tests/ALL_TESTS.md + tests/storage-service_tests.md: §20 (20 tests)
- backend/STATUS.md, frontend/STATUS.md: updated with new endpoints/routes
- changelog/2026-04-20_storage-service.md: full change log

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
curo1305
2026-04-20 16:13:05 +02:00
parent 4c35d7a2a4
commit cfec3bb906
15 changed files with 746 additions and 22 deletions
+22 -9
View File
@@ -6,17 +6,19 @@ This file provides permanent, authoritative guidance to Claude Code for every se
- `frontend/CLAUDE.md` — routes, components, API client patterns, XSS prevention
- `features/ai-service/CLAUDE.md` — /chat, /health, /queue endpoints; queue service
- `features/doc-service/CLAUDE.md` — document/category/share endpoints; DB models; PDF limits; file watcher
- `features/storage-service/CLAUDE.md` — storage API, pluggable backend drivers (local/S3/WebDAV), migration
---
## Merge checklist
Before merging any feature branch into `main`, every test relevant to the changed area in `tests/ALL_TESTS.md` (and the relevant service-specific file) must be marked passing. The test suite covers all 19 feature areas across four service files:
Before merging any feature branch into `main`, every test relevant to the changed area in `tests/ALL_TESTS.md` (and the relevant service-specific file) must be marked passing. The test suite covers all 20 feature areas across five service files:
- `tests/backend_tests.md` — §19, §18
- `tests/frontend_tests.md` — §19
- `tests/doc-service_tests.md` — §1016
- `tests/ai-service_tests.md` — §17
- `tests/storage-service_tests.md` — §20
Do not merge without it.
@@ -35,7 +37,7 @@ Do not merge without it.
- New Docker service, volume, network, or env var → update **Docker Infrastructure** in this file
- Stack version changed → update **Stack** in this file
- New feature or endpoint added → add test rows to **both** `tests/ALL_TESTS.md` (in the relevant section) **and** the matching service-specific file (`tests/backend_tests.md`, `tests/frontend_tests.md`, `tests/doc-service_tests.md`, or `tests/ai-service_tests.md`). Use the same test number and format as existing rows.
- New feature or endpoint added → add test rows to **both** `tests/ALL_TESTS.md` (in the relevant section) **and** the matching service-specific file (`tests/backend_tests.md`, `tests/frontend_tests.md`, `tests/doc-service_tests.md`, `tests/ai-service_tests.md`, or `tests/storage-service_tests.md`). Use the same test number and format as existing rows.
This check is mandatory — treat it the same as updating STATUS.md.
@@ -143,7 +145,17 @@ These standards are **non-negotiable**. Every change must comply. Implementation
- `backend-net`: all containers except frontend; not reachable from host in prod.
- `frontend-net`: only frontend; single host port (80 prod / 5173 dev).
- DB, backend, doc-service, ai-service have **no** host port bindings in prod.
- DB, backend, doc-service, ai-service, storage-service have **no** host port bindings in prod.
### Storage rule (non-negotiable)
**No service may write to a filesystem path for persistent data.** All file/blob storage must go through the storage-service HTTP API (`PUT/GET/DELETE /objects/{bucket}/{key}`). Config JSON files must be stored in the `config` bucket. Uploaded files must be stored in the `documents` bucket. Violation is a security and architecture defect.
The only two persistent storage mechanisms in the project are:
1. **PostgreSQL** — structured/relational data
2. **storage-service** — all file/blob/config data (local filesystem by default; switchable to S3-compatible or WebDAV)
New services and features must follow this pattern. See `features/storage-service/CLAUDE.md` for the API reference.
### Pre-commit security hook
@@ -179,9 +191,10 @@ All other per-service defaults are in the relevant sub-CLAUDE.md file.
| Service | Image base | Internal port | User | Volumes | Network |
|---------|-----------|---------------|------|---------|---------|
| `db` | postgres:16-alpine | 5432 | 70:70 | `postgres_data` | backend-net |
| `backend` | python:3.12-slim | 8000 | 1001:1001 | `app_config` | backend-net |
| `ai-service` | python:3.12-slim | 8010 | 1001:1001 | `app_config` | backend-net |
| `doc-service` | python:3.12-slim | 8001 | 1001:1001 | `doc_data`, `watch_data`, `app_config` | backend-net |
| `backend` | python:3.12-slim | 8000 | 1001:1001 | | backend-net |
| `ai-service` | python:3.12-slim | 8010 | 1001:1001 | | backend-net |
| `doc-service` | python:3.12-slim | 8001 | 1001:1001 | `watch_data` | backend-net |
| `storage-service` | python:3.12-slim | 8020 | 1001:1001 | `storage_data` | backend-net |
| `frontend` | nginx-unprivileged:alpine | 8080 | 1001:1001 | — | backend-net, frontend-net |
### Volumes
@@ -189,15 +202,14 @@ All other per-service defaults are in the relevant sub-CLAUDE.md file.
| Volume | Mount path | Contains |
|--------|-----------|---------|
| `postgres_data` | `/var/lib/postgresql/data` | PostgreSQL data |
| `doc_data` | `/data/documents` | Uploaded PDF files |
| `storage_data` | `/data/storage` | All file/blob storage: PDFs (`documents/`) and config JSONs (`config/`) |
| `watch_data` | `/data/watch` | Watch directory (bind-mount NAS/Nextcloud via docker-compose.override.yml) |
| `app_config` | `/config` | Per-service runtime config JSON files |
### Networks
| Network | Host-accessible | Members |
|---------|----------------|---------|
| `backend-net` | No (no host ports in prod) | db, backend, ai-service, doc-service, frontend |
| `backend-net` | No (no host ports in prod) | db, backend, ai-service, doc-service, storage-service, frontend |
| `frontend-net` | Yes (port 80 → frontend:8080) | frontend |
### Environment variables (required in `backend/.env`)
@@ -213,6 +225,7 @@ Injected by docker-compose (not in `.env`):
```
DOC_SERVICE_URL=http://doc-service:8001
AI_SERVICE_URL=http://ai-service:8010
STORAGE_SERVICE_URL=http://storage-service:8020
```
---