Make the tool proxy safe to point every visitor at - #45
Merged
Merged
Conversation
The Hobby plan does not create a URL by itself. This image runs only pnpm proxy, listens on 0.0.0.0, and answers GET /api/health so a generated Railway domain can be pasted into Tools → Tool proxy URL. Co-authored-by: Sebastian <devbadya@users.noreply.github.com>
A hosted build can now carry a proxy origin, so search and page reads work without anyone opening the Tools panel. Three things had to be true first. Both tools fall back to calling the provider from the page when the proxy fails, so an outage, a spent budget or an allowlist that has not caught up costs a slower search rather than the answer. An empty VITE_AGENT_API_BASE is no longer read as same-origin. A workflow forwarding a repository variable nobody set hands the build an empty string, which would have aimed every visitor at an /api the static host does not serve. The standalone proxy allows 30 requests a minute per caller and answers 429 beyond that, counted from the forwarded address. The origin allowlist says who may call, not how often, and an allowed page is what a scraper would forge. Co-authored-by: Sebastian <devbadya@users.noreply.github.com>
devbadya
marked this pull request as ready for review
August 30, 2026 19:22
Keep the Railway host paragraph from #44 and the AGENT_API_BASE plus fallback copy from this branch. Co-authored-by: Sebastian <devbadya@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The proxy exists but every visitor would have to paste its URL into the Tools panel to get anything from it. This makes it something the build can carry — which is only defensible once a proxy outage stops being an outage for the app.
The fallback comes first
searchWebandreadPagetry the proxy and fall back to calling the provider from the page when it fails. An outage, a spent Railway budget or an allowlist that has not caught up now costs a slower search rather than the answer. Browser-direct is the path this build already took, so the worst case is the old behaviour.The build can carry an origin
deploy.ymlpasses the repository variableAGENT_API_BASEto the build asVITE_AGENT_API_BASE. Set it and every visitor's DuckDuckGo search and page reads go through that proxy with no configuration. Leave it unset and the site stays browser-direct, which is what a fork needs.An empty value is now explicitly not a proxy. A workflow forwarding a variable nobody set hands the build
'', and the old code read that as same-origin/api— pointing every hosted visitor at an endpoint a static host does not serve.A public proxy needs a ceiling
The origin allowlist says who may call, not how often, and an allowed page is exactly what a scraper would forge.
pnpm proxyallows 30 requests a minute per caller and answers429beyond that. The caller is the left-mostx-forwarded-foraddress, since Railway and every other edge terminate the connection themselves and the socket address would put every visitor in one bucket.PROXY_RATE_LIMITchanges it,0switches it off, health checks are exempt.Tests
pnpm checkpasses: 1195 tests, up from 1187. New coverage for both fallbacks, the empty-value case, and the sliding window including per-caller buckets and eviction of callers that fell silent.The fallback, proven against the real deployed proxy. The dev server's origin (
http://127.0.0.1:5173) is not on that proxy's allowlist, so it is genuinely refused. Both/api/searchand/api/fetchfail with CORS/403 in the Network panel, and the search still returns three real results whileread_pagestill returns Example Domain:Console: the proxy is refused and FALLBACK_OK still reports three results and the page title
Network: 403 to the Railway proxy, then 200 through the reader
proxy_refuses_search_still_works.mp4
The rate limit, live against
pnpm proxywithPROXY_RATE_LIMIT=3:To show artifacts inline, enable in settings.