Use open CORS on public catalog routes (PP-5045) - #3693
Conversation
|
Claude finished @tdilauro's task in 6m 33s —— View job SummarySolid, well-scoped change: the decorator sits outside DetailsMinor:
|
Greptile SummaryThis PR applies wildcard, non-credentialed CORS handling to public catalog routes and updates the documented scope of the patron-web hostname allowlist.
Confidence Score: 5/5The PR appears safe to merge because no blocking failure remains within the reviewed follow-up scope. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| src/palace/manager/api/routes.py | Replaces patron-origin CORS with wildcard non-credentialed CORS on public routes and positions it before library resolution. |
| tests/manager/api/test_routes.py | Adds coverage for wildcard public-route responses, library-resolution errors, and retained patron-route allowlisting. |
| tests/fixtures/api_routes.py | Extends the direct route-request fixture to accept request headers needed by CORS tests. |
| README.md | Clarifies that the hostname allowlist governs patron-data endpoints rather than public catalog endpoints. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
Browser[Browser client] --> Route{Requested route}
Route -->|Public catalog route| PublicCORS[Wildcard origin without credential support]
Route -->|Patron-management route| PatronCORS[Configured patron-web origin allowlist]
PublicCORS --> Library[Resolve library when required]
PatronCORS --> Auth[Authenticate patron]
Library --> PublicResponse[Public response]
Auth --> PatronResponse[Patron-specific response]
Reviews (3): Last reviewed commit: "CI AI code review feedback" | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #3693 +/- ##
=======================================
Coverage 93.56% 93.56%
=======================================
Files 513 513
Lines 46948 46951 +3
Branches 6414 6414
=======================================
+ Hits 43926 43931 +5
+ Misses 1953 1952 -1
+ Partials 1069 1068 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L3iQo3a4T3VgtLEyDbonPL
5125daf to
e18169b
Compare
Description
Applies the new
allows_public_corsdecorator to the routes that serve public, credential-free data: the library index, authentication document, catalog feeds (groups, feed, navigation), search, crawlable feeds, the MARC download page, works lookups (URN lookup, contributor, series, permalink, recommendations, related books), analytics event tracking (authentication there is optional, and events record with or without a patron), andversion.json. These routes now sendAccess-Control-Allow-Origin: *without credentials. The authentication document, the MARC page, and/version.jsonpreviously sent no CORS headers at all. Authenticated routes (loans, holds, borrow, fulfill, revoke, annotations, and the patron profile, device, and token endpoints) keep the existingallows_patron_weballowlist behavior.Per the decorator's placement rule, it sits outside
has_library, so OPTIONS preflights get full CORS headers before library resolution can short-circuit.Updates the
PALACE_PATRON_WEB_HOSTNAMESdocumentation to match.Note
This PR is stacked atop #3680. It should not be merged until that one has landed.
Motivation and Context
These routes are readable by anyone without credentials, so restricting browser origins adds no protection. It only breaks web catalog clients whose hosts are not in the configured allowlist, which creates friction for dev instances and new deployments. With open CORS on public routes, a web catalog works against any Circulation Manager without configuration; the allowlist now only governs credentialed endpoints.
Patron-specific variants of these routes (root lane redirects, loan state on permalinks, age-based lane filtering) are reachable only through an explicit
Authorizationheader. The Palace web client sends that header on a plain, non-credentialed fetch, so the wildcard origin does not affect it; cookie-credentialed requests are not part of the patron API.How Has This Been Tested?
New parametrized tests request each of the 18 public routes through the route test fixture with a real
Originheader and assert the wildcard origin with no credentials header. A negative test asserts/loansstill echoes only configured allowlist origins and never the wildcard, and a library-not-found test pins the decorator's placement outsidehas_library. All existing route and controller tests pass.Checklist