document password reset flow in CLAUDE.md and reset-password page

This commit is contained in:
Davide Scaini
2026-04-14 22:34:15 +02:00
parent 8fbd9a95e8
commit 9419bd0c20
2 changed files with 19 additions and 1 deletions
+17
View File
@@ -235,6 +235,23 @@ Key facts:
`fetch('/api/me')` auth wall; `/login/` and `/register/` have `public={true}` to skip it
- Incremental rebuild: `POST /api/activity/{id}` triggers `bincio render --handle {user}`
as a fire-and-forget subprocess (only if `--site-dir` was passed to `bincio serve`)
### Password reset (no email — out-of-band code)
There is no email infrastructure. Password resets work via admin-generated one-time codes:
1. **Admin** opens `/admin/` → clicks **"Reset pwd"** next to the user → a code appears
inline (monospace, click to copy). Valid for **24 hours**, tied to that handle.
2. **Admin** sends the code out-of-band (Signal, Telegram, etc.).
3. **User** goes to `/reset-password/`, enters handle + code + new password → done.
API:
- `POST /api/admin/users/{handle}/reset-password-code` (admin) → `{code, expires_in_hours: 24}`
- `POST /api/auth/reset-password` (public) → body `{handle, code, password}`
DB: `reset_codes` table `(code, handle, created_by, created_at, expires_at, used_at)`.
Generating a new code invalidates any prior unused code for the same handle.
Used codes are kept for audit. `change_password()` in `db.py` updates the bcrypt hash.
- Write API in `bincio serve` delegates to `bincio.edit.server._apply_sidecar_edit`; the
Strava sync delegates to `bincio.edit.server.strava_sync` with a temporary data_dir swap