Per-user read state and subscriptions
Read, starred and position move to entry_state; subscriptions carry each person's keywords, auto-download, explicit and per-scan limit. The feed list and unread counts are per person, and the existing library is adopted by the admin on first start. The feed URL, folder and schedule stay shared and admin-only: one file serves everyone, so they describe the file rather than a preference. Scanning merges subscribers' wants -- anyone wanting an item is enough -- via merge_policy, which is pure and tested. Also: the test fixture wiped its data directory from every Playwright worker, deleting the database out from under the running daemon. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AdXho5tTkjFLeUXKbEjKBh
This commit is contained in:
36
PROGRESS.md
36
PROGRESS.md
@@ -56,6 +56,38 @@ and until now nothing set them.
|
||||
|
||||
---
|
||||
|
||||
## 2026-09-11 — Steps B and C: what is yours, what is everyone's
|
||||
|
||||
Read, starred and playback position moved out of `entries` into `entry_state (user_id, feed_id,
|
||||
guid, ...)`; subscriptions became rows in `subscriptions (user_id, feed_id, ...)` carrying **your**
|
||||
keywords, auto-download, explicit and per-scan limit. The feed list, unread counts, filters and
|
||||
mark-all-read are all per person now. On first start the existing library is adopted by the admin:
|
||||
2438 read/starred items and all 86 feeds, so nothing was lost.
|
||||
|
||||
The split follows from the file being shared:
|
||||
|
||||
* **Yours**: read state, starred, position, keywords, auto-download, explicit, per-scan limit,
|
||||
and which feeds you see at all.
|
||||
* **Everyone's**: the feed URL, its download folder, and when it is scanned -- there is one copy of
|
||||
a file however many people subscribe, so those describe the file, not a preference. Admin-only,
|
||||
refused with a 403 for anyone else rather than merely hidden.
|
||||
|
||||
Scanning merges the subscribers' wants, because one fetch and one file serve them all: an item is
|
||||
downloaded if **anyone** wants it (any one person's keyword set matching is enough, and one person
|
||||
taking everything removes the filter), auto-download is on if anyone has it on, and the per-scan cap
|
||||
is the largest anyone asked for. `merge_policy` is a pure function with a test covering each of
|
||||
those. Subscribing to a feed someone already has costs no second fetch and no second copy on disk;
|
||||
unsubscribing takes it off your list alone, and only when the last subscriber leaves does the feed
|
||||
stop being scanned.
|
||||
|
||||
**A test-harness bug worth naming**: Playwright imports the config in every worker, so the fixture's
|
||||
`prepare()` ran again mid-run and deleted the data directory out from under the daemon. The daemon
|
||||
kept serving from the unlinked inode while the CLI and any query opened a fresh empty database at
|
||||
the same path -- which looked exactly like sign-in being broken. Only the launching process wipes
|
||||
now (a worker has `TEST_WORKER_INDEX`).
|
||||
|
||||
---
|
||||
|
||||
## 2026-09-10 — Scanning is the operator's decision
|
||||
|
||||
The per-feed **Check schedule** picker is gone from feed settings, and the global Settings page is
|
||||
@@ -123,10 +155,10 @@ on disk. `enclosures.url` is already globally UNIQUE, so the file half is nearly
|
||||
optionally creates a user -- honoured only from a `trusted_proxies` address, so a LAN client
|
||||
cannot simply assert it. The existing shared token keeps working and resolves to the admin, so
|
||||
the healthcheck and any scripts survive. Login page for direct access.
|
||||
- [ ] **B. Per-user read state.** `entry_state(user_id, feed_id, guid, read, flagged, position)`;
|
||||
- [x] **B. Per-user read state.** `entry_state(user_id, feed_id, guid, read, flagged, position)`;
|
||||
the current columns on `entries` migrate into the first user's rows. Unread counts, filters and
|
||||
playback position all become per user.
|
||||
- [ ] **C. Per-user subscriptions.** `subscriptions(user_id, feed_id)`. config.toml stays the feed
|
||||
- [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
|
||||
|
||||
Reference in New Issue
Block a user