settings->get(Setting::PasswordMinLength); return max(self::MIN_LENGTH, min(self::MAX_LENGTH, (int) $configured)); } public function rejectsBreached(): bool { return (bool) $this->settings->get(Setting::PasswordRejectBreached); } /** * The rule object handed to every password field. * * `uncompromised()` calls the k-anonymity range API at * haveibeenpwned, so it stays production-only regardless of the * setting: outside production it would put a network round-trip (and * a flaky one) into the test suite and local dev. */ public function rule(): Password { $rule = Password::min($this->minLength()); if ($this->rejectsBreached() && app()->isProduction()) { $rule = $rule->uncompromised(); } return $rule; } /** * What the forms tell the person choosing a password, shared with * every page through HandleInertiaRequests. * * `reject_breached` reports the setting rather than whether the check * will actually run, because it is a statement of this * installation's policy — the production gate above is an * implementation detail of how we keep tests offline, not something * an administrator configured. * * @return array{min_length: int, reject_breached: bool} */ public function descriptor(): array { return [ 'min_length' => $this->minLength(), 'reject_breached' => $this->rejectsBreached(), ]; } }