Homework

Homework — expire a token, see the slog bug

Make it yours.

  1. Expire a token by hand. Request a reset, but before opening the link run UPDATE password_reset_tokens SET expires_at = now() - interval '1 hour';. Open the link → the invalid page. GetValidPasswordReset's expires_at > now() clause did its job. Reset tokens don't live forever — a leaked link is useless after an hour.

  2. See the slog bug for yourself. In ConsoleSender.Send, temporarily replace the fmt.Fprintf loop with s.log.Info("email", "body", msg.Text) (you'd need to pass a logger in). Trigger a reset and look at the log: the whole email — link and all — is one line with literal \n sequences, and the URL is unclickable and hard to copy. That's why the console sender writes to stdout directly. Revert it.

  3. Wire up real email (optional). Get a free Resend API key, then run EMAIL_SENDER=resend RESEND_API_KEY=... go run ./cmd/signflow. The startup log switches to "using Resend sender", and a reset actually emails you. Same Sender interface, a different implementation — the handler code didn't change at all. Switch back to console (unset the vars) and the flow still works, key-free.

Where this is going — the documents phase. Auth is complete: register, login, logout, password reset, sessions, CSRF — all real, all tested. SignFlow now knows who every request is. The next phase gives those users something to do: upload a document. You'll build a storage.Store interface (the same dev-impl/prod-impl seam as email), stream an uploaded file to disk while hashing it with SHA-256 in the same pass, and build an owner-scoped dashboard where a foreign document id returns 404, not 403. The hash you capture on upload is what lesson 11's signatures will pin — and what the tamper-detection demo will expose.