The password setup/change form used hx-target="#password-section" with
hx-swap="innerHTML", but that div wraps the form itself. On a validation
error the route returns only an alert div, so the swap replaced the entire
form — the password inputs disappeared. Most visible during registration's
"set password" step.
Retarget the form to a dedicated #password-error div outside the form
(mirrors the working login form's #login-error pattern), so the form and
its inputs survive errors while messages still render inside #password-section.
Also fix pre-existing broken e2e tests: they omitted the required
current_password fill and used passwords below the zxcvbn strength
threshold (score 1 < MIN_PASSWORD_STRENGTH=2).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Use Annotated[str, Form()] for FastAPI dependencies (FAST002)
- Add missing type annotations across src/ and tests/ (ANN001/003/201/202)
- Reduce function arguments via request.form() reads (PLR0913)
- Combine return paths to reduce return statements (PLR0911)
- Use anyio.Path for async-safe filesystem operations (ASYNC240)
- Extract constants, helpers, and dict comprehensions for clarity
- Move inline imports to top-level (PLC0415)
- Use raw strings for regex match patterns (RUF043)
- Fix redundant get_session_user call in delete_user (not-iterable)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use isinstance check instead of bool flag to help ty resolve
the current_password attribute on the validated model.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use PasswordChange model (requires current password) for users with
existing passwords and PasswordSet for first-time setup. Add zxcvbn
strength validation and current password field to credentials template.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace manual validation error formatting with shared helper in both
admin and manage profile routes. Add UsernameInput validation to invite
route and GroupListInput validation to groups route.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add hidden CSRF token inputs to admin profile, groups, and invite
forms. Add maxlength, pattern, and title attributes to invite input.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add slowapi-based rate limiting: 5/min on password login, 10/min on
WebAuthn login. Includes shared rate limiter reset fixture for tests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add active-user checks to password login, WebAuthn login, and magic
link registration to prevent deactivated accounts from authenticating.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add BCP 47 locale validator to ProfileUpdate, UsernameInput model,
GroupListInput model, PasswordSet/PasswordChange with zxcvbn strength
checking, and shared format_validation_errors HTML helper.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 7 new e2e tests verifying profile form validation in both manage
and admin UIs: invalid phone number, phone normalization, E.164 hint
attributes, and admin-side email/phone/picture URL validation errors.
Fix 3 pre-existing test failures:
- Replace invalid seeded phone number (+1234567890) with valid E.164
(+12025551234) that was causing profile update tests to fail
- Update email validation error assertion to match actual pydantic
message (value_error type uses raw message, not label-prefixed)
The CSRF middleware added to main after the admin-pages branch was
created caused all admin test POSTs/DELETEs to be rejected. Add
get_csrf_token() calls and X-CSRF-Token headers to login helpers and
all mutation requests, matching the pattern used by other tests.