Files
kite/.planning/phases/03-document-migration-multi-user-isolation/03-VALIDATION.md
T
curo1305 fdc32d431d docs(03): create Phase 3 execution plan — document migration & multi-user isolation
5 plans across 5 sequential waves covering: Alembic migration 0003 (null-user
cleanup, NOT NULL constraint, quota reconciliation), presigned MinIO PUT upload
flow with atomic quota enforcement, auth guards on all document/topic endpoints,
flat-file settings retirement + per-user AI classification, and frontend quota bar
with 3-step XHR upload progress.

Verification passed across all 12 dimensions. All 8 phase requirements covered
(STORE-03/04/05/06, SEC-04, DOC-03/04/05).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 13:36:28 +02:00

67 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
phase: 3
slug: document-migration-multi-user-isolation
status: draft
nyquist_compliant: false
wave_0_complete: false
created: 2026-05-23
---
# Phase 3 — Validation Strategy
> Per-phase validation contract for feedback sampling during execution.
---
## Test Infrastructure
| Property | Value |
|----------|-------|
| **Framework** | pytest + pytest-asyncio (existing in codebase) |
| **Config file** | `backend/pytest.ini` or `backend/pyproject.toml` |
| **Quick run command** | `cd backend && pytest tests/test_documents.py tests/test_quota.py tests/test_topics.py -x -q` |
| **Full suite command** | `cd backend && pytest -v` |
| **Estimated runtime** | ~3060 seconds |
---
## Sampling Rate
- **After every task commit:** Run `cd backend && pytest tests/test_documents.py tests/test_quota.py tests/test_topics.py -x -q`
- **After every plan wave:** Run `cd backend && pytest -v`
- **Before `/gsd:verify-work`:** Full suite must be green
- **Max feedback latency:** 60 seconds
---
## Per-Task Verification Map
| Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status |
|---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------|
| Migration null-user cleanup | 01 | 1 | D-02 | SEC-04 | Null-user docs deleted before NOT NULL constraint | integration | `pytest tests/test_alembic.py::test_migration_0003 -x` | ❌ W0 | ⬜ pending |
| Quota reconciliation | 01 | 1 | D-03 | STORE-03 | used_bytes matches SUM(size_bytes) post-migration | integration | `pytest tests/test_alembic.py::test_migration_0003 -x` | ❌ W0 | ⬜ pending |
| Atomic quota enforce | 02 | 2 | STORE-03 | STORE-03 | No double-spend on concurrent uploads | unit+integration | `pytest tests/test_quota.py -x` | ❌ W0 | ⬜ pending |
| Concurrent quota race | 02 | 2 | STORE-03 (SC2) | STORE-03 | Two concurrent uploads at limit → exactly one 413 | integration | `pytest tests/test_quota.py::test_concurrent_quota_race -x` | ❌ W0 | ⬜ pending |
| Quota exceeded response | 02 | 2 | STORE-05 | STORE-05 | 413 with {used_bytes, limit_bytes, rejected_bytes} | unit | `pytest tests/test_quota.py::test_quota_exceeded_response -x` | ❌ W0 | ⬜ pending |
| Atomic quota decrement | 02 | 2 | STORE-06 | STORE-06 | Delete decrements quota atomically | unit | `pytest tests/test_quota.py::test_delete_decrements_quota -x` | ❌ W0 | ⬜ pending |
| Upload-url endpoint | 02 | 2 | D-05 | SEC-04 | Creates pending Document row + returns presigned URL | unit | `pytest tests/test_documents.py::test_upload_url_endpoint -x` | ❌ W0 | ⬜ pending |
| Confirm endpoint | 02 | 2 | D-05 | STORE-03 | stat_object size used, status=uploaded set | unit | `pytest tests/test_documents.py::test_confirm_endpoint -x` | ❌ W0 | ⬜ pending |
| Quota bar endpoint | 02 | 2 | STORE-04 | — | GET /api/me/quota returns {used_bytes, limit_bytes} | unit | `pytest tests/test_documents.py::test_get_quota -x` | ❌ W0 | ⬜ pending |
| Cross-user access | 03 | 3 | SEC-04 | SEC-04 | Cross-user document access returns 404 | unit | `pytest tests/test_documents.py::test_cross_user_access_404 -x` | ❌ W0 | ⬜ pending |
| Admin 403 on documents | 03 | 3 | SEC-04 (SC4) | SEC-04 | Admin JWT on /api/documents/* returns 403 | unit | `pytest tests/test_documents.py::test_admin_cannot_access_documents -x` | ❌ W0 | ⬜ pending |
| Topic namespace isolation | 03 | 3 | DOC-04 | — | Topic list = system topics + own topics only | unit | `pytest tests/test_topics.py::test_topic_namespace -x` | ❌ W0 | ⬜ pending |
| Per-user AI provider | 04 | 4 | DOC-03/DOC-05 | — | Classifier uses user's assigned provider not global | unit | `pytest tests/test_classifier.py::test_per_user_provider -x` | ❌ W0 | ⬜ pending |
| Celery task provider lookup | 04 | 4 | DOC-05 | — | Celery task resolves provider from document owner's DB | unit | `pytest tests/test_classifier.py::test_celery_task_uses_user_provider -x` | ❌ W0 | ⬜ pending |
| Settings endpoint removed | 04 | 4 | D-12 | — | /api/settings returns 404 | unit | `pytest tests/test_settings.py::test_settings_endpoint_removed -x` | ❌ W0 | ⬜ pending |
*Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky*
---
## Wave 0 Requirements
- [ ] `backend/tests/test_quota.py` — stubs for STORE-03, STORE-05, STORE-06, concurrent race
- [ ] `backend/tests/test_alembic.py` — stub for migration 0003 test
- [ ] `backend/tests/test_classifier.py` — stubs for DOC-03, DOC-05 per-user provider
- [ ] `backend/tests/conftest.py``auth_user` fixture (authenticated user with quota row), `admin_user` fixture, MinIO mock fixtures for `presigned_put_object` and `stat_object`