A new rssdy crate mounted at /rss. Subscriptions are (name, url) pairs in
rss.toml; `%` on /rss takes a pasted feed URL, fetches it once, names the
subscription from the feed's own title and persists it, `e` renames, `d`
unsubscribes without touching captured audio. Feeds are read as RSS
2.0/1.0/0.x, Atom or JSON Feed through feed-rs.
**A premium feed URL is the credential.** Library paths are displayed,
logged, and persisted into saved queues and bookmark tomls, so a URL in one
leaks into all of them. Paths therefore carry a slug of the subscription name
plus blake3(guid)[..16] — /rss/the-economist-podcasts/676f8bfa48c9cac3 — and
URLs are redacted from every Debug impl and kept out of errors (reqwest goes
through without_url).
**Nothing is cached, at either end.** A listing always fetches. The half that
is easy to miss is client-side: both clients cache listings by path and only
/crabidy, /fs and /orphans bypassed it, so /rss joins MUTABLE_ROOTS in both —
otherwise a re-visit answers from the client and the server's freshness is
invisible. One memo, written by listings and read only when resolving a track
(bounded to 8 feeds), keeps queueing 40 episodes at one fetch instead of 41
without a TTL to guess at.
Verifying against the user's real Economist feed caught a bug no unit test
would have: feed-rs parses <itunes:duration> as NPT, which has no MM:SS form,
so "53:25" fell through to its leading-number regex and a 53-minute episode
reported 53 *seconds* ("1:20:40" happens to parse fine). That field is now
recovered from the raw body — a shallow scan keyed by guid and enclosure URL —
and the live feed reports 3205/2830/1662 s, matching 53:25/47:10/27:42.
Bounded by design: per-request timeout, an 8 MiB body cap enforced while
reading chunks rather than after the fact, an episode cap, newest-first
enforced at the provider boundary so any backend obeys it. A malformed entry
is skipped; only an unfetchable feed errors, and it fails that node alone.
Behind a default-on `rss` cargo feature like every other provider, with a row
in check-features. Documented in docs/src/providers/rss.md and
rssdy/README.md, both stating plainly that the URL is a credential, that
listings are never cached, and that bookmarks depend on publisher guids —
capture what you want to keep.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>