Skip to content

fix(auth): keep private route cache policies on authenticated responses - #408

Merged
Brooooooklyn merged 5 commits into
mainfrom
fix/auth-keep-route-cache-control
Oct 13, 2026
Merged

Brooooooklyn merged 5 commits into
mainfrom
fix/auth-keep-route-cache-control

Conversation

@TheAlexLichter

@TheAlexLichter TheAlexLichter commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Problem

Void's auth middleware copies the session lookup's cache-control: no-store and pragma: no-cache onto every signed-in response. This overwrites the route's own policy. So signed-in data can never be revalidated: private, no-cache plus an ETag never gives a 304.

signed-in GET /report   (route sends private, no-cache + ETag)
  route ──► auth middleware ──► Cache-Control: no-store    ✗ never a 304

What this PR changes

route Cache-Control (signed-in)        before      after
────────────────────────────────────   ─────────   ──────────────────────────
no-store                               no-store    kept (no pragma)
private, no-cache   (+ any max-age)    no-store    kept → etag() answers 304
private  /  private, max-age=60        no-store    no-store
private="set-cookie" / no-cache="…"    no-store    no-store
no-cache  /  public  /  none           no-store    no-store
anonymous request                      unchanged   unchanged
  • A kept policy also skips the cookie-rotation fallback (private, no-store). The rotated Set-Cookie is still sent.
  • Directive parsing keeps quoted values intact. A comma inside no-cache="a,private" does not make a bare private.

Decisions

Question Choice Why
Keep bare private? No The browser can reuse it without asking the Worker. After sign-out, the next account on the same browser can see it.
Keep private, no-cache? Yes Shared caches can't store it, and the browser must ask before each reuse. This is the 304 case.
Send Clear-Site-Data on sign-out? Not here Separate product decision.

Known limits

  • The app sends the 304, not Void. Use Hono's etag() middleware.
  • A hand-written ETag must differ per user. Otherwise user B can get a 304 for user A's cached page.
  • The browser Back button can show a kept private, no-cache page after sign-out. Pages that must not stay in the browser cache should keep the default no-store.

Shared caches stay safe: ISR and dispatch skip requests with credentials, and they never store private, no-cache or no-store.

Testing

Test Covers
auth-isr-cache-policy.test.ts (real Better Auth) kept and no-store tables, quoted values, case and tab variants, etag() 304 end to end
auth-middleware.test.ts cookie rotation with kept and not-kept policies
vp run test, vp run check, lint, fmt pass

🤖 Generated with Claude Code

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://fix-auth-keep-route-cache-control-void-cloud.voidzero-docs.workers.dev (commit 8b0c224)

This URL reflects your latest Preview deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://df23b703-void-cloud.voidzero-docs.workers.dev 8b0c224 2026-10-13T04:53:25.509Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://f3f844a1-void-cloud.voidzero-docs.workers.dev 8af5b3f 2026-10-12T11:11:13.953Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://9a40282f-void-cloud.voidzero-docs.workers.dev 76ad922 2026-10-12T08:47:40.309Z Visit the dashboard ↗

TheAlexLichter and others added 3 commits October 12, 2026 13:09
A bare `private` still lets the browser reuse a signed-in response
without asking the Worker, so the next account on the same browser can
see it. Keep the route's Cache-Control only when it has `no-store`, or
`private` together with `no-cache`. Every other policy gets the session
lookup's `no-store`, as before.

Parse directives with quoted values intact, so a comma inside a quoted
value can't produce a false bare directive.

Document `etag()` for 304s, per-user ETags, and the Back button limit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Brooooooklyn
Brooooooklyn merged commit 01900a2 into main Oct 13, 2026
19 checks passed
@Brooooooklyn
Brooooooklyn deleted the fix/auth-keep-route-cache-control branch October 13, 2026 06:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants