Rate limits
z4j applies token-bucket rate limits to public auth paths and to admin paths whose write fan-out can be expensive. Authenticated read paths are not capped.
Per-IP buckets
Section titled “Per-IP buckets”All values are the in-code defaults defined in z4j_brain.domain.ip_rate_limit. The window is 60 seconds.
| Endpoint | Cap (per IP) |
|---|---|
POST /api/v1/auth/login | 20 / min |
POST /api/v1/auth/password-reset/request and /confirm | 10 / min (shared bucket) |
GET /api/v1/invitations/preview and POST /api/v1/invitations/accept | 30 / min (shared bucket) |
| Bulk-write admin actions (bulk-delete tasks, bulk-retry, purge-queue, schedule trigger / import / resync) | 10 / min (shared bucket) |
Notification-channel /channels/test preflight | 20 / min |
| Agent WebSocket connects | dedicated bucket on the /ws endpoint |
Exceeding any limit returns 429 Too Many Requests.
Per-account login lockout (not per-IP)
Section titled “Per-account login lockout (not per-IP)”In addition to the per-IP login bucket, the brain tracks failed logins per account:
| Setting | Default | Meaning |
|---|---|---|
Z4J_LOGIN_LOCKOUT_THRESHOLD | 10 | Failed attempts before lockout. |
Z4J_LOGIN_LOCKOUT_DURATION_SECONDS | 900 (15 min) | How long the lockout lasts. |
Z4J_LOGIN_BACKOFF_BASE_SECONDS | 0.5 | Per-failure incremental backoff applied to the response. |
Z4J_LOGIN_BACKOFF_MAX_SECONDS | 5.0 | Cap on that backoff. |
Z4J_LOGIN_MIN_DURATION_MS | (settings) | Minimum response time held server-side so timing is not exploitable. |
The lockout is per-account, so an attacker rotating IPs to evade the per-IP cap still hits the account-level wall.
Response headers
Section titled “Response headers”The brain does not emit X-RateLimit-Limit / X-RateLimit-Remaining / X-RateLimit-Reset today. Detect throttling via the 429 status alone.
Tuning
Section titled “Tuning”Tunables for login lockout and account backoff live in Settings (see above and the env-vars reference). The per-IP bucket sizes are in-code defaults; changing them requires a code change.
Bypass
Section titled “Bypass”/health and /metrics are not rate-limited; scraping is expected.