Warn before deleting a file other people share

A feed with other subscribers labels the button Delete for everyone and
names them in the confirmation. The server decides: if anyone else has
starred the item or not played it, DELETE returns 409 with the reason and
only ?force=true proceeds. A feed's header says when it is shared, which
answers why a file nobody here asked for exists.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AdXho5tTkjFLeUXKbEjKBh
This commit is contained in:
2026-09-11 02:37:07 +00:00
parent f0d03c79c8
commit 686851b448
2 changed files with 39 additions and 9 deletions

View File

@@ -56,6 +56,26 @@ and until now nothing set them.
---
## 2026-09-11 — Step D: one file, and everyone who wants it
The last of it, which is all about telling the truth before acting:
* **Delete says whose file it is.** A feed with other subscribers labels the button *Delete for
everyone*, and the confirmation names how many people share it. The server then has the last
word: if anyone else has starred the item or not played it yet, `DELETE /api/enclosures/{id}`
returns **409** with the reason in plain words, and only `?force=true` goes through. So the
rule is enforced where it matters rather than in the page that happens to be asking.
* **A feed's header says it is shared** -- "shared with 1 other person" -- which is the answer to
"why is there a file here I never asked for": someone else's subscription fetched it, and one
copy serves you both.
* Retention already respects the same rule from the entry before this one: starred by anyone keeps
it, read by everyone releases it.
`others_wanting` is tested with three subscribers disagreeing, and a browser test walks the whole
delete flow: the label, both prompts, declining the second, and the file still being there.
---
## 2026-09-11 — Retention caught up with per-user state
Moving read and starred into `entry_state` left `reap_candidates` reading `entries.read` and
@@ -175,7 +195,7 @@ on disk. `enclosures.url` is already globally UNIQUE, so the file half is nearly
- [x] **C. Per-user subscriptions.** `subscriptions(user_id, feed_id)`. config.toml stays the feed
catalogue; the UI lists only what you subscribe to. Adding a feed someone else already has costs
nothing. A feed nobody subscribes to stops being scanned but keeps its files.
- [ ] **D. One file, many users.** Auto-download when *any* subscriber wants it; retention never
- [x] **D. One file, many users.** Auto-download when *any* subscriber wants it; retention never
deletes a file another user has starred or not yet played; deleting a download says so when
someone else still has it.