Skip to content

audit: no Cache-Control on any response — every RSS poll and agent fetch is a full Worker SSR render #37

Description

@tkowalczyk

Evidence (verified on production 2026-06-12)

curl -sI against /rss.xml, /statements/2026-05-31-weekly and ...weekly.md on prod: no Cache-Control, no ETag, no cf-cache-status — Cloudflare doesn't cache Worker responses without explicit headers. The intended audience is feed readers + LLM agents polling rss.xml/llms.txt/.md on schedules; content changes at most weekly. Every poll burns a Worker invocation and renders the full content collection.

TDD plan (failing tests first)

  1. src/lib/http/cached-response.ts (pure): feedResponse(body, contentType, { maxAge, sMaxage, swr }) returning a Response with correct headers; or a cacheHeaders() builder.
    Tests FIRST: header string exactly public, max-age=300, s-maxage=3600, stale-while-revalidate=86400 (tune values — content changes weekly; 1h edge cache + SWR is conservative), charset preserved, status set.
  2. Adopt in rss.xml.ts, llms.txt.ts, sitemap.xml.ts, statements.md.ts, and markdownResponse (200s only — 404s get no-store or short TTL; test that too).
  3. HTML pages: set via Astro.response.headers in Layout or per-page; decide whether statement HTML gets the same TTL (probably yes).
  4. Purge story: deploys replace the Worker but the CF edge cache persists — either keep s-maxage ≤ the acceptable post-publish delay (new statements appear within 1h) or add a deploy-time purge step later. Document the choice in the module.

Acceptance criteria

AC Test
Response factory header contract (200 vs 404) unit
All feed + .md endpoints emit Cache-Control unit on the factory + curl after deploy shows cf-cache-status: HIT on second request
A newly published statement is visible at the configured staleness bound documented, value asserted in test

Metadata

Metadata

Assignees

No one assigned

    Labels

    afkAgent-grabbable: implementable without further inputenhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions