---
phase: "06.2"
plan: "01"
type: execute
wave: 0
depends_on: []
files_modified:
  - backend/tests/test_shares.py
  - backend/tests/test_documents.py
  - backend/tests/test_audit.py
autonomous: true
requirements:
  - SHARE-03
  - SHARE-05
  - ADMIN-06
must_haves:
  truths:
    - "pytest exits 0 after adding 11 xfail stubs — no new failures"
    - "Each stub is reachable by name so Wave 1 and 2 plans can promote them individually"
    - "Stubs use strict=False so they report as xfail, not xpass, while implementation is absent"
  artifacts:
    - path: "backend/tests/test_shares.py"
      provides: "xfail stubs for test_share_create_with_permission, test_share_patch_permission, test_share_patch_idor"
      contains: "pytest.xfail"
    - path: "backend/tests/test_documents.py"
      provides: "xfail stubs for test_delete_cloud_document_propagates, test_delete_cloud_document_failure, test_delete_cloud_remove_only"
      contains: "pytest.xfail"
    - path: "backend/tests/test_audit.py"
      provides: "xfail stubs for 5 audit gap tests"
      contains: "pytest.xfail"
  key_links:
    - from: "backend/tests/test_shares.py"
      to: "Wave 1 Plan 06.2-02"
      via: "test function names (must match exactly)"
      pattern: "test_share_create_with_permission|test_share_patch_permission|test_share_patch_idor"
    - from: "backend/tests/test_documents.py"
      to: "Wave 1 Plan 06.2-03"
      via: "test function names (must match exactly)"
      pattern: "test_delete_cloud_document_propagates|test_delete_cloud_document_failure|test_delete_cloud_remove_only"
    - from: "backend/tests/test_audit.py"
      to: "Wave 2 Plan 06.2-04"
      via: "test function names (must match exactly)"
      pattern: "test_audit_log_includes_user_handle|test_audit_log_filter_by_handle|test_audit_log_filter_unknown_handle|test_daily_exports_list|test_daily_export_download"
---

<objective>
Add 11 xfail test stubs — one per Wave 0 gap identified in VALIDATION.md — across three test files. These stubs establish the Nyquist contract: each gap has a named, runnable test before any implementation begins. Wave 1 and Wave 2 plans promote individual stubs to real tests.

Purpose: Nyquist compliance — no task in Waves 1 or 2 can complete without a matching automated test. Stubs guarantee the test function names exist before any executor tries to promote them.

Output: 11 new test functions (3 in test_shares.py, 3 in test_documents.py, 5 in test_audit.py), all marked xfail(strict=False).
</objective>

<execution_context>
@/Users/nik/Documents/Progamming/document_scanner/.planning/phases/06.2-close-v1-sharing-cloud-delete-csv-export-gaps/06.2-VALIDATION.md
</execution_context>

<context>
@/Users/nik/Documents/Progamming/document_scanner/.planning/ROADMAP.md
@/Users/nik/Documents/Progamming/document_scanner/.planning/phases/06.2-close-v1-sharing-cloud-delete-csv-export-gaps/06.2-CONTEXT.md
</context>

<tasks>

<task type="auto">
  <name>Task 1: Add xfail stubs to test_shares.py (SHARE-03)</name>
  <files>backend/tests/test_shares.py</files>
  <read_first>
    - backend/tests/test_shares.py — read the full file to understand the existing async_client/auth_user/second_auth_user/db_session fixture pattern and function naming conventions before appending
    - .planning/phases/06.2-close-v1-sharing-cloud-delete-csv-export-gaps/06.2-VALIDATION.md — Wave 0 requirements section, exact test names
  </read_first>
  <action>
Append three new async test functions to the end of backend/tests/test_shares.py. Each uses the `pytest.xfail("not implemented yet")` call immediately as its first statement (no imports, no fixtures consumed). Use `@pytest.mark.xfail(strict=False, reason="Phase 6.2 — not implemented yet")` decorator OR inline `pytest.xfail(...)` at function start — inline is preferred to match the existing xfail pattern in test_documents.py (which uses the inline call, not the decorator).

The three function signatures to add are:

1. `async def test_share_create_with_permission(async_client, auth_user, second_auth_user, db_session):`
   - Docstring: "POST /api/shares respects permission field from request body (SHARE-03, D-08, D-10)"
   - Body: `pytest.xfail("Phase 6.2 — not implemented yet")`

2. `async def test_share_patch_permission(async_client, auth_user, second_auth_user, db_session):`
   - Docstring: "PATCH /api/shares/{id} changes permission to edit (SHARE-03, D-09)"
   - Body: `pytest.xfail("Phase 6.2 — not implemented yet")`

3. `async def test_share_patch_idor(async_client, auth_user, second_auth_user, db_session):`
   - Docstring: "PATCH /api/shares/{id} by non-owner returns 404 — IDOR protection (SHARE-03, D-09, T-IDOR)"
   - Body: `pytest.xfail("Phase 6.2 — not implemented yet")`

Do NOT add any imports — `pytest` is already imported at the top of the file. Do NOT implement any logic beyond the xfail call.
  </action>
  <verify>
    <automated>cd /Users/nik/Documents/Progamming/document_scanner/backend && pytest tests/test_shares.py::test_share_create_with_permission tests/test_shares.py::test_share_patch_permission tests/test_shares.py::test_share_patch_idor -v 2>&1 | grep -E "xfail|XFAIL|passed|failed" | head -20</automated>
  </verify>
  <done>All three new tests collected and reported as XFAIL (not ERROR, not FAILED); `pytest tests/test_shares.py -x -q` exits 0</done>
</task>

<task type="auto">
  <name>Task 2: Add xfail stubs to test_documents.py (cloud-delete)</name>
  <files>backend/tests/test_documents.py</files>
  <read_first>
    - backend/tests/test_documents.py — read the full file to confirm import structure, existing xfail pattern (inline pytest.xfail call), and where to append new functions
    - .planning/phases/06.2-close-v1-sharing-cloud-delete-csv-export-gaps/06.2-VALIDATION.md — Wave 0 requirements section
  </read_first>
  <action>
Append three new async test functions to the end of backend/tests/test_documents.py. Use inline `pytest.xfail("Phase 6.2 — not implemented yet")` as the first statement — matching the existing pattern in the file (which uses `@pytest.mark.xfail(strict=False, ...)` decorator on legacy tests at the top, but newer additions in this file use the inline call pattern from VALIDATION.md guidance).

The three function signatures to add are:

1. `async def test_delete_cloud_document_propagates(async_client, auth_user, db_session):`
   - Docstring: "DELETE /api/documents/{id} for a cloud doc calls cloud backend delete_object (D-01)"
   - Body: `pytest.xfail("Phase 6.2 — not implemented yet")`

2. `async def test_delete_cloud_document_failure(async_client, auth_user, db_session):`
   - Docstring: "DELETE /api/documents/{id} returns cloud_delete_failed=True when provider raises (D-03)"
   - Body: `pytest.xfail("Phase 6.2 — not implemented yet")`

3. `async def test_delete_cloud_remove_only(async_client, auth_user, db_session):`
   - Docstring: "DELETE /api/documents/{id}?remove_only=true skips cloud delete, removes DB row only (D-02)"
   - Body: `pytest.xfail("Phase 6.2 — not implemented yet")`

All three stubs must have `pytestmark = pytest.mark.asyncio` coverage — confirm this is already at the top of the file or add it if missing. Do not implement any logic beyond xfail.
  </action>
  <verify>
    <automated>cd /Users/nik/Documents/Progamming/document_scanner/backend && pytest tests/test_documents.py::test_delete_cloud_document_propagates tests/test_documents.py::test_delete_cloud_document_failure tests/test_documents.py::test_delete_cloud_remove_only -v 2>&1 | grep -E "xfail|XFAIL|passed|failed" | head -20</automated>
  </verify>
  <done>All three new tests collected and reported as XFAIL; `pytest tests/test_documents.py -x -q` exits 0</done>
</task>

<task type="auto">
  <name>Task 3: Add xfail stubs to test_audit.py (ADMIN-06 gaps)</name>
  <files>backend/tests/test_audit.py</files>
  <read_first>
    - backend/tests/test_audit.py — read the full file to see existing helpers (_seed_audit), fixture usage (async_client, admin_user, db_session), and where to append
    - .planning/phases/06.2-close-v1-sharing-cloud-delete-csv-export-gaps/06.2-VALIDATION.md — Wave 0 requirements section
  </read_first>
  <action>
Append five new async test functions to the end of backend/tests/test_audit.py. Use inline `pytest.xfail("Phase 6.2 — not implemented yet")` as the first statement in each body.

The five function signatures to add are:

1. `async def test_audit_log_includes_user_handle(async_client, admin_user, db_session):`
   - Docstring: "Audit log items include user_handle and actor_handle strings (D-11)"
   - Body: `pytest.xfail("Phase 6.2 — not implemented yet")`

2. `async def test_audit_log_filter_by_handle(async_client, admin_user, db_session):`
   - Docstring: "GET /api/admin/audit-log?user_handle=X filters to matching entries (D-12)"
   - Body: `pytest.xfail("Phase 6.2 — not implemented yet")`

3. `async def test_audit_log_filter_unknown_handle(async_client, admin_user, db_session):`
   - Docstring: "GET /api/admin/audit-log?user_handle=unknown returns empty items list, not 422 (D-12)"
   - Body: `pytest.xfail("Phase 6.2 — not implemented yet")`

4. `async def test_daily_exports_list(async_client, admin_user):`
   - Docstring: "GET /api/admin/audit-log/daily-exports returns {items: [...]} (D-15)"
   - Body: `pytest.xfail("Phase 6.2 — not implemented yet")`

5. `async def test_daily_export_download(async_client, admin_user):`
   - Docstring: "GET /api/admin/audit-log/daily-exports/{date} returns CSV bytes with Content-Disposition (D-16)"
   - Body: `pytest.xfail("Phase 6.2 — not implemented yet")`

Do not add any new imports beyond what is already at the top of the file. Do not implement any logic.
  </action>
  <verify>
    <automated>cd /Users/nik/Documents/Progamming/document_scanner/backend && pytest tests/test_audit.py::test_audit_log_includes_user_handle tests/test_audit.py::test_audit_log_filter_by_handle tests/test_audit.py::test_audit_log_filter_unknown_handle tests/test_audit.py::test_daily_exports_list tests/test_audit.py::test_daily_export_download -v 2>&1 | grep -E "xfail|XFAIL|passed|failed" | head -20</automated>
  </verify>
  <done>All five new tests collected and reported as XFAIL; `pytest tests/test_audit.py -x -q` exits 0; total xfail count in test_audit.py increases by 5</done>
</task>

</tasks>

<threat_model>
## Trust Boundaries

| Boundary | Description |
|----------|-------------|
| test runner → test files | xfail stubs must not execute any production code paths |

## STRIDE Threat Register

| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-06.2-01-01 | Tampering | xfail stubs accidentally implementing logic | accept | Stubs contain only `pytest.xfail(...)` — no imports, no API calls, no fixtures consumed beyond signature |
</threat_model>

<verification>
After all three tasks complete:

```
cd /Users/nik/Documents/Progamming/document_scanner/backend && pytest tests/test_shares.py tests/test_audit.py tests/test_documents.py -x -q
```

Expected: exits 0, all 11 new stubs reported as xfail. Pre-existing 310 passing tests must remain passing. Pre-existing `test_extract_docx` failure is allowed.
</verification>

<success_criteria>
- 11 new xfail stubs collected across the three test files
- `pytest tests/test_shares.py tests/test_audit.py tests/test_documents.py -x -q` exits 0
- Every stub matches the exact function name from VALIDATION.md Wave 0 Requirements
- No existing passing tests are broken
</success_criteria>

<output>
Create `.planning/phases/06.2-close-v1-sharing-cloud-delete-csv-export-gaps/06.2-01-SUMMARY.md` when done.
</output>
