fix(12.1-01): restore asyncio import, bump version to 0.2.3, update docs
- Restore asyncio import removed when legacy list_folder was deleted (health_check still uses asyncio.to_thread); fixes test_nextcloud_connect_persists regression - Bump backend/main.py and frontend/package.json version to 0.2.3 - Update CLAUDE.md: note Phase 12.1 Plan 01 complete, add normalize_nextcloud_url to shared module map, add NextcloudBackend no-override rule - Update README.md: version 0.2.3, note canonical Nextcloud URL normalization and OneDrive nextLink origin guard - Full backend suite: 585 passed, 1 pre-existing failure (missing python-docx module)
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
DocuVault is a multi-user SaaS document management platform built on FastAPI (Python) + Vue 3. It handles document upload, text extraction (PDF/DOCX/image/text), AI-based topic classification, per-user isolated storage, folder organization, document sharing, and pluggable cloud storage backends (OneDrive, Google Drive, Nextcloud, WebDAV).
|
||||
|
||||
**Current state:** v0.2.1 — Phase 12 gap-closure complete 2026-06-20. Migration-gated Compose startup (migrate service, service_completed_successfully dependency gate), 0005→0006 upgrade regression tests, RUNBOOK migration ops section. Provider-neutral cloud resource contract (CloudResourceAdapter, CloudResource, CloudCapability), durable CloudItem/CloudFolderState metadata layer (Alembic migration 0006), connection-ID browse API with IDOR protection and stale-while-revalidate, refresh_cloud_folder Celery task, and capability-aware StorageBrowser frontend. 12 of 12 phases complete. Not cleared for public internet deployment.
|
||||
**Current state:** v0.2.3 — Phase 12.1 Plan 01 complete 2026-06-22. Cloud provider adapter contract repaired: Nextcloud now inherits canonical `WebDAVBackend.list_folder(connection_id, user_id, parent_ref=None, page_token=None) -> CloudListing`; legacy `list_folder(folder_path="") -> list[dict]` override removed. `normalize_nextcloud_url()` added to `cloud_utils.py`. OneDrive `@odata.nextLink` cross-origin guard added. Four-provider parametrized contract suite in `test_cloud_provider_contract.py`. Phase 12.1 in progress. Not cleared for public internet deployment.
|
||||
|
||||
## Stack
|
||||
|
||||
@@ -41,12 +41,14 @@ Before adding a helper, check if it belongs in an existing shared module:
|
||||
| `backend/ai/utils.py` | `strip_code_fences`, `parse_classification`, `parse_suggestions` — AI response parsing shared by all providers |
|
||||
| `backend/services/auth.py` | `validate_password_strength(password)` — raises `ValueError`; routers catch and re-raise as `HTTPException` |
|
||||
| `backend/storage/cloud_base.py` | `CloudResourceAdapter`, `CloudListing`, `CloudResource`, `CloudCapability` — Phase 12 browse contract; all 4 providers implement this |
|
||||
| `backend/storage/cloud_utils.py` | `validate_cloud_url`, `normalize_nextcloud_url`, `encrypt_credentials`, `decrypt_credentials` — Phase 12.1 adds `normalize_nextcloud_url` |
|
||||
| `backend/services/cloud_items.py` | `resolve_owned_connection`, `upsert_cloud_item`, `reconcile_cloud_listing`, `get_or_create_folder_state` — owner-scoped cloud metadata service |
|
||||
| `backend/api/cloud/schemas.py` | `CloudBrowseResponse`, `CloudItemOut`, `FolderFreshnessOut`, `ConnectionRenameRequest` — credential-free cloud response schemas |
|
||||
|
||||
**Rules:**
|
||||
- No router may define `_ip()`, `_get_ip()`, or any other local variant of `get_client_ip`. Import from `deps.utils`.
|
||||
- No router may define its own `CloudConnectionError`. Import from `storage.exceptions`.
|
||||
- `NextcloudBackend` must NOT override `list_folder` — it inherits the canonical `WebDAVBackend` implementation. Any Nextcloud-specific URL handling belongs in `normalize_nextcloud_url` in `cloud_utils.py`.
|
||||
- No AI provider may define its own `_strip_code_fences` or `_parse_*`. Import from `ai.utils`.
|
||||
- No API file may define `_validate_password_strength`. Import from `services.auth`.
|
||||
- Service layer raises `ValueError` (or domain exceptions), never `HTTPException`. Only the router layer raises `HTTPException`.
|
||||
|
||||
Reference in New Issue
Block a user