SQLAlchemy async join (Share + User for handle lookup)
IntegrityError → HTTP 409 (duplicate share)
IDOR protection via owner assertion → 404 (not 403)
created
modified
backend/api/shares.py
backend/main.py
GET /received defined before DELETE /{share_id} to prevent FastAPI path parameter conflict
DELETE wrong-owner returns 404 not 403 (T-04-04-02 — prevents share ID enumeration)
write_audit_log uses session.flush within caller transaction (D-14 pattern)
No quota table touched in shares.py — recipient quota isolation (T-04-04-04)
duration_seconds
completed_date
tasks_total
tasks_completed
files_created
files_modified
145
2026-05-25
1
1
1
1
Phase 04 Plan 04: Sharing API Summary
One-liner
JWT-authenticated document sharing API with IDOR-safe revoke (404 on wrong-owner), handle-based recipient lookup, and metadata-only "received" virtual folder.
What was built
Created backend/api/shares.py implementing four endpoints:
POST /api/shares — grant share by recipient handle; 400 self-share, 404 bad UUID/unknown doc/unknown user, 409 duplicate (UniqueConstraint → IntegrityError)
GET /api/shares?document_id= — list shares owned by current user for a document, with recipient handle via JOIN
GET /api/shares/received — virtual "Shared with me" folder; returns metadata only (id, filename, content_type, size_bytes, created_at, owner_handle) — never extracted_text
DELETE /api/shares/{share_id} — revoke with IDOR protection: share.owner_id != current_user.id → 404 "Share not found"
Registered in backend/main.py as shares_router under the Phase 4 routers section.
The pre-existing failure (test_extract_docx — ModuleNotFoundError: No module named 'docx') is completely unrelated to this plan (missing python-docx package in the local environment). It was already failing before this plan.
Security Invariants Verified
Threat
Mitigation
Verified
T-04-04-02: Share IDOR on DELETE
share.owner_id != current_user.id → 404
grep line 246
T-04-04-03: extracted_text leak
Not included in received response
grep: absent from return dict
T-04-04-04: Quota modification
No quotas table touched in shares.py
grep: no quotas reference
T-04-04-05: Duplicate share DoS
IntegrityError → 409 on UniqueConstraint
line 103-106
T-04-04-06: Doc existence leak
Ownership assertion → 404 (not 403)
line 99-100
Acceptance Criteria
backend/api/shares.py exists with all four endpoint functions
GET /api/shares/received defined before DELETE /{share_id} (line 187 vs 228)
test_share_revoke_wrong_owner_404 is xfail (not FAILED)
Full suite has zero FAILED from this plan's changes
Deviations from Plan
None — plan executed exactly as written. Route ordering, IDOR pattern, audit log calls, and quota isolation all implemented per specification.
Known Stubs
None — all four endpoints are fully implemented. Test stubs in test_shares.py are intentional xfail stubs that will be implemented in plan 04-05 (per the test file docstring).
Threat Flags
None — all trust boundaries and STRIDE threats from the plan's threat model are mitigated in the implementation.