Password Reset
Overview
A user who has forgotten their password cannot reset it themselves (no self-service flow yet). An admin must reset it via the CLI. The reset updates all three credential stores atomically and — in production — refreshes the running server’s in-memory Anki sync state without a restart.
Production (Docker on DigitalOcean)
docker exec flashcard-flow-server-1 \ flashcard-flow-server reset-password <email> '<new-password>'Expected output:
Password reset for '<username>' (<email>)In-memory credentials refreshed — Anki Desktop sync works immediately.The user can immediately:
- Log in to the web UI with the new password
- Sync from Anki Desktop with the new password (no server restart needed)
Dev / Local (bare-metal)
The server must be running with DATABASE_URL set (i.e. loaded from .env) for the no-restart path to work. If it is:
./target/release/flashcard-flow-server reset-password <email> '<new-password>'If the server was started without DATABASE_URL (SQLite mode), the CLI will print:
Warning: server returned 404 Not Found — Anki Desktop sync will work after next restart.This means the DB reset succeeded (web login works immediately) but the in-memory refresh failed due to a DB mismatch. Fix: restart the server.
pkill -f flashcard-flow-servercargo run --release -p flashcard-flow-server &How it works
The CLI subcommand does two things:
-
DB update — recomputes and writes all three credential hashes for the user:
password_hash(Argon2) — used by web loginhkey(SHA-1 ofusername:password) — used by Anki Desktop sync (in-memory)pbkdf2_hash(PBKDF2) — used to restore Anki sync state after a server restart
-
In-memory refresh — calls
POST /api/admin/refresh-useron the running server (authenticated withJWT_SECRET). The server reads the new hashes from the DB and pushes them into the sync server’s in-memory table, evicting the stale entry. This means Anki Desktop sync works immediately with the new password.
If the server is unreachable or returns an error, the CLI prints a warning and the DB update still stands — web login works immediately, Anki Desktop sync works after the next server restart.
Security notes
- The admin endpoint (
POST /api/admin/refresh-user) is authenticated withJWT_SECRETas a bearer token. Anyone withJWT_SECRETcan call it, so keep that secret secure. - The new password is passed as a CLI argument, which is visible in shell history. After use, consider clearing history (
history -d <n>) or advising the user to change their password immediately after receiving it. - There is no rate limiting on admin-initiated resets — only human access controls.
Future: self-service reset
When self-service “forgot password” is implemented, it will send a time-limited reset link via Resend. The same change_password / in-memory refresh logic will be reused under the hood.