---
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.
