--- phase: "6.1" slug: close-v1-audit-gaps status: validated nyquist_compliant: true wave_0_complete: true created: 2026-05-30 audited: 2026-05-30 gaps_found: 3 gaps_resolved: 2 gaps_manual: 1 --- # Phase 6.1 — Validation Strategy > Nyquist validation contract for Phase 6.1: Close v1.0 Audit Gaps (SHARE-01..05, ADMIN-06, STORE-06). --- ## Test Infrastructure | Property | Value | |----------|-------| | **Framework** | pytest 9.0.3, pytest-asyncio 1.4.0 | | **Config file** | `backend/pytest.ini` — `asyncio_mode = auto`, `testpaths = tests` | | **Quick run command** | `docker compose exec backend python -m pytest tests/test_shares.py tests/test_audit.py -v` | | **Full suite command** | `docker compose exec backend python -m pytest -v` | | **Estimated runtime** | ~2 seconds (shares+audit), ~45 seconds (full suite) | --- ## Sampling Rate - **After every task commit:** Run `docker compose exec backend python -m pytest tests/test_shares.py tests/test_audit.py -v` - **After every plan wave:** Run `docker compose exec backend python -m pytest -v` - **Before `/gsd:verify-work`:** Full suite must be green - **Max feedback latency:** ~2 seconds (targeted), ~45 seconds (full) --- ## Per-Task Verification Map | Task ID | Plan | Wave | Requirement | Threat Ref | Secure Behavior | Test Type | Automated Command | File Exists | Status | |---------|------|------|-------------|------------|-----------------|-----------|-------------------|-------------|--------| | 06.1-01-T1 | 01 | 1 | — | — | `second_auth_user` fixture distinct from `auth_user` (no handle collision) | integration | `pytest tests/test_shares.py -v` | ✅ | ✅ green | | 06.1-01-T2 | 01 | 1 | SHARE-01 | T-04-04-02 | POST /api/shares 201; 404 on unknown handle | integration | `pytest tests/test_shares.py::test_share_success tests/test_shares.py::test_share_handle_not_found -v` | ✅ | ✅ green | | 06.1-01-T2 | 01 | 1 | SHARE-02 | T-04-04-03, T-04-04-04 | /received has metadata only (no extracted_text); recipient quota unchanged | integration | `pytest tests/test_shares.py::test_shared_with_me tests/test_shares.py::test_share_no_quota_impact -v` | ✅ | ✅ green | | 06.1-01-T2 | 01 | 1 | SHARE-03 | — | shares default to permission="view"; POST and GET list both assert field value | integration | `pytest tests/test_shares.py::test_share_default_permission_view -v` | ✅ | ✅ green | | 06.1-01-T2 | 01 | 1 | SHARE-04 | T-04-04-02 | DELETE 204 removes share; IDOR: recipient DELETE → 404 not 403 | integration | `pytest tests/test_shares.py::test_revoke_share tests/test_shares.py::test_share_revoke_wrong_owner_404 -v` | ✅ | ✅ green | | 06.1-01-T2 | 01 | 1 | SHARE-05 | — | Owner's GET /api/documents shows is_shared=True after sharing; False before | integration | `pytest tests/test_shares.py::test_share_indicator_in_owner_list -v` | ✅ | ✅ green | | 06.1-02-T1 | 02 | 1 | ADMIN-06 | D-15 | paginated viewer shape; no filename/extracted_text/password_hash/credentials_enc in items or metadata_; admin gate 403; filter by event_type narrows results; CSV export | integration | `pytest tests/test_audit.py -v` | ✅ | ✅ green | *Status: ⬜ pending · ✅ green · ❌ red · ⚠️ flaky* --- ## Wave 0 Requirements Existing infrastructure covered all phase requirements. No Wave 0 work needed. - `backend/tests/conftest.py` — `async_client`, `auth_user`, `admin_user`, `db_session` fixtures (pre-existing) - `second_auth_user` fixture added in Plan 06.1-01 Task 1 (commit b7df971) --- ## Manual-Only Verifications | Behavior | Requirement | Why Manual | Test Instructions | |----------|-------------|------------|-------------------| | `test_delete_decrements_quota` passes as PASSED (not XFAIL) under live PostgreSQL | STORE-06 | `test_quota.py:196` has `@pytest.mark.xfail(strict=False, reason="requires PostgreSQL for atomic UUID-typed quota SQL")` — runs as xfail on SQLite. Live PostgreSQL required to confirm the atomic `GREATEST(0, used_bytes - delta)` SQL works correctly. | Run: `INTEGRATION=1 docker compose exec backend python -m pytest tests/test_quota.py::test_delete_decrements_quota -v` — expect `PASSED`, not `XFAIL` or `XPASS`. | --- ## Validation Sign-Off - [x] All tasks have automated verify commands - [x] Sampling continuity: no 3 consecutive tasks without automated verify - [x] Wave 0: no stubs — all tests implemented with real assertions - [x] No watch-mode flags - [x] Feedback latency < 5s (targeted suite) - [x] `nyquist_compliant: true` set in frontmatter **Approval:** validated 2026-05-30 --- ## Validation Audit 2026-05-30 | Metric | Count | |--------|-------| | Requirements assessed | 7 (SHARE-01..05, ADMIN-06, STORE-06) | | Gaps found | 3 (SHARE-03 partial, SHARE-05 missing, STORE-06 partial) | | Resolved (automated) | 2 (SHARE-03, SHARE-05 — new tests added) | | Escalated to manual-only | 1 (STORE-06 — requires live PostgreSQL INTEGRATION=1) | | Tests added this audit | 2 (`test_share_default_permission_view`, `test_share_indicator_in_owner_list`) | | Total phase tests after audit | 14 (9 shares + 5 audit) | ### Note on VERIFICATION.md stale state The existing `06.1-VERIFICATION.md` was generated before commit `451fff1` (which added `test_audit_log_filter_by_event_type`) and incorrectly listed "Gap 1 — audit filter behavioral tests missing" as unresolved. At audit time, `test_audit.py` contained 5 tests (not 4 as stated), and Gap 1 was already closed. The VERIFICATION.md gap count of 2 was reduced to 1 real gap (STORE-06) for this audit, plus 2 test-coverage gaps (SHARE-03, SHARE-05) that were resolved here.