Repository navigation
feat(api): Auth errors carry a machine-readable code (#357) - #372
Merged
Merged
Conversation
Every failure of login (bearer and web), register, refresh and change-password, and every rate-limiter rejection, is now application/problem+json with a stable `code` extension and the old English text in `detail`. Failures of one request field are ValidationProblems with the code listed under that field in `errors` (username, email, password, currentPassword, newPassword). Status codes are unchanged. The sliding-window limiters report no retry time, so a rate-limited response never carried Retry-After. Each policy now answers with its whole window (60 s sensitive, 900 s refresh), after which every permit is back. Contract tests run the real endpoints, mapper and limiter on the in-process test host and pin each code, status, content type and Retry-After with literals. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The password failures' mapping throws for an error it does not own
instead of returning null for the caller to throw. The contract tests
assert every problem through one helper, so each checks its status in
the body too, and wrong credentials and lockout run on both login
endpoints. The change-password endpoint test stubs a problem rather
than the removed { error } shape. Doc comments say what, not why.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.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.
Closes #357
Summary
Auth failures change from an English sentence to Problem Details with a stable
code. Status codes are unchanged.invalid_credentials401,account_disabled401,account_locked429 + Retry-Afterrefresh_token_required401,refresh_token_invalid401,account_disabled401,account_locked429 + Retry-Afterinvalid_username/username_taken→username,invalid_email/email_taken→email,password_too_short/_too_long/_pwned→password; plain:invite_token_invalid422invalid_credentials400 →currentPassword,password_*422 →newPasswordrate_limited429 + Retry-AfterThe rate limiter now sends Retry-After on every rejection. Both policies are sliding windows, which report no retry time, so this header was never sent before. Each policy now sends its whole window as Retry-After:
The following were decided with the maintainer while implementing:
codeis a Problem Details extension.typestays at its default. feat(api): Every error is a Problem Details response #364 should reusecode(see the comment there).errorsvalues are codes, not English text.Admin endpoints are out of scope.
Evidence
The new tests (
AuthErrorContractTests) post to the real endpoints on the in-process host. Each one asserts the status, the content type,code,detail,errorsand Retry-After against literal values.application/json, notapplication/problem+json). The rate-limit cases fail on a missingRetry-After.scripts/mutation-changed.shon the five changed source files reports 100.00%.Merge Danger
Door: two-way
Nothing is deployed, and no client consumes these bodies yet. #360 is the first.
Blast Radius: auth-responses
Only the error bodies of the auth endpoints change, plus Retry-After on 429. Success responses and status codes are untouched.
🤖 Generated with Claude Code