Skip to main content

RecoveryPolicy

Trait RecoveryPolicy 

Source
pub trait RecoveryPolicy: Send + Sync {
    // Required methods
    fn reset_token_ttl(&self) -> ChronoDuration;
    fn request_rate_limit(&self) -> (u32, StdDuration);
    fn consume_rate_limit(&self) -> (u32, StdDuration);
    fn strict_mailer_required(&self) -> bool;

    // Provided method
    fn public_site_url(&self, req: &Request) -> Option<String> { ... }
}
Expand description

Tunables for the R1 recovery flow: token TTL, rate-limit shape, strict-mailer boot guard, and public-site-URL derivation.

Admin::new() seeds DefaultRecoveryPolicy; projects override via crate::admin::Admin::recovery_policy. The trait is Send + Sync so the Arc<dyn RecoveryPolicy> lives on Admin and is cheap to clone into async futures.

The trait method public_site_url has a provided default that derives the URL from request headers via [derive_public_site_url] per DESIGN_RECOVERY.md §12.3. Projects whose deployment can’t rely on the standard Forwarded / X-Forwarded-* / Host headers override this method and return their own absolute URL (e.g. stamped at deployment time from a config secret).

§Trust boundary for forwarded headers

The default public_site_url honours these client-supplied inputs in priority order:

  1. RFC 7239 Forwarded header (for / proto / host of the first hop)
  2. X-Forwarded-Proto + X-Forwarded-Host (first CSV entry of each)
  3. Host header (assumes http://)

The operator’s reverse proxy MUST strip incoming versions of these headers before adding its own. The framework cannot know the deployment topology; if a hostile client can reach the process directly with a chosen Forwarded: … header set, the reset link in the dispatched email will point wherever they ask. proto is whitelisted to {http, https} (case-insensitive) and host is rejected when it contains whitespace, control bytes, or CRLF — so direct injection of \r\n-style header smuggling fails — but a malicious yet shape-conformant value still needs to be filtered upstream.

Projects that need a stricter trust posture: override public_site_url to return a fixed string (e.g. read from project config at startup) and the framework will use that regardless of headers.

Required Methods§

Source

fn reset_token_ttl(&self) -> ChronoDuration

How long a freshly-issued reset token stays valid. Default 1 hour. Locked-decision per DESIGN_RECOVERY.md §17.

Source

fn request_rate_limit(&self) -> (u32, StdDuration)

Per-IP rate-limit on POST /admin/forgot-password. Returned as (capacity, window): at most capacity requests within window. Default (5, 15min).

Source

fn consume_rate_limit(&self) -> (u32, StdDuration)

Per-IP rate-limit on POST /admin/reset-password/<token>. Tighter than the request limit since the consume path is the brute-force surface. Default (10, 5min).

Source

fn strict_mailer_required(&self) -> bool

When true, the framework refuses to start at boot if the registered mailer is still the default crate::email::LogMailer (production deployments must opt in to a real mailer). Default false. Enforcement lands when the recovery handlers ship (R1 commit #7+); this commit ships the declaration only.

Provided Methods§

Source

fn public_site_url(&self, req: &Request) -> Option<String>

Derive the absolute base URL the reset email’s link should point at. Default: see [derive_public_site_url] + trust-boundary docs on this trait. Projects override this method to return a fixed string (e.g. read from config) when header derivation isn’t appropriate for their topology.

Returns None when nothing resolves; the caller (R1 issue handler, commit #7) treats None as a hard failure and records metadata.email_send_status = "failed" with a clear log line.

Implementors§