fix(12-05): bump version to 0.2.1 and update docs for migration-gated startup
- backend/main.py, frontend/package.json: version 0.2.0 → 0.2.1 - CLAUDE.md, AGENTS.md: current state updated to reflect gap-closure - README.md: startup instructions note migrate runs automatically; update migration commands - RUNBOOK.md: startup diagram includes migrate service; migration gate explanation - SECURITY.md: Phase 12 gap-closure threat register and security gate evidence
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.0 — Phase 12 complete (2026-06-19). Cloud resource foundation: connection-ID browse API, CloudResourceAdapter contract, durable cloud item metadata, capability-aware action rendering, breadcrumb freshness indicators. Cloud and local files share one StorageBrowser implementation. Security-negative suite in test_cloud_security.py. Not cleared for public internet deployment.
|
||||
**Current state:** v0.2.1 — Phase 12 gap-closure complete (2026-06-20). Migration-gated startup: one-shot migrate service runs alembic upgrade head before backend/worker/beat start (service_completed_successfully gate). 0005→0006 upgrade regression in test_migration_0006.py. RUNBOOK migration ops section. Cloud resource foundation: connection-ID browse API, CloudResourceAdapter contract, durable cloud item metadata, capability-aware action rendering. Not cleared for public internet deployment.
|
||||
|
||||
## Stack
|
||||
|
||||
@@ -123,9 +123,9 @@ This project uses the GSD (Get Shit Done) planning workflow. Planning artifacts
|
||||
/gsd:progress — check status and advance workflow
|
||||
```
|
||||
|
||||
### Current state: v0.2.0 — Phase 12 complete (2026-06-19)
|
||||
### Current state: v0.2.1 — Phase 12 gap-closure complete (2026-06-20)
|
||||
|
||||
Phase 12 (cloud-resource-foundation): full cloud browse foundation — CloudResourceAdapter contract, connection-ID browse API (`GET /api/cloud/connections/{id}/items`), durable cloud item metadata (CloudItem ORM), connection-ID routing (`/cloud/:connectionId`), capability-aware action rendering (CapabilityButton / aria-disabled), breadcrumb freshness indicators (refreshing/fresh/stale), session-only folder memory, display-name rename for cloud connections, and a dedicated security-negative integration suite (`test_cloud_security.py`). Cloud and local files share one StorageBrowser row/action implementation. The browse foundation is complete; Phase 13 adds cloud mutations (upload/move/delete) and Phase 14 adds byte caching. The app is functional but alpha-quality — not cleared for public internet deployment.
|
||||
Phase 12 gap-closure: migration-gated Compose startup (migrate service, service_completed_successfully dependency gate on backend/worker/beat), 0005→0006 upgrade regression tests (test_migration_0006.py), RUNBOOK migration ops section. Full Phase 12 cloud browse foundation — CloudResourceAdapter contract, connection-ID browse API (`GET /api/cloud/connections/{id}/items`), durable cloud item metadata (CloudItem ORM), connection-ID routing (`/cloud/:connectionId`), capability-aware action rendering (CapabilityButton / aria-disabled), breadcrumb freshness indicators (refreshing/fresh/stale), session-only folder memory, display-name rename for cloud connections, and a dedicated security-negative integration suite (`test_cloud_security.py`). Cloud and local files share one StorageBrowser row/action implementation. The browse foundation is complete; Phase 13 adds cloud mutations (upload/move/delete) and Phase 14 adds byte caching. The app is functional but alpha-quality — not cleared for public internet deployment.
|
||||
|
||||
## Development Setup
|
||||
|
||||
|
||||
@@ -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.0 — Phase 12 complete 2026-06-19. 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.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.
|
||||
|
||||
## Stack
|
||||
|
||||
@@ -119,7 +119,7 @@ This project uses the GSD (Get Shit Done) planning workflow. Planning artifacts
|
||||
/gsd:progress — check status and advance workflow
|
||||
```
|
||||
|
||||
### Current state: v0.2.0 — Phase 12 (cloud-resource-foundation) complete (2026-06-19)
|
||||
### Current state: v0.2.1 — Phase 12 gap-closure complete (2026-06-20)
|
||||
|
||||
All phases are marked complete in `.planning/ROADMAP.md`. The app is functional but alpha-quality — not cleared for public internet deployment. The next milestone has not been started.
|
||||
|
||||
|
||||
@@ -117,16 +117,15 @@ print('JWT_PUBLIC_KEY=' + base64.b64encode(k.public_key().public_bytes(serializ
|
||||
# (everything else has usable defaults for local dev)
|
||||
nano .env
|
||||
|
||||
# 5. Start all services
|
||||
# 5. Start all services (migrations run automatically before backend starts)
|
||||
docker compose up -d --build
|
||||
|
||||
# 6. Run database migrations
|
||||
docker compose exec backend alembic upgrade head
|
||||
|
||||
# 7. Open the app
|
||||
# 6. Open the app
|
||||
open http://localhost:5173
|
||||
```
|
||||
|
||||
The `migrate` service runs `alembic upgrade head` automatically before the backend, Celery worker, and Celery beat start. No manual migration step is needed on a normal `docker compose up`.
|
||||
|
||||
The bootstrap admin account (email + password from `.env`) is created automatically on first startup if no users exist.
|
||||
|
||||
---
|
||||
@@ -222,8 +221,12 @@ npm run dev # http://localhost:5173
|
||||
### Database migrations
|
||||
|
||||
```bash
|
||||
# Apply all pending migrations
|
||||
docker compose exec backend alembic upgrade head
|
||||
# Migrations run automatically on docker compose up via the migrate service.
|
||||
# To run them manually (e.g., after a git pull without restarting):
|
||||
docker compose run --rm migrate
|
||||
|
||||
# Check current revision
|
||||
docker compose run --rm migrate alembic current
|
||||
|
||||
# Create a new migration after changing db/models.py
|
||||
docker compose exec backend alembic revision --autogenerate -m "describe change"
|
||||
|
||||
+32
@@ -385,3 +385,35 @@ None. Phase 12 adds a read-only cloud browse surface (no MinIO writes, no quota
|
||||
|---------|-----------|---------------|-----------|
|
||||
| T-12-SC | pip-audit tooling | pip-audit not installed in local Python 3.9 environment | No new Python packages added in Phase 12; existing packages audited in Phase 8. Operator should run pip-audit in CI or with Python 3.12 target environment. |
|
||||
| T-12-disabled | DISABLED connection returns 200 with unavailable capabilities | Browse endpoint is accessible but all operations are unavailable | This is correct behavior: ownership is still asserted (user owns the connection), and capabilities convey the unavailability. No cloud bytes or credentials are served. |
|
||||
|
||||
---
|
||||
|
||||
## Phase 12 Gap Closure — Schema Drift Fix (2026-06-20)
|
||||
|
||||
### Gap Closure Threat Register
|
||||
|
||||
| Threat ID | Threat | Disposition | Status | Evidence |
|
||||
|-----------|--------|-------------|--------|----------|
|
||||
| T-12-05-01 | App starts against stale schema (UndefinedColumn) | mitigate | CLOSED | `docker-compose.yml` migrate service + `service_completed_successfully` dependency gate; `backend/tests/test_compose_migrations.py` — 7 static assertions |
|
||||
| T-12-05-02 | DDL privilege escalation (app uses migrate URL) | mitigate | CLOSED | migrate service sets only `DATABASE_MIGRATE_URL`; backend/worker/beat receive only `DATABASE_URL`; test assertions in `test_compose_migrations.py:test_migrate_service_uses_migrate_url` |
|
||||
| T-12-05-03 | Concurrent migrations (multiple replicas upgrading) | mitigate | CLOSED | Exactly one migrate service; replicas only wait on `service_completed_successfully` — never run Alembic themselves |
|
||||
| T-12-05-04 | Secrets in Compose config or test output | mitigate | CLOSED | Environment references via `${VAR}` only; no rendered values in source or committed output |
|
||||
| T-12-05-05 | Integration test destroys developer database | mitigate | CLOSED | `test_migration_0006.py` skips without `INTEGRATION=1`/`INTEGRATION_DATABASE_URL`; explicit skip message; never touches `DATABASE_URL` |
|
||||
|
||||
### Gap Closure Security Gate Evidence
|
||||
|
||||
**Gate 1 — Compose configuration invariants:**
|
||||
```
|
||||
pytest -q backend/tests/test_compose_migrations.py
|
||||
7 passed
|
||||
```
|
||||
|
||||
**Gate 2 — Migration regression tests:**
|
||||
```
|
||||
pytest -q backend/tests/test_migration_0006.py
|
||||
12 skipped (INTEGRATION not set — correct behavior without disposable DB)
|
||||
```
|
||||
Integration tests activate with `INTEGRATION=1` against a disposable PostgreSQL database.
|
||||
|
||||
**Gate 3 — No new Python or frontend packages introduced.**
|
||||
**Gate 4 — No hardcoded credentials in Compose or test files.**
|
||||
|
||||
+1
-1
@@ -244,7 +244,7 @@ async def lifespan(app: FastAPI):
|
||||
|
||||
# ── Application factory ───────────────────────────────────────────────────────
|
||||
|
||||
app = FastAPI(title="Document Scanner API", version="0.2.0", lifespan=lifespan)
|
||||
app = FastAPI(title="Document Scanner API", version="0.2.1", lifespan=lifespan)
|
||||
|
||||
# Rate limiter state (slowapi)
|
||||
app.state.limiter = auth_limiter
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "document-scanner-frontend",
|
||||
"version": "0.2.0",
|
||||
"version": "0.2.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
Reference in New Issue
Block a user