Repository navigation
feat(ui): Sign in from the login screen (#360) - #381
Merged
Merged
Conversation
A user signs in at /login with username or email and password and lands on the signed-in placeholder at /, which sends a visitor without a token back to /login. React Hook Form and zod/mini validate the form. src/api/ calls POST /api/v1/auth/login, keeps the access token in memory only, and reads the Problem Details: code, field errors and Retry-After. Each code maps to a catalog message; an unknown code, an unreadable body or a network failure shows the generic one. A locked or rate-limited response counts down from Retry-After and blocks the button until it ends. zod/mini instead of zod: the full build put initial JS at 148.5 of the 150 kB budget; it is 130.5 kB now. zod's eval probe is turned off in main.tsx, because the CSP forbids eval. End-to-end flows: success, wrong password, disabled account, and locked account with its countdown, in all three browsers. No public endpoint creates invites (#107 is deferred), so users are seeded through the admin API, as decided on #360. The global setup rotates the bootstrap admin's password and fails on a database that is not fresh. Each test creates its own user and changes the temporary password. Every e2e request reaches the API from the one Docker bridge address, so the Sensitive rate limit (10 per minute per client) would stop the suite within seconds. Its permit limit becomes the validated setting RateLimit:SensitivePermitLimit. The default is unchanged; only the e2e compose file raises it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MessageKey is derived from the catalog, both rate-limit policies are configured in one place, the success and disabled-account flows are checked with axe, an e2e reload proves the token is not persisted, and the lockout pauses leave a margin past each lock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The countdown sits beside the alert instead of inside it, so a screen reader announces the error once rather than on every tick. The success flow checks for CSP violations before the reload clears them. 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 #360. Implementation decisions: seeding and rate limits, where the code differs from the design.
Summary
API:
RateLimit:SensitivePermitLimit, a validated setting with the default unchanged (10). Onlydocker-compose.e2e.ymlraises it, because every e2e request reaches the API from the one Docker bridge address.E2E users are seeded only through the public API:
POST /usersand changes its temporary password.PATCH /users/{id}.zod/miniinstead ofzod, because the full build left the initial JS at 148.5 of the 150 kB budget.Evidence
/was an unguarded placeholder.After:
Retry-After.429;0and-1fail at startup).E2Ejob.Merge Danger
Door: two-way
Blast Radius: UI routes
/now needs a token, so the smoke test checks the login page instead of the placeholder. The API change only adds a setting, and its default is unchanged.🤖 Generated with Claude Code