Skip to content

Add password recovery to BackToSchool sign-in - #181

Merged
ralyodio merged 1 commit into
mainfrom
fix/backtoschool-password-reset
Sep 13, 2026
Merged

ralyodio merged 1 commit into
mainfrom
fix/backtoschool-password-reset

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

BackToSchool users had no way to recover a forgotten password. Add “Forgot password?” to sign-in and branded request/new-password pages backed by durable, expiring, single-use recovery links sent through the configured Resend sender.

Recovery atomically changes the password and revokes existing browser, CLI, and legacy JWT sessions. Requests use generic responses, bounded payloads, and IP/address throttles; tokens are hashed in Postgres and carried in URL fragments.

Validation: real Postgres recovery tests cover replacement, expiry, simultaneous consumption, restart, invalid passwords, and session revocation. Playwright verifies the complete mobile browser flow, same-tab email links, new login, reuse rejection, and preserved focus. Typechecks and builds pass.

@ralyodio
ralyodio merged commit 5d3e685 into main Sep 13, 2026
3 checks passed
ralyodio added a commit that referenced this pull request Sep 16, 2026
… already serves (#216)

PR #181 built password recovery (hashed single-use links, Resend mail,
session revocation) and put a "Forgot password?" link on the BackToSchool
sign-in, but nixamp.com's own account panel never linked to it. A member
whose password no longer matched read "that email and password do not
match an account" with nowhere to go, although /reset-password was live
on the same origin.

The link sits next to "Create one", hides while creating an account, and
opens in its own tab inside a classroom embed so the host page's iframe
is not navigated away.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
ralyodio added a commit that referenced this pull request Sep 16, 2026
… card said once (#217)

* Account panel: a "Forgot password?" link to the reset page nixamp.com already serves

PR #181 built password recovery (hashed single-use links, Resend mail,
session revocation) and put a "Forgot password?" link on the BackToSchool
sign-in, but nixamp.com's own account panel never linked to it. A member
whose password no longer matched read "that email and password do not
match an account" with nowhere to go, although /reset-password was live
on the same origin.

The link sits next to "Create one", hides while creating an account, and
opens in its own tab inside a classroom embed so the host page's iframe
is not navigated away.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* BackToSchool is its own account; nixamp is an optional backend; the host card is said once

backtoschool.help runs in the nixamp process over the same users table, and
its sign-in dialog said so ("your BackToSchool identity is your NixAmp
account"), which filed the nixamp password under the school in a password
manager and made nixamp a thing every teacher had to have. Neither is wanted.

The account card, shared by both apps: src/profiles.ts keeps a name, a
homepage, a line, a linked avatar and an uploaded photo (bytes in Postgres,
type sniffed, served with an etag) against the account. An OpenProfile.md
fills it in one move and its address is remembered on the persona. A class
made without host fields takes the card, so the school form no longer asks
for a name and photo every time; it shows the card and points at settings.

Connect nixamp, optional: the school is a built-in public OAuth 2.1 client
of nixamp.com (PKCE, consent page, refresh rotation, a new `streams`
scope). src/nixamp-link.ts keeps the tokens against the school account and
refreshes them; src/nixamp-link-api.ts is connect, callback, connection and
streams. What it buys is a pick list of the servers you run and what is live
on them, instead of a link pasted from a terminal. Withdrawing it on either
side ends it on both.

The school gets a settings dialog (profile, photo, OpenProfile, the
connection, sign out) and loses every mention of nixamp on the way in.
nixamp.com gets "Teach this on backtoschool.help": one click makes the
class from the live room and the card, starts it, and opens it.

Tests: unit tests for the card parser, the link module and the streams
reader; two real-Postgres runs (card round trip with a photo, an import and
a class; connect through consent to callback, streams and disconnect over
one server that is both sides). The server's catch-all now logs under
NIXAMP_DEBUG, which is how the second of those was made to pass.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant