Each open access request on /dashboard/users gains an Approve form with
a suggested username. Approving creates a user-role account with a
20-character random temporary password, emails it to the requester with
the sign-in link, and marks the request done; if the email fails the
account is deleted so the admin can retry. Approval refuses when mail is
not configured.
Migration 0008 adds users.must_change_password. A middleware on the
signed-in routers sends flagged users to /account?change=1 until they
set a new password; login honours the flag regardless of `next`, and the
CLI's `users passwd` clears it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QVPagF6jfDv78CC5Jv2wp4
A new [mail] section configures an SMTP relay (SES-style STARTTLS or
implicit TLS; the password is environment-only via
DAILY_EPUB_MAIL__SMTP_PASS) and src/mail.rs wraps lettre in a small
plain-text Mailer built once at server start. Each stored access request
now emails mail.notify_to in a spawned task with the address, reason,
time, and a link to /dashboard/users. POST /request-access shares the
login endpoint's per-IP limiter (server.login_attempts per window).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QVPagF6jfDv78CC5Jv2wp4