Skip to content

Open cross-origin reads for third-party frontends - #309

Merged
amrtgaber merged 1 commit into
mainfrom
open-reads-cors
Jul 26, 2026
Merged

Open cross-origin reads for third-party frontends#309
amrtgaber merged 1 commit into
mainfrom
open-reads-cors

Conversation

@amrtgaber

@amrtgaber amrtgaber commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Completes #297: the public read surface now answers cross-origin browser requests from any origin with Access-Control-Allow-Origin: * — no per-origin onboarding — while the credentialed first-party posture is untouched.

New PublicReadCORSMiddleware (pure ASGI, registered outside the credentialed CORSMiddleware), implementing the design notes recorded on the issue:

  • Split posture in two layers, since one CORSMiddleware can't express both (wildcard and allow_credentials are mutually exclusive per spec): criticalbit origins keep the credentialed echo for the management surface; everyone else gets * on public /v1 GET/HEAD.
  • Literal *, never an origin echo — echoing requires Vary: Origin, which fragments CDN cache entries per origin; * is constant and cache-safe. The layer never touches Vary.
  • /v1/me excluded — a GET, but per-user and cookie-authenticated; it stays first-party-only. Writes and infra routes get nothing.
  • Simple requests only (plain GETs, EventSource included) — no preflight machinery needed or wanted; documented in the README consumer section.
  • Defers, never double-sets: if the credentialed middleware already answered, the layer stays out. One real subtlety found by test: Starlette's credentialed CORSMiddleware stamps allow-credentials: true on every response, allowed origin or not — paired with * that's a spec-invalid combination, so the layer strips the stray header on the responses it opens (that branch only runs for non-first-party origins, so no grant is ever revoked).
  • Pure ASGI so the streaming /v1/stream response passes through untouched.

README's third-party-frontend section rewritten for the new posture (browser apps work from any origin; keep requests simple; write API unchanged).

Tests

598 passed. New matrix: third-party GET → * with no credentials header; first-party origin → credentialed echo preserved (no downgrade to *); /v1/me → never opened; third-party write → nothing; no Origin header → nothing; infra routes → nothing.

Closes #297

@amrtgaber
amrtgaber merged commit f39b99f into main Jul 26, 2026
3 checks passed
@amrtgaber
amrtgaber deleted the open-reads-cors branch July 26, 2026 04:54
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.

Third-party frontend reads: document per-origin CORS onboarding; design the open-reads posture

1 participant