Files
kill-the-news/CHANGELOG.md
T
Julien Herr 7297e06b94 fix(feed): escape bare ampersands in entry HTML attribute URLs
linkedom escapes & in text nodes but not in attribute values, so URLs
with query strings (?a=1&b=2) serialized with bare ampersands. Valid XML
inside the feed CDATA, but the W3C validator parses the embedded HTML and
warns "Named entity expected. Got none." on <description>/<content:encoded>
(RSS) and <summary>/<content> (Atom). Escape every & not already starting
a valid entity; covers all three formats via processEmailContent.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-25 22:49:57 +02:00

6.4 KiB

Changelog

All notable changes to this project are documented in this file.

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

Keep the ## [Unreleased] section up to date as part of every change (the same rule as the rest of the docs). At release time npm run release X.Y.Z promotes this section to ## [X.Y.Z] and the Release workflow publishes it verbatim as the GitHub Release notes — so what you write here is what ships.

Unreleased

Fixed

  • Subscription-confirmation detection now recognises a confirm email whose CTA button carries the subscribe/subscription hint only in its visible text (e.g. "Yes, subscribe me to this mailing list.") over an opaque tracking-redirect href — previously the link scored zero and the email was missed.
  • Sender favicons now recover from a transient miss: a failed favicon lookup is cached negatively for 6 hours instead of a full week, so a domain whose icon was momentarily unavailable (e.g. not yet indexed upstream) is retried on the next email instead of staying blank for days.
  • Feed entry HTML now escapes bare ampersands in attribute URLs (e.g. query strings like ?a=1&b=2), clearing the W3C feed validator's "Named entity expected. Got none." warning and improving interoperability with stricter feed readers.

0.3.1 - 2026-05-25

Fixed

  • Feed self link (RSS/Atom/JSON) is derived from the configured domain instead of the request host — it no longer leaks the workers.dev host when a feed is reached directly, and now matches the alternate link.

0.3.0 - 2026-05-25

Added

  • Native feed detection — incoming newsletters are inspected for a self-advertised Atom/RSS/JSON feed (rel=alternate links in the email HTML); discovered feeds are stored per sender on the Feed aggregate and surfaced as chips on the feed detail page, a dashboard pill, and (read-only) on the REST Feed schema, with a dismissable notice.
  • Subscription confirmation surfacing — confirmation emails ("click to confirm your subscription") are detected at ingestion and flagged on the feed; the admin UI surfaces the confirmation link, a badge, a dashboard pill, and an inline banner (all dismissable), tightened against false positives via a weak-signal heuristic.
  • JSON Feed 1.1 output (/json/:feedId).
  • OPML export of all feeds (/admin/opml).
  • Conditional GET (ETag / Last-Modified / 304) on the feed routes.
  • Per-feed Subscribe chips for RSS/Atom/JSON with copy / open / validate actions, reused across dashboard and feed detail page.
  • Email detail page links to its public entry page; land on the feed's emails page right after creation.
  • Optional per-feed "sender in title" toggle.
  • Running version shown in the admin/status footer, /health, and /api/v1/stats.

Changed

  • Read/write identity decoupling (privacy) — the public read id (FeedId, used in /rss/:feedId) is fully decoupled from the inbound email address (MailboxId, noun.noun.NN); a feed's read URL never reveals its inbound alias and vice-versa (reading /rss/<noun.noun.NN> 404s).
  • Sender display name, site URL and parsing now owned by the EmailAddress value object (DDD cleanup).
  • Release version is derived from the git tag; CI guards against tagging the wrong commit.

0.2.1 - 2026-05-24

Added

  • Optional FALLBACK_FORWARD_ADDRESS: forward non-feed mail to a verified address so a domain catch-all can point at kill-the-news without swallowing personal mail (forwarded mail is counted in the stats dashboard).

Changed

  • Feed, entry, and attachment responses send X-Robots-Tag: noindex; a new /robots.txt disallows /rss, /atom, /entries, /files, and /admin — private feeds and emails stay out of search engines.
  • Relative links/images in email bodies are absolutized against the sender's site; lazy-loaded images are promoted so they don't render blank.
  • Feed <title> is plain text (HTML stripped, entities decoded).
  • Sender-site derivation moved onto the EmailAddress value object (siteBaseUrl).

Fixed

  • XML-illegal control characters are stripped from generated feeds (valid astral characters such as emoji preserved).

0.2.0 - 2026-05-24

Added

  • Versioned REST API (/api/v1/feeds*) with an OpenAPI 3.1 spec (/api/openapi.json) and rendered reference docs via Scalar (/api/docs).
  • /api/v1/stats as the canonical public stats endpoint (JSON + CORS).
  • Optional R2 attachment storage with a config toggle, storage metrics, download links on the email/admin views, and inline cid: image rendering.
  • Project favicon (/favicon.svg, /favicon.ico) and per-feed favicon derived from the last sender's domain (/favicon/:feedId).
  • RFC 8058 one-click unsubscribe dispatched when a feed is deleted.

Changed

  • Large internal refactor toward a clean domain-driven architecture; redesigned landing/status page.

Removed

  • The deprecated /api/stats endpoint (use /api/v1/stats).

0.1.0 - 2026-05-22

Added

  • Atom feed format (/atom/:feedId) alongside RSS 2.0.
  • WebSub push notifications advertised via Link header for real-time delivery instead of polling.
  • HTML email processing — bodies sanitized via linkedom + escape-html (XSS prevention, MSO style stripping, plain-text fallback).
  • Email attachments as RSS enclosures, stored in R2 and served at /files/:attachmentId/:filename.
  • Sender blocklist with 4-level priority matching and a quick-add dropdown.
  • EMAIL_DOMAIN env var to separate web domain and email domain.
  • Authelia / reverse-proxy auth via trusted headers (Remote-User, X-Forwarded-User).
  • Demo environment auto-deployed to demo.kill-the.news with a nightly KV reset.
  • Admin UI redesign (Inter font, orange theme), client scripts compiled via esbuild, templates on hono/jsx.