hataa 08b27aef73
feat(auth): make login rate-limit parameters configurable, fixes #5108 (#5110)
* feat(auth): make login rate-limit parameters configurable, fixes #5108

Add auth.local.max_login_attempts (default 5) and auth.local.lockout_seconds
(default 300) so operators can tune the per-IP login throttle: raise the
ceiling for shared-egress-IP offices behind proxies/NAT, or tighten it for
stricter posture. Policy is live-read per call (matching the
_local_registration_enabled precedent), so a config reload applies without a
Gateway restart; raising the threshold mid-lockout immediately unblocks
affected IPs.

Review feedback addressed (willem-bd):
- Only FileNotFoundError falls back to the hardcoded defaults; a malformed
  config propagates, mirroring _local_registration_enabled, so an operator
  who tightened the policy never silently gets the more permissive defaults.
- _check_rate_limit looks up the record before resolving the policy, so a
  clean IP pays zero config reads (get_app_config re-hashes config.yaml per
  call and login_local is an unauthenticated async endpoint).

Bumps config_version to 39 in config.example.yaml and the Helm chart
(values.yaml + README example) so the chart drift check stays green.

* fix(auth): reject max_login_attempts=1 and honor live lockout_seconds for active lockouts

* fix(auth): close live-policy state gaps in login throttle (resurrection, count reset, broken-config verification)

* fix(auth): commit evaluated lockout duration on decreases too, preventing raise-resurrection

* test(auth): pin broken-config fail-closed sequence through the login route

* fix(auth): sweep expired locks by stored sentence and keep policy reads off the event loop

* fix(auth): re-read throttle record after the policy-resolution yield point

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-09-02 19:16:56 +08:00
..