Skip to main content

Forgot Password

POST 

/auth/forgot-password

Begin the password-reset flow (SCRIFT-82).

Always 202, regardless of whether the email matches a user - the response body is identical on both paths, and a floor on the handler's wall-clock time keeps the duration identical too.

⚠ That floor is load-bearing, not belt-and-braces. The known-account path mints a token and commits a transaction; the unknown-account path returns after a single SELECT. An identical body with a distinguishable duration still enumerates accounts. This docstring previously claimed timing safety that no code provided.

Rate limits: 3/hour per client address (slowapi, keyed by :func:~scrift.api.middleware.rate_limit.get_client_address, which resolves the visitor through the proxy chain - see #110), and a silent per-account budget in the service layer.

⚠ The per-account budget never changes the response. A 429 that fired only for accounts that exist would be an enumeration oracle, which is exactly what the always-202 contract exists to prevent. Only the address-keyed limit may 429, because it does not depend on whether the account exists.

Request​

Responses​

Successful Response