Per-space shared trash in the unified Deleted files view #97

Merged
Cordy merged 6 commits from feat/space-trash into main 2026-08-03 20:47:10 +00:00
Owner

Closes #95

Per Nikola's spec: deleting inside a shared space no longer buries the file in the deleter's personal trash — it routes to the space's own trash (/spaces/<name>/.trash/), and the existing single "Deleted files" view shows the union: personal deletions plus the trash of every space the caller's groups grant, newest first, each entry tagged with its origin and who deleted it.

Why inside the space: everything composes. Scope authorizes members (read-only included) to see it; the group key (#18) keeps encrypting it — space-file deletion becomes a same-scope rename, removing v0.3.25's re-key-to-deleter behaviour; retention, legal holds, and audit apply unchanged since paths never leave the space; admin raw-deletes inside a space trash hit the same retentionBlocked guard (test-pinned).

Authorization (decided 2026-08-03): every member sees a space's entries; restore/purge require write membership (member of the group itself, not -ro) — a read-only auditor cannot resurrect files, and their attempts get an indistinguishable not-found. Space entry IDs are namespaced s:<space>:<id>, so the existing /api/v1/trash/{id} surface addresses both kinds with no new routes.

Sweeper (#77): auto-purge now also sweeps every space trash with identical guard rails, crediting space:<name> in the audit trail.

UI: origin chip (space name + deleter) on space entries; restore/purge buttons hidden when canModify is false. Deleting whole space roots keeps the old per-user semantics; .trash entries are now filtered from all non-admin listings server-side (previously root-only).

Tests: routing + visibility matrix (write member / read-only / outsider), read-only restore/purge refusal, restore roundtrip, personal-trash unchanged, sweep of space trashes, and the retention suite adapted to the new routing.

Closes #95 Per Nikola's spec: deleting inside a shared space no longer buries the file in the deleter's personal trash — it routes to the **space's own trash** (`/spaces/<name>/.trash/`), and the existing single "Deleted files" view shows the union: personal deletions plus the trash of every space the caller's groups grant, newest first, each entry tagged with its origin and who deleted it. **Why inside the space:** everything composes. Scope authorizes members (read-only included) to see it; the group key (#18) keeps encrypting it — space-file deletion becomes a *same-scope* rename, removing v0.3.25's re-key-to-deleter behaviour; retention, legal holds, and audit apply unchanged since paths never leave the space; admin raw-deletes inside a space trash hit the same `retentionBlocked` guard (test-pinned). **Authorization (decided 2026-08-03):** every member sees a space's entries; restore/purge require **write membership** (member of the group itself, not `-ro`) — a read-only auditor cannot resurrect files, and their attempts get an indistinguishable not-found. Space entry IDs are namespaced `s:<space>:<id>`, so the existing `/api/v1/trash/{id}` surface addresses both kinds with no new routes. **Sweeper (#77):** auto-purge now also sweeps every space trash with identical guard rails, crediting `space:<name>` in the audit trail. **UI:** origin chip (space name + deleter) on space entries; restore/purge buttons hidden when `canModify` is false. Deleting whole space *roots* keeps the old per-user semantics; `.trash` entries are now filtered from all non-admin listings server-side (previously root-only). Tests: routing + visibility matrix (write member / read-only / outsider), read-only restore/purge refusal, restore roundtrip, personal-trash unchanged, sweep of space trashes, and the retention suite adapted to the new routing.
Cordy merged commit d39beb49f8 into main 2026-08-03 20:47:10 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/Cairn#97
No description provided.