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
+29 -1
View File
@@ -1,11 +1,12 @@
# ALL_TESTS — Full Test Suite
Complete test suite covering all 19 feature areas. Run tests relevant to the changed area before merging any feature branch into `main`. Service-specific subsets live in separate files:
Complete test suite covering all 20 feature areas. Run tests relevant to the changed area before merging any feature branch into `main`. Service-specific subsets live in separate files:
- `tests/backend_tests.md` — §19, §18 (auth, users, admin, groups, appearance, service health, plugins, AI/doc settings, infra/security)
- `tests/frontend_tests.md` — §19 (UI & routing)
- `tests/doc-service_tests.md` — §1016 (upload/processing, list/filtering, slide-over, sharing, categories, bulk actions, watch directory)
- `tests/ai-service_tests.md` — §17 (AI queue & providers)
- `tests/storage-service_tests.md` — §20 (storage-service: objects, backend switching, migration)
Every test describes the exact UI action or API call to perform and the expected outcome.
@@ -351,3 +352,30 @@ Mark each row before opening the PR.
| 19.9 | TanStack Query cache | Navigate away from docs → back | List loads from cache instantly; background refetch runs |
| 19.10 | 30s service poll | Leave `/apps` open for 30s | `GET /api/services` fires again in network tab |
| 19.11 | Three-dots menu not clipped | Scroll document table → open three-dot actions on any row | Dropdown renders above the table's overflow-hidden container; not cut off |
---
## 20. Storage Service
| # | Test | Steps | Expected |
|---|------|-------|----------|
| 20.1 | Upload object | `PUT /objects/documents/test/file.pdf` with binary body | 204; object stored |
| 20.2 | Download object | `GET /objects/documents/test/file.pdf` after 20.1 | 200; binary content matches upload |
| 20.3 | Delete object | `DELETE /objects/documents/test/file.pdf` | 204; subsequent GET returns 404 |
| 20.4 | List bucket | `GET /objects/documents` | 200; JSON array of keys includes `test/file.pdf` |
| 20.5 | Health endpoint | `GET /health` | `{"status":"ok","backend":"local"}` |
| 20.6 | Path traversal rejected | `PUT /objects/documents/../etc/passwd` | 400 |
| 20.7 | PDF upload via UI | Upload a PDF document | File stored in storage-service under `documents/{user_id}/{doc_id}.pdf`; `doc_data` volume absent |
| 20.8 | PDF download via UI | Download a previously uploaded PDF | File streams correctly from storage-service |
| 20.9 | Document delete via UI | Delete a document | `DELETE /objects/documents/{key}` called; storage-service key gone |
| 20.10 | Config persistence | Restart all containers | `doc_service_config.json` and AI config survive restart in storage-service config bucket |
| 20.11 | Admin storage page | Navigate to `/admin/storage` as admin | Page loads; current backend shows "local — healthy" |
| 20.12 | Non-admin storage page blocked | Navigate to `/admin/storage` as non-admin | Redirected to `/login` |
| 20.13 | Start migration — local to local | Select "Local filesystem" and click "Test & Migrate" | 400 or migration completes instantly; no data loss |
| 20.14 | Migration progress poll | Start a migration | Status badge updates every ~2 s: validating → migrating → done |
| 20.15 | Cancel migration | Start migration; immediately click Cancel | Migration state becomes "cancelled"; old backend remains active |
| 20.16 | Migration conflict | Start a migration while one is running | 409 "A migration is already in progress" |
| 20.17 | Migration — switch to S3 | Configure MinIO credentials; click "Test & Migrate" | All objects copied to S3 bucket; `GET /health` reports `backend: s3`; old local files gone |
| 20.18 | No doc_data volume | `docker volume ls` after full stack up | `doc_data` volume absent |
| 20.19 | No app_config volume | `docker volume ls` after full stack up | `app_config` volume absent |
| 20.20 | Only storage_data volume | Verify `storage_data` volume exists | `docker volume ls` shows `storage_data`; all config and documents in it |