Deploy to S3 / deploy (push) Successful in 23sDetails
Every business action now lands in a new append-only audit_log table with the
verified signed-in identity: logins, closing create/delete/reopen, file upload
(incl. replacements) and delete, processing runs, export generation and
downloads. Rows carry no FK so history survives a closing's deletion.
Admins (new users.is_admin flag, granted via `manage.py set-admin <username>`)
can read it at /api/audit and in a new Audit Log page in the sidebar; everyone
else gets 403 and no nav entry. login/me responses now carry is_admin.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New flow (active once AR_SMTP_* is configured; hidden otherwise):
- POST /api/auth/request-code emails a code to the account address
(usernames are emails). HMAC-stored, 10-min expiry, single-use,
5-attempt lockout, 60s resend throttle, no user enumeration.
- POST /api/auth/reset-password sets the new password with the code —
works signed-in (Settings) and from the login screen (Forgot
password?), so users can self-recover without the admin.
- Mailer: stdlib smtplib (STARTTLS/SSL, certifi CA bundle); SMTP
settings documented in .env templates.
- Settings switches to the code flow when email is on; the
current-password form remains the fallback.
Note: CRAI_Report was checked as the reference for code-sending — it
has no email/OTP functionality, so this is a fresh implementation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>