Say what a refused request means, instead of its status code - #159
Merged
Conversation
Every per-site endpoint now requires a credential, which makes a refusal the likeliest failure a misconfigured project meets. Until now none of the three write paths handled one: they fell through to "Patchstack returned 401", which names neither the cause nor the fix. That output is routinely read by an AI coding agent with nowhere else to look it up. There are three causes and three different remedies. Holding no credential is a setup step that never ran. Holding one that is refused means expired, revoked, or a site that no longer exists. A 403 means the credential is valid and simply belongs to another site — usually a config file carrying the wrong UUID — which was previously indistinguishable from having no credential at all. Also fixes a regression the boundary change introduces. The package-removed signal read "gone" off a 404, but a deleted site cannot answer 404 there any more: that route resolves the site from the credential, so once the site record is gone the credential resolves to nothing and the answer is 401. Unhandled, this would advise re-running login for a site that no longer exists. The question goes instead to the endpoint that can still answer it — public widget settings, which needs no credential and 404s for a removed site. One shared helper so the three paths cannot drift apart, and it returns null for anything that is not an authentication failure: relabelling a 500 as an auth problem would be worse than the bare status code it replaced. Both of those are covered by controls, along with the difference between the two 401 messages. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Improves auth error messages with clear, actionable instructions. 🎯 Quality: 100% Elite · 📦 Size: Medium 📈 This month: Your 107th PR — above team average · Averaging Excellent |
Contributor
Author
|
/review |
mariojgt
approved these changes
Aug 20, 2026
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.
ENG-3644
Every per-site Pulse endpoint requires a credential, which makes a refusal the likeliest failure a misconfigured project meets. None of the three write paths handled one — they fell through to:
That names neither the cause nor the fix, and this output is routinely read by an AI coding agent that has no other source for the answer.
Three causes, three remedies
login, orPATCHSTACK_API_KEYsiteUuidin.patchstackrc.jsonThe last one was previously indistinguishable from the first, and it is the one that would otherwise send someone hunting a network problem.
A regression this also fixes
postPackageRemovedreadgoneoff a 404. A deleted site can no longer answer 404 there: the route resolves the site from the credential, so once the site record is gone the credential resolves to nothing and the answer is 401. Verified directly against the server rather than assumed.Unhandled, uninstalling a site that was already deleted in the dashboard would advise re-running
loginfor a site that does not exist. So the question goes to the endpoint that can still answer it — public widget settings, which needs no credential and 404s for a removed site — and only then reportsgone.Tests
tests/auth-failure-message.test.ts, 9 cases, three of which are controls:gonewhen the site really is gone — otherwise a real credential problem would read as a removed site and be silently ignoredMutation-checked: collapsing the two 401 messages fails the two that distinguish them; answering for every status fails both non-auth controls; treating any 401 as
gonefails only the control that says otherwise.Full suite green (1258 passed, 6 skipped), typecheck and template typecheck clean.
Not touched
fetchSiteStatushits the public widget-settings endpoint and is correctly unauthenticated. The runtime's rules and detections paths already attach a credential.