Files
ipodderx-rs/CHANGELOG.md
rays d7fac2d0e7 Never list paid-feed services; scan on add; no "reaped"; slimmer header
- Security: feeds from Patreon, Supercast, Supporting Cast, Glow and
  Memberful are never listed in Popular or the Directory. A Supercast
  feed keeps its key in the URL's path, which the query check missed, so
  it was being listed.
- Adding a feed queues a scan of it, and an OPML import that added feeds
  scans what is due, so items show without pressing Scan.
- A file deleted to save space, or by hand, looks as if it was never
  downloaded: no "reaped" chip, just the Download button. The retention
  summary says "deleted".
- The feed header keeps its title and stats to one line each and wraps
  its buttons; a single feed's table drops the Feed column.
- Tests: adding a feed shows its item without Scan; a deleted file shows
  no "reaped"; paid-feed hosts and acast public ids in the unit test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016HdTEWQNrzyFULijigkmMn
2026-09-11 14:47:03 +00:00

8.2 KiB

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

The long form, with what was wrong before and how it was found, is in docs/history.md.

Unreleased

Added

  • A toolbar across the top, after the original iPodderX: add and unsubscribe, play, mark read and keep for the selected item, scan, a search box for what is showing, and Settings and Log.
  • Directory, Popular and All Subscriptions at the top of the feed list, opening in the main pane. Directory lists every feed anyone here subscribes to, A to Z (GET /api/directory). All Subscriptions lists every item from every feed you subscribe to (GET /api/entries).
  • Items show as a table (unread, kept, item, feed, file, published) with a Files pane beside it, and a status bar with the totals.

Changed

  • Popular shows the top 10, not 20, and counts everyone, you included. Your own feeds stay on it, marked Subscribed, and clicking one opens it.
  • Adding a feed scans it straight away, and an OPML import that added feeds scans them, so their items show without pressing Scan.
  • A file deleted to save space, or by hand, looks as if it was never downloaded: no "reaped" label, just the Download button. The retention summary says "deleted", not "reaped".

Security

  • Feeds from paid-feed services (Patreon, Supercast, Supporting Cast, Glow, Memberful) are never listed in Popular or the Directory. A Supercast feed, which keeps its key in the URL's path rather than the query, was being listed.

0.3.0 - 2026-09-11

Added

  • Add feed lists what other people on this server subscribe to, most subscribers first, and subscribes you by id (GET /api/popular, POST /api/popular/{id}). Feeds from an OPML, and feeds with a login or a key in their URL, are never listed.
  • Upload an OPML file to import, beside the paste box. The page checks it looks like OPML before sending it and clears the picker afterwards.
  • Settings → Manage users: add and remove accounts, and choose who is an admin (GET/POST /api/users, PATCH/DELETE /api/users/{id}).
  • Per-user subscriptions, and per-user read, starred and playback state. The existing library is adopted by the admin on first start.
  • Subscribing to a feed someone else already has costs no second fetch and no second copy. Scanning merges every subscriber's wants.
  • Delete on a shared feed reads Delete for everyone, and the server answers 409 while anyone else has starred the item or not played it (?force=true overrides).
  • A shared feed's header says how many other people read it.
  • docs/ for configuration, the CLI, users, SSO and architecture, and CLAUDE.md for anyone working on the code.
  • Browser tests for OPML import and export by every route, user admin, unread ordering, and ipx import/ipx export.

Changed

  • Feeds inside an OPML subscription list the ones with unread items first.
  • OPML import subscribes you to every feed in the file. ipx import subscribes the first admin.
  • OPML export lists only your own subscriptions.
  • Production runs as a Docker image pushed to 192.168.1.130:5000 and recreated with docker compose.
  • This changelog follows Keep a Changelog. The long-form entries moved to docs/history.md.

Fixed

  • Importing another account's OPML export subscribed nobody and reported "Imported 0 feed(s)". Feeds it added had no subscriber, so they were never scanned.
  • Importing something that is not OPML answered 500. It is now 400 "that is not an OPML file", refused before anything changes.
  • Starring stopped protecting a file from the quota and age sweeps once read state became per-user.

Security

  • The log is admin-only (GET /api/logs answers 403, and the Log button is hidden). It names every account, every feed and every failed sign-in.
  • OPML export no longer hands anyone signed in the whole catalogue, including other people's private feed URLs.

0.2.0 - 2026-09-10

Added

  • Web UI served by the daemon: plain HTML and JS compiled into the binary, with feeds, items, filters, search, sanitised show notes and live progress over SSE.
  • Player bar with resume, speed, keyboard shortcuts and lock-screen controls.
  • Three-pane layout: feeds beside, items above, and the selected item's text and files below.
  • Phone layout.
  • Accounts and sign-in: Argon2id passwords, session cookies, ipx user add|list|passwd|rm, and a trusted proxy header for Cloudflare Zero Trust or Authentik (docs/sso.md).
  • Subscribing to an OPML: it is re-read every scan and its feeds show as a folder. A feed dropped from it is removed unless it has downloads.
  • Scheduling: a global interval with per-feed overrides (every 30m, 4h, 1d, 2w).
  • [general] media_types, default audio and video, and max_new_per_check, default 3.
  • Every enclosure of an item, a View link for files that are not audio or video, and per-item artwork.
  • In-app log view with Daemon I/O, Scans and HTTP tabs.
  • Mark all read on an OPML subscription.
  • Editable feed URL with a copy button.
  • Docker image whose healthcheck goes through the control socket.
  • The iPodderX name, icon, and a colour scheme taken from the icon.
  • tests/page-smoke.js and a Playwright browser suite.

Changed

  • Global settings and scan schedules are admin-only. The per-feed schedule picker is gone.
  • Feeds from an OPML live in the database, not config.toml.
  • Opening an item marks it read. Playing it marks it read only at the end or past 90%.
  • "Episodes" became "items", since half the library is text.
  • A burst of scan events causes one refresh, not one per feed.
  • All is the default filter. OPML import and export, Settings and Log moved out of the header.
  • Torrents run detached, two at a time.

Fixed

  • Download fetched the next queued episodes instead of the one clicked.
  • Pressing play made an item vanish from the Unread list.
  • Clearing a folder, schedule or cap from the UI did nothing.
  • The daemon ignored SIGTERM until the current download finished.
  • A missing function stopped the page script and left the whole UI dead.
  • One download painted progress on every pending row.
  • A torrent could freeze scanning for up to an hour.
  • Downloading from an OPML feed failed with "belongs to unsubscribed feed".
  • Image enclosures were downloaded, counted as episodes and given a play button.
  • A feed whose entries had been deleted stayed empty, because the server kept answering 304.
  • An item with several enclosures kept only the last.
  • OPML folders rendered open by default.
  • Mark read in the text pane recursed until the stack overflowed.
  • The Unread, Downloaded and Flagged filters answered 500 without a search term.
  • An OPML subscription always showed 0 unread.
  • Folder names kept doubled spaces where separators were stripped.
  • Sidebar rows had four different left edges.

Security

  • The web UI needs a token or a sign-in. The token is compared in constant time, and an empty token refuses to serve.
  • Show notes are sanitised with ammonia.
  • A proxy's user header is honoured only from an address in trusted_proxies.
  • A feed URL must be http(s), so file:///etc/passwd is refused.
  • Download folders are sanitised per path segment, so ../../etc/Show cannot climb out.

0.1.0 - 2026-09-09

Added

  • ipx, a Rust rewrite of the iPodderX engine: TOML config, SQLite state, and ipx list, add, rm and fetch.
  • RSS and Atom parsing with conditional GET, <ttl> and basic auth.
  • Streaming downloads with explicit, keyword and per-scan filters, deduplicated by enclosure URL.
  • Quota and age retention that never touches a starred file, and ipx reap [--dry-run].
  • ipx daemon with a JSON-lines Unix socket. CLI commands proxy to a running daemon.
  • Torrent enclosures through librqbit, seeding to a ratio or a time, with a stall timeout.
  • ipx import and ipx export for OPML, and systemd units in contrib/.