testing/cross_backend/login_security.ts

Cross-backend parity suite for login rate limiting + trusted-proxy (X-Forwarded-For) resolution over real HTTP.

Login throttling and client-IP resolution are wired-but-never-crossed: the in-process describe_rate_limiting_tests covers the limiter, and the fuz_http / proxy middleware unit tests cover XFF resolution, but no case exercised either over a real socket on both impls — the limiter is nulled on every standard cross backend and the resolved client IP has no wire-observable downstream there. This dedicated suite spawns a backend with the login limiters enabled + the loopback proxy trusted (see global_setup_login_security.ts), then pins two properties end-to-end:

  • per-IP login limit fires — the first default_login_ip_rate_limit failed logins from one forwarded IP each return 401, and the next returns 429 with the canonical `{error: "rate_limit_exceeded", retry_after} body **and** a Retry-After: ceil(retry_after)` header. The 429 wire shape is the cross-impl contract — TS rate_limit_exceeded_response and Rust route_response::rate_limit_exceeded must agree.
  • trusted-proxy / XFF resolution is honored — distinct X-Forwarded-For IPs get independent buckets: after exhausting one forwarded IP to 429, a *different* forwarded IP is unaffected (401, not 429). A backend that ignored XFF and keyed on the (loopback) TCP peer would 429 the fresh-IP request too — so the 401 proves the limiter keys on the resolved X-Forwarded-For client IP.

Determinism without a limiter reset. Limiter state is in-memory and the per-test _testing_reset wipes only the DB, never the buckets — so each case uses its own forwarded IP and its own (non-existent) username, keeping every bucket independent across cases and across the two impls (separate processes). The login floor is zeroed on both spines, so the failed-login loop stays fast.

Both surfaces are flat REST (POST /api/account/login) on every spine, so this is an imperative suite (not a conformance_table row) — the sibling of origin.ts / identity_parity.ts. Cross-process only: the limiter+proxy wiring is the point, and the in-process counterparts already exist (describe_rate_limiting_tests + the proxy middleware tests). Cited property: docs/security.md §"Rate Limiting" + §"Trusted Proxy / Client IP".

$lib-free by contract (relative specifiers only), like the sibling cross-backend suites.

view source

Declarations
#

2 declarations

describe_login_security_cross_tests
#

LoginSecurityCrossTestOptions
#

testing/cross_backend/login_security.ts view source

LoginSecurityCrossTestOptions import type {LoginSecurityCrossTestOptions} from '@fuzdev/fuz_app/testing/cross_backend/login_security.js';

Options for the login-security parity suite.

setup_test

Per-test fixture producer (cross-process only — see the module doc).

type SetupTest

readonly

login_path?

REST login route path. Default /api/account/login (the spine convention).

type string

readonly

Depends on
#