crabidy/plan/rss-provider.md

61 lines
3.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Plan — RSS provider
Executes `architecture/rss-provider.md` against `quality/rss-provider.md`.
Two commits: **(A)** the `rssdy` crate, **(B)** wiring (server feature,
clients, docs).
## A — The `rssdy` crate
- [x] **A1 — `api::Episode::key_for`**`blake3(guid)` truncated to 16 hex
chars. *Verifies:* G7.
- [x] **A2 — `api::FeedFetcher`**`reqwest` client with the timeout,
streaming the body while counting bytes so `max_feed_bytes` rejects
before buffering it whole; parse with `feed-rs`; map entries to
`Episode` (guid → key, title, author, published, `itunes:duration` where
present, first audio enclosure); skip entries with no enclosure; sort
newest first; truncate to `limit`. Errors carry no URL. *Verifies:* G1,
G15, G16, G17.
- [x] **A3 — `slugify` + de-duplication** at load and on rename/subscribe.
*Verifies:* G8.
- [x] **A4 — `parse_path`** for root/feed/episode, rejecting anything else.
*Verifies:* G10.
- [x] **A5 — `Client::with_api` / `init`** — resolve subscriptions with
slugs, drop entries without a url (warning), keep the settings for
write-back. No feeds still mounts. *Verifies:* G18.
- [x] **A6 — Listings**`get_lib_root` lists subscriptions and is
creatable; `get_lib_node("/rss/<slug>")` fetches, replaces the memo, and
returns episodes as tracks (queueable, downloadable). *Verifies:* G3, G9.
- [x] **A7 — Memo** — bounded push/replace, listing-written, read by
`get_urls_for_track` / `get_metadata_for_track` /
`resolve_tracks_into`. *Verifies:* G4, G5.
- [x] **A8 — Subscription CRUD**`create_lib_node` (URL → fetch → name
from feed title → add), `rename_lib_node`, `delete_lib_node`, and
`settings()` reserializing the live list. *Verifies:* G11G14.
- [x] **A9 — `rssdy/src/tests.rs`** over a `FakeFeeds` fixture backend
covering every gate above.
- [x] **A10 — Commit A**: crate tests, clippy, fmt clean.
## B — Wiring
- [x] **B1 — Server feature `rss`** — optional `dep:rssdy`, `all-providers`
membership, `ALL_PROVIDERS` + `BUILT_IN_PROVIDERS` entries,
`ProviderToggles.rss`, `ProviderToggles::all`, and the mount
registration through `mount_from_config`. *Verifies:* G19.
- [x] **B2 — `check-features`** gains an `rss`-alone row. *Verifies:* G19.
- [x] **B3 — Clients**`/rss` into `MUTABLE_ROOTS` in `cbd-tui/src/rpc.rs`
and `cbd-web/src/state.rs`, with their cacheability tests extended.
*Verifies:* G6.
- [x] **B4 — Docs**`docs/src/providers/rss.md`, `rssdy/README.md`,
links from `docs/src/providers.md`, `SUMMARY.md`, `config.md`, and the
root README (tree + config table). Say plainly that a premium URL is a
credential, that listings are never cached, and that bookmarks depend on
publisher guids. *Verifies:* G20.
- [x] **B5 — `plan/summary.md`** entry, then commit B.
## Deferred (recorded, not dropped)
- OPML import/export, per-episode played state, background polling, and
artwork (`itunes:image`) — the library model has no field for it.
- Sharing the episode→`Track` mapping with `fyyd`; worth extracting only
if a third podcast source lands.