29 Commits
Author SHA1 Message Date
Julien HerrandClaude Opus 4.7 97ce9a62b4 feat: reader-rendering correctness + privacy hardening (P1·S batch)
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 <[email protected]>
2026-05-24 17:47:46 +02:00
Julien HerrandClaude Opus 4.7 c2a0a68058 refactor(api): remove the deprecated /api/stats endpoint
The only consumer (the marketing landing) now uses /api/v1/stats, so drop
the legacy /api/stats route and its handler. Delete src/routes/stats.ts and
its test; repoint the index CORS test at /api/v1/stats.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-23 23:15:08 +02:00
Julien HerrandClaude Opus 4.7 daa93d8093 feat(api): make /api/v1/stats public and point the landing at it
Unify the monitoring stats on the versioned API: /api/v1/stats is now public
(no auth) and CORS-enabled, mirroring the legacy /api/stats. The marketing
landing (docs/index.html) now fetches /api/v1/stats; /api/stats is kept as a
deprecated alias for existing monitors. Feed/email routes remain token-gated.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-23 23:12:43 +02:00
Julien HerrandClaude Opus 4.7 45d2a14a12 feat(api): add versioned REST API with OpenAPI 3.1 spec
Expose /api/v1/* for feed and email management (feeds CRUD, email
list/get/delete, stats) so the service can be automated without scraping
the admin UI. Built on @hono/zod-openapi; the OpenAPI 3.1 spec is served at
/api/openapi.json with a Scalar reference at /api/docs.

Auth is token-based (Authorization: Bearer <ADMIN_PASSWORD>) plus the
existing reverse-proxy headers — no cookie, no CSRF. Extracted the auth
primitives into src/lib/auth.ts and the feed create/update/delete
orchestration into src/lib/feed-service.ts so the admin UI and the REST API
share a single source of truth.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-23 23:01:15 +02:00
Julien HerrandClaude Opus 4.7 db31e33a8b docs: extract install/deploy/config guide into INSTALL.md
Slim README down to project overview (why, features, architecture,
security) with a short Installation quick-start that links to the new
INSTALL.md. Repoint setup.sh references and CLAUDE.md maintenance list.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-23 21:49:19 +02:00
Julien HerrandClaude Opus 4.7 6cd2d425a2 feat(attachments): list downloadable attachments on admin email detail page
The admin email detail view loaded the full email but never rendered its
attachments, so there was no way to download them from the admin UI (only
the public entry view and the feed enclosure exposed them).

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-23 18:11:29 +02:00
Julien HerrandClaude Opus 4.7 ddde0e26a2 docs(readme): add Continuous deployment section with CI secrets and token permissions
Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-23 17:51:50 +02:00
Julien HerrandClaude Opus 4.7 20c9bca34a docs(readme): note R2 permission needed for scoped deploy tokens
Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-23 17:50:04 +02:00
Julien HerrandClaude Opus 4.7 f150d40c45 feat(attachments): R2 toggle, storage metrics, and demo R2 config
Add an ATTACHMENTS_ENABLED switch (default on when R2 is bound) via a
central getAttachmentBucket helper, surface R2 + estimated KV usage
against the free tier on the status page and /api/stats (refreshed by the
hourly cron), let setup.sh create and wire the R2 bucket, and bind the
demo bucket so the deployed demo has attachments.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-23 17:33:50 +02:00
Julien HerrandClaude Opus 4.7 3ad0188bc0 feat(unsubscribe): RFC 8058 one-click unsubscribe on feed deletion
Capture each sender's List-Unsubscribe one-click URL during ingestion
(stored per sender in feed metadata, mirroring the iconDomain pattern) and
fire one-click POSTs via ctx.waitUntil when a feed is deleted, so newsletters
stop mailing the now-dead address. Tracked with a new unsubscribes_sent
counter surfaced on the status page and /api/stats.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-23 14:35:05 +02:00
Julien HerrandClaude Opus 4.7 eb12f21894 feat(favicon): per-feed icon from the last sender's domain
Resolve each feed's most recent sender domain and serve its favicon at
GET /favicon/:feedId, falling back to the project icon. Icons are fetched
in the background on ingestion (direct /favicon.ico then a DuckDuckGo
fallback), cached base64 in KV keyed by domain with a 1-week TTL so the
fetch only fires when absent. Exposed via RSS <image> / Atom <icon>/<logo>
and rendered in the admin feed list, plus a landing-page feature card.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-23 14:05:14 +02:00
Julien HerrandClaude Opus 4.7 b534ce5bf8 feat(monitoring): add stats counters API and public status page
Add GET /api/stats exposing cumulative counters (feeds created/deleted,
emails received/rejected, recent date-times) plus live values (active
feeds, active WebSub subscriptions). Counters persist in a stats:counters
KV singleton and are incremented at the email-processing chokepoint and
feed create/delete paths. Replace the / → /admin redirect with a public
status page rendering these figures with a link to the admin.

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-23 09:50:51 +02:00
Julien HerrandClaude Sonnet 4.6 6fddbd40f2 feat: rename project to kill-the-news, add GitHub Pages landing page
- Rename all references from Email-to-RSS/email-to-rss to kill-the-news
  across README.md, AGENTS.md, package.json, wrangler-example.toml, setup.sh
- Add docs/index.html: dark-themed landing page for GitHub Pages
  covering features, how it works, quick start, and tech stack

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-05-21 20:45:25 +02:00
Julien HerrandClaude Sonnet 4.6 b24ee969d1 style: fix Prettier formatting on 11 files
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-05-21 11:35:37 +02:00
Julien HerrandClaude Sonnet 4.6 e93bbb8d3e feat: store email attachments in R2 and expose as RSS enclosures
Attachments from incoming emails are uploaded to an optional Cloudflare R2
bucket and exposed as <enclosure> elements in RSS and <link rel="enclosure">
in Atom feeds, served at /files/{id}/{filename} with immutable caching.

R2 is opt-in: if ATTACHMENT_BUCKET is not bound the feature is a no-op.
Attachments are cleaned up from R2 on email/feed deletion and during
size-based feed trimming. Adds MockR2 to the test setup.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-05-21 09:09:37 +02:00
Julien Herr 3e28246c61 docs: document FEED_MAX_SIZE_BYTES and proxy auth setup in README 2026-05-21 08:42:48 +02:00
Julien HerrandClaude Sonnet 4.6 ad5bd9a79a docs: document Cloudflare Email Workers as primary ingestion method
Add setup instructions for Cloudflare Email Routing (Option A, recommended)
and reposition ForwardEmail as an optional alternative (Option B). Clarify
Cloudflare free plan includes Workers, KV, and Email Routing. Fix security
note scope and remove redundant/misleading content.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-05-21 00:36:44 +02:00
Young Lee 1d8cffb119 Update README.md 2026-02-09 12:14:06 -08:00
Young Lee bf3a4d9672 Improve admin delete confirmations 2026-02-06 13:36:17 -08:00
Young Lee 1c40740686 feat(admin): async bulk delete with toasts 2026-02-06 01:17:03 -08:00
Young Lee 2d350a7601 feat(admin): style search + clarify bulk actions 2026-02-06 00:49:36 -08:00
Young Lee 65cf54a764 feat(admin): resizable + sortable table columns 2026-02-06 00:26:38 -08:00
Young Lee 022c188873 fix(admin): truncate spam titles + speed up table view 2026-02-06 00:11:32 -08:00
Young Lee 223560e874 fix(security): lock down admin + add bulk cleanup UI 2026-02-05 23:18:25 -08:00
Young Lee daf54a0fc0 chore: modernize setup, dependencies, and project docs 2026-02-05 22:34:13 -08:00
Young Lee 610823cb96 Update README 2025-02-27 20:41:46 -08:00
Young Lee 38f56eb7e2 Completely streamline setup experience for new users, add more documentation 2025-02-27 20:15:05 -08:00
Young Lee 56a8263f33 Enhance admin interface, security, and feed management with improved UX and authentication 2025-02-27 18:04:01 -08:00
Young Lee 8839aac24b Set up initial project and files 2025-02-27 14:51:38 -08:00