The RSS/Atom/JSON self link was derived from the request origin, leaking
the workers.dev host when reached directly instead of via the custom
domain. Use the configured-domain URL builders so self matches alternate.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Batch of four reader-facing improvements (TODO "Compat lecteurs + dedup"):
- JSON Feed at /json/:feedId (feed lib .json1()); all formats cross-link
- OPML export at /admin/opml (admin-protected; the registry lists every
feed URL, so it must not be public)
- Conditional GET on /rss + /atom: strong ETag + Last-Modified, 304 on
If-None-Match/If-Modified-Since, validators shared via http-cache.ts
- Duplicate-send dedup in ingestion: match by Message-ID, fall back to a
SHA-256 of normalized subject+content; a duplicate is a no-op and bumps
the new emails_deduplicated counter (status page + /api/v1/stats)
429 tests green, tsc clean, build dry-run OK. Docs (README/CLAUDE/TODO +
landing cards) updated.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Close the five open P1·S items from TODO.md:
- X-Robots-Tag: noindex on rss/atom/entries/files + a /robots.txt
- absolutize relative content URLs against the sender's site
- promote lazy-loaded images (data-src → src, strip loading="lazy")
- strip XML-illegal control chars from generated feeds (keep emoji)
- plain-text feed <title> (strip HTML, decode entities)
Sender-base derivation lives on the EmailAddress value object
(siteBaseUrl) instead of a misplaced favicon helper. Bump to 0.2.1
and document the changes in README + CLAUDE.md.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Add src/utils/urls.ts with baseUrl, feedRssUrl, feedAtomUrl, feedUrl,
feedEmailAddress, feedTopicPattern
- Add optional EMAIL_DOMAIN env var so web domain and email domain can
differ (e.g. demo.kill-the.news serves feeds, @kill-the.news receives mail)
- Replace all inline domain template literals with the new helpers
- Remove unused site_url/feed_url fields from FeedConfig
- Remove unused feedPath param from fetchFeedData
- Extract verifyCallback() to deduplicate verifyAndStoreSubscription /
verifyAndDeleteSubscription
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The RSS feed already advertised hub and self via the Link response
header, but the Atom feed was missing it entirely. Subscribers using
Atom had no way to discover the hub for real-time push notifications.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>