cfec3bb906
- 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>
4.9 KiB
4.9 KiB
2026-04-20 — Dedicated storage-service with pluggable backends
Timestamp: 2026-04-20T00:00:00Z
Summary
Introduced a dedicated storage-service container (port 8020) as the single file/blob persistence layer for the entire stack. All services now route file and config I/O through this service's HTTP API. The service supports pluggable storage backends (local filesystem by default; S3-compatible and WebDAV built in) with a zero-data-loss migration flow. The doc_data and app_config Docker volumes were removed.
Files Added
features/storage-service/app/main.py— FastAPI app, lifespan (backend init)features/storage-service/app/core/config.py— Settings (DATA_DIR, STORAGE_BACKEND, S3_, WEBDAV_)features/storage-service/app/routers/health.py— GET /healthfeatures/storage-service/app/routers/objects.py— PUT/GET/DELETE /objects/{bucket}/{key:path}, GET /objects/{bucket}features/storage-service/app/routers/migrate.py— POST/GET/DELETE /migrate, PATCH /backend-configfeatures/storage-service/app/services/backend_manager.py— Driver factory, singleton, atomic switchfeatures/storage-service/app/services/migration.py— Async migration: copy → verify → switch → cleanupfeatures/storage-service/app/services/backends/base.py— AbstractStorageBackend ABCfeatures/storage-service/app/services/backends/local.py— LocalFSBackend (path traversal guard)features/storage-service/app/services/backends/s3.py— S3Backend (aiobotocore, endpoint_url configurable)features/storage-service/app/services/backends/webdav.py— WebDAVBackend (aiohttp + defusedxml)features/storage-service/scripts/start.sh— prod uvicorn startfeatures/storage-service/scripts/start_dev.sh— dev uvicorn --reload startfeatures/storage-service/pyproject.toml— Dependenciesfeatures/storage-service/Dockerfile— python:3.12-slim, non-root user 1001, port 8020features/storage-service/CLAUDE.md— API reference, bucket docs, driver docsfeatures/storage-service/STATUS.md— Service statusbackend/app/core/config_storage.py— Thin async helpers: read_json/write_json/delete_key/list_keysbackend/app/routers/storage_config.py— Admin proxy endpoints for storage config + migrationfeatures/doc-service/alembic/versions/0008_rename_file_path_to_storage_key.py— DB migrationfrontend/src/pages/StorageAdminPage.tsx— Admin UI: backend status, driver form, migration progresstests/storage-service_tests.md— §20 storage-service test suite
Files Modified
docker-compose.yml— Added storage-service, storage_data volume; removed doc_data, app_config; added depends_on service_healthydocker-compose.dev.yml— Added storage-service dev overridebackend/app/core/config.py— Added STORAGE_SERVICE_URLbackend/app/core/app_config.py— Full async rewrite using config_storage HTTP helpers (no filesystem)backend/app/routers/settings.py— Removed all asyncio.to_thread wrappers; direct await callsbackend/app/main.py— Register storage_config router; update register_services callbackend/app/services/service_health.py— Register storage-servicefeatures/doc-service/app/core/config.py— Added STORAGE_SERVICE_URLfeatures/doc-service/app/models/document.py— file_path → storage_keyfeatures/doc-service/app/services/storage.py— Complete rewrite: HTTP client calls to storage-servicefeatures/doc-service/app/services/config_reader.py— Complete rewrite: reads/writes via storage-service config bucketfeatures/doc-service/app/services/file_watcher.py— Uses save_upload() → storage-servicefeatures/doc-service/app/routers/documents.py— storage_key refs, pdfplumber(io.BytesIO), streaming from storage-servicefeatures/ai-service/app/core/config.py— Added STORAGE_SERVICE_URL; removed CONFIG_PATHfeatures/ai-service/app/services/config_reader.py— Complete rewrite: reads/writes via storage-service config bucketfrontend/src/api/client.ts— Added StorageStatus, MigrationStatus, StorageBackendConfig interfaces + 5 API functionsfrontend/src/App.tsx— Added /admin/storage route (AdminRoute → StorageAdminPage)tests/ALL_TESTS.md— Updated to 20 feature areas; added §20 storage-service testsCLAUDE.md— Added storage-service to Services/Volumes/Networks tables; storage enforcement rule; §20 test filebackend/CLAUDE.md— Added config_storage.py, storage_config.py to tree; added admin storage endpointsfrontend/CLAUDE.md— Added StorageAdminPage to tree; added /admin/storage routefeatures/doc-service/CLAUDE.md— Updated storage.py description; file_path → storage_key; added migration 0008features/ai-service/CLAUDE.md— Added config_reader.py descriptionbackend/STATUS.md— Added storage-config endpoints; updated settings persistence notefrontend/STATUS.md— Added /admin/storage route; added StorageAdminPage description