diff --git a/.planning/phases/06.2-close-v1-sharing-cloud-delete-csv-export-gaps/06.2-VALIDATION.md b/.planning/phases/06.2-close-v1-sharing-cloud-delete-csv-export-gaps/06.2-VALIDATION.md index aa6e602..91614c3 100644 --- a/.planning/phases/06.2-close-v1-sharing-cloud-delete-csv-export-gaps/06.2-VALIDATION.md +++ b/.planning/phases/06.2-close-v1-sharing-cloud-delete-csv-export-gaps/06.2-VALIDATION.md @@ -1,10 +1,11 @@ --- phase: 6.2 slug: close-v1-sharing-cloud-delete-csv-export-gaps -status: draft -nyquist_compliant: false -wave_0_complete: false +status: complete +nyquist_compliant: true +wave_0_complete: true created: 2026-05-31 +audited: 2026-05-31 --- # Phase 6.2 — Validation Strategy @@ -38,18 +39,18 @@ created: 2026-05-31 | Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status | |---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------| -| SHARE-05-fix | 01 | 1 | SHARE-05 | — | `is_shared` drives badge (not `share_count`) | unit | `pytest tests/test_shares.py::test_share_indicator_in_owner_list -x` | ✅ | ⬜ pending | -| SHARE-03-post | 01 | 1 | SHARE-03 | — | POST /api/shares respects `permission` field | integration | `pytest tests/test_shares.py::test_share_create_with_permission -x` | ❌ W0 | ⬜ pending | -| SHARE-03-patch | 01 | 1 | SHARE-03 | T-IDOR | PATCH /api/shares/{id} changes permission | integration | `pytest tests/test_shares.py::test_share_patch_permission -x` | ❌ W0 | ⬜ pending | -| SHARE-03-idor | 01 | 1 | SHARE-03 | T-IDOR | PATCH wrong owner → 404 (not 403) | integration | `pytest tests/test_shares.py::test_share_patch_idor -x` | ❌ W0 | ⬜ pending | -| CLOUD-del-route | 02 | 1 | CLOUD-del | T-quota | delete_document routes to cloud backend for non-minio | integration | `pytest tests/test_documents.py::test_delete_cloud_document_propagates -x` | ❌ W0 | ⬜ pending | -| CLOUD-del-fail | 02 | 1 | CLOUD-del | T-cloud | Cloud delete failure returns structured JSON error | integration | `pytest tests/test_documents.py::test_delete_cloud_document_failure -x` | ❌ W0 | ⬜ pending | -| CLOUD-del-rm | 02 | 1 | CLOUD-del | T-quota | remove_only=true skips cloud, removes DB record only | integration | `pytest tests/test_documents.py::test_delete_cloud_remove_only -x` | ❌ W0 | ⬜ pending | -| AUDIT-handle | 03 | 2 | ADMIN-06 | — | Audit log response includes user_handle and actor_handle | integration | `pytest tests/test_audit.py::test_audit_log_includes_user_handle -x` | ❌ W0 | ⬜ pending | -| AUDIT-filter | 03 | 2 | ADMIN-06 | — | user_handle filter resolves to correct entries | integration | `pytest tests/test_audit.py::test_audit_log_filter_by_handle -x` | ❌ W0 | ⬜ pending | -| AUDIT-filter-empty | 03 | 2 | ADMIN-06 | — | unknown handle filter returns empty (not error) | integration | `pytest tests/test_audit.py::test_audit_log_filter_unknown_handle -x` | ❌ W0 | ⬜ pending | -| DAILY-list | 03 | 2 | ADMIN-06 | — | Daily exports list endpoint returns sorted keys | integration | `pytest tests/test_audit.py::test_daily_exports_list -x` | ❌ W0 | ⬜ pending | -| DAILY-dl | 03 | 2 | ADMIN-06 | T-path | Daily export download returns CSV bytes; date validated against regex | integration | `pytest tests/test_audit.py::test_daily_export_download -x` | ❌ W0 | ⬜ pending | +| SHARE-05-fix | 01 | 1 | SHARE-05 | — | `is_shared` drives badge (not `share_count`) | unit | `pytest tests/test_shares.py::test_share_indicator_in_owner_list -x` | ✅ | ✅ green | +| SHARE-03-post | 01 | 1 | SHARE-03 | — | POST /api/shares respects `permission` field | integration | `pytest tests/test_shares.py::test_share_create_with_permission -x` | ✅ | ✅ green | +| SHARE-03-patch | 01 | 1 | SHARE-03 | T-IDOR | PATCH /api/shares/{id} changes permission | integration | `pytest tests/test_shares.py::test_share_patch_permission -x` | ✅ | ✅ green | +| SHARE-03-idor | 01 | 1 | SHARE-03 | T-IDOR | PATCH wrong owner → 404 (not 403) | integration | `pytest tests/test_shares.py::test_share_patch_idor -x` | ✅ | ✅ green | +| CLOUD-del-route | 02 | 1 | CLOUD-del | T-quota | delete_document routes to cloud backend for non-minio | integration | `pytest tests/test_documents.py::test_delete_cloud_document_propagates -x` | ✅ | ✅ green | +| CLOUD-del-fail | 02 | 1 | CLOUD-del | T-cloud | Cloud delete failure returns structured JSON error | integration | `pytest tests/test_documents.py::test_delete_cloud_document_failure -x` | ✅ | ✅ green | +| CLOUD-del-rm | 02 | 1 | CLOUD-del | T-quota | remove_only=true skips cloud, removes DB record only | integration | `pytest tests/test_documents.py::test_delete_cloud_remove_only -x` | ✅ | ✅ green | +| AUDIT-handle | 03 | 2 | ADMIN-06 | — | Audit log response includes user_handle and actor_handle | integration | `pytest tests/test_audit.py::test_audit_log_includes_user_handle -x` | ✅ | ✅ green | +| AUDIT-filter | 03 | 2 | ADMIN-06 | — | user_handle filter resolves to correct entries | integration | `pytest tests/test_audit.py::test_audit_log_filter_by_handle -x` | ✅ | ✅ green | +| AUDIT-filter-empty | 03 | 2 | ADMIN-06 | — | unknown handle filter returns empty (not error) | integration | `pytest tests/test_audit.py::test_audit_log_filter_unknown_handle -x` | ✅ | ✅ green | +| DAILY-list | 03 | 2 | ADMIN-06 | — | Daily exports list endpoint returns sorted keys | integration | `pytest tests/test_audit.py::test_daily_exports_list -x` | ✅ | ✅ green | +| DAILY-dl | 03 | 2 | ADMIN-06 | T-path | Daily export download returns CSV bytes; date validated against regex | integration | `pytest tests/test_audit.py::test_daily_export_download -x` | ✅ | ✅ green | *Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky* @@ -57,17 +58,17 @@ created: 2026-05-31 ## Wave 0 Requirements -- [ ] `tests/test_shares.py::test_share_create_with_permission` — stubs for SHARE-03 POST permission field -- [ ] `tests/test_shares.py::test_share_patch_permission` — stubs for SHARE-03 PATCH endpoint -- [ ] `tests/test_shares.py::test_share_patch_idor` — stubs for IDOR invariant on PATCH -- [ ] `tests/test_documents.py::test_delete_cloud_document_propagates` — stubs for cloud delete routing -- [ ] `tests/test_documents.py::test_delete_cloud_document_failure` — stubs for D-03 structured error -- [ ] `tests/test_documents.py::test_delete_cloud_remove_only` — stubs for D-02 remove_only path -- [ ] `tests/test_audit.py::test_audit_log_includes_user_handle` — stubs for D-11 handle enrichment -- [ ] `tests/test_audit.py::test_audit_log_filter_by_handle` — stubs for D-12 handle filter -- [ ] `tests/test_audit.py::test_audit_log_filter_unknown_handle` — stubs for D-12 empty result -- [ ] `tests/test_audit.py::test_daily_exports_list` — stubs for D-15 listing endpoint -- [ ] `tests/test_audit.py::test_daily_export_download` — stubs for D-16 streaming endpoint +- [x] `tests/test_shares.py::test_share_create_with_permission` — stubs for SHARE-03 POST permission field +- [x] `tests/test_shares.py::test_share_patch_permission` — stubs for SHARE-03 PATCH endpoint +- [x] `tests/test_shares.py::test_share_patch_idor` — stubs for IDOR invariant on PATCH +- [x] `tests/test_documents.py::test_delete_cloud_document_propagates` — stubs for cloud delete routing +- [x] `tests/test_documents.py::test_delete_cloud_document_failure` — stubs for D-03 structured error +- [x] `tests/test_documents.py::test_delete_cloud_remove_only` — stubs for D-02 remove_only path +- [x] `tests/test_audit.py::test_audit_log_includes_user_handle` — stubs for D-11 handle enrichment +- [x] `tests/test_audit.py::test_audit_log_filter_by_handle` — stubs for D-12 handle filter +- [x] `tests/test_audit.py::test_audit_log_filter_unknown_handle` — stubs for D-12 empty result +- [x] `tests/test_audit.py::test_daily_exports_list` — stubs for D-15 listing endpoint +- [x] `tests/test_audit.py::test_daily_export_download` — stubs for D-16 streaming endpoint --- @@ -84,11 +85,22 @@ created: 2026-05-31 ## Validation Sign-Off -- [ ] All tasks have `` verify or Wave 0 dependencies -- [ ] Sampling continuity: no 3 consecutive tasks without automated verify -- [ ] Wave 0 covers all MISSING references -- [ ] No watch-mode flags -- [ ] Feedback latency < 30s -- [ ] `nyquist_compliant: true` set in frontmatter +- [x] All tasks have `` verify or Wave 0 dependencies +- [x] Sampling continuity: no 3 consecutive tasks without automated verify +- [x] Wave 0 covers all MISSING references +- [x] No watch-mode flags +- [x] Feedback latency < 30s (suite: ~3.4s for 50 tests) +- [x] `nyquist_compliant: true` set in frontmatter -**Approval:** pending +**Approval:** 2026-05-31 — 50 passed, 4 xfailed, 0 failed + +--- + +## Validation Audit 2026-05-31 + +| Metric | Count | +|--------|-------| +| Gaps found | 11 | +| Resolved | 11 | +| Escalated | 0 | +| Suite result | 50 passed, 4 xfailed |