Write down the multi-user plan

SQLite stays; sign-in is local user/pass or the Authentik already
fronting ipodderx.sdf1.net. Feeds, items and files shared; read state
and subscriptions per user.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AdXho5tTkjFLeUXKbEjKBh
This commit is contained in:
2026-09-10 20:04:37 +00:00
parent 772dda5154
commit ed26fa2061

View File

@@ -56,6 +56,32 @@ and until now nothing set them.
--- ---
## Multi-user — the plan
Decided with Ray: **stay on SQLite** (Postgres was considered and dropped -- it is a deployment
choice, not a capability one, and nothing here contends for writes). Sign-in is either a local
username and password or the Authentik that already fronts `ipodderx.sdf1.net` through a Cloudflare
tunnel. Feeds, items and files are **shared**; read state and subscriptions are **per user**.
The point of sharing: two people subscribed to the same show cost one fetch, one parse, and one file
on disk. `enclosures.url` is already globally UNIQUE, so the file half is nearly free.
- [ ] **A. Users, sessions, sign-in.** `users` + `sessions` tables, Argon2 hashing, session cookie,
`ipx user add|list|passwd|rm`. Authentik/proxy header (`trusted_header` in `[web]`) signs in and
optionally creates a user. 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)`;
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
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
deletes a file another user has starred or not yet played; deleting a download says so when
someone else still has it.
---
## 2026-09-10 — Items, not episodes ## 2026-09-10 — Items, not episodes
Half the library is text feeds, so the UI no longer calls everything an episode: counts, the search Half the library is text feeds, so the UI no longer calls everything an episode: counts, the search