Files
zpan/migrations/0003_recycle_bin.sql
T
Jasper Van cd764c07a7 feat(server): recycle bin API for matters (#273)
* feat(server): recycle bin API for matters

Add trash, restore, permanent delete, and empty-trash operations on
MatterService. Trashing/restoring/purging a folder cascades to all
descendants. Permanent delete removes S3 objects and decrements
storages.used and org_quotas.used.

Endpoints:
- PATCH /api/objects/:id/trash       — soft delete
- PATCH /api/objects/:id/restore     — restore from trash
- DELETE /api/objects/:id            — permanent delete (only if trashed)
- POST  /api/recycle-bin/empty       — purge all trashed items

Note: empty-trash is mounted at /api/recycle-bin/empty (instead of
/api/objects/trash/empty as in the task spec) because Hono's router does
not allow mounting two sub-apps at overlapping prefixes (/api/objects
and /api/objects/trash) — doing so silently breaks routing for unrelated
paths like /api/auth/**. The functional behavior is identical.

Schema: matters gets a nullable trashed_at column (migration 0003).

Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f

* test(server): improve branch coverage for recycle bin code

Add tests covering:
- File creation with presigned upload URL
- File copy with S3 copyObject
- Permanent delete of trashed files (S3 deleteObjects verified)
- Cascade purge of folder with file children
- Trash/restore idempotency (already-trashed, not-trashed)
- 404 for missing items on trash/restore
- Empty trash with mixed folders and files
- Empty trash on empty bin (no-op)
- File download URL generation

Mock S3Service methods (presignUpload, presignDownload, copyObject)
globally in beforeEach to enable file-based route tests.

Branch coverage: 87.84% (threshold: 80%)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Bob <aibob@mails.agent-kanban.dev>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 17:55:09 -04:00

3 lines
97 B
SQL

-- Add trashed_at column for recycle bin support
ALTER TABLE `matters` ADD `trashed_at` integer;