Skip to content

BackToSchool is its own account, nixamp an optional backend, the host card said once - #217

Merged
ralyodio merged 2 commits into
mainfrom
backtoschool-own-account
Sep 16, 2026
Merged

ralyodio merged 2 commits into
mainfrom
backtoschool-own-account

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Why

backtoschool.help runs in the nixamp process over the same users table, and its sign-in dialog said "Your BackToSchool identity is your NixAmp account". That filed the nixamp password under the school in Bitwarden, and made nixamp something every teacher had to have. Anthony's ruling: nixamp login from BackToSchool is optional; nobody needs nixamp except as the streaming backend.

Includes the one-line "Forgot password?" commit from #216 (branch cut from it).

What

  • Account card, shared by both apps (src/profiles.ts, table nixamp_profiles): name, homepage, a line, a linked avatar and an uploaded photo kept as bytes in Postgres (type sniffed from the file, served at GET /api/v1/profiles/<id>/photo with an etag and 304). Routes GET/PUT /api/v1/me/profile, PUT/DELETE /api/v1/me/profile/photo, POST /api/v1/me/profile/import (fills the card from an OpenProfile.md and remembers the URL on the persona, so the phone voice reads the same file).
  • A class takes the card: POST /api/v1/events fills hostName/homepageUrl/avatarUrl from the profile when blank. The school form no longer asks for them; it shows the card with "Edit in settings". Editing a class never sends those keys, so nothing is wiped.
  • Connect nixamp, optional (src/nixamp-link.ts, src/nixamp-link-api.ts): the school is a built-in public OAuth 2.1 client of nixamp.com (PKCE, consent, refresh rotation, new streams scope; NIXAMP_OAUTH_BACKTOSCHOOL=off removes it). Tokens kept in nixamp_links against the school account, refreshed when stale, dropped when nixamp.com refuses a refresh. GET /api/v1/nixamp/streams lists the servers you run and what is live on them, as links a classroom accepts. Disconnect withdraws the grant on nixamp.com too.
  • School settings dialog: profile, photo upload, OpenProfile fill, the nixamp connection, sign out. Every mention of nixamp on the way in is gone. The class form gets a "Your nixamp streams" picker when connected.
  • nixamp.com one click: "Teach this on backtoschool.help" beside the copy-link button. Makes the class from the live room and the card, starts it, opens backtoschool.help/live/<slug>.
  • Server catch-all logs the exception under NIXAMP_DEBUG (a 500 in a test was invisible without it).

Verification

  • bun run typecheck (server, web, school) clean; bun test test web/test 851 pass, 0 fail, run with NIXAMP_TEST_DATABASE_URL set so the two real-Postgres tests ran: card round trip with a photo, an import and a class inheriting it; connect → consent → callback → streams → disconnect over one server acting as both sides.
  • bun run build for web and school pass; both bundles carry the new markup.
  • Not verified live: needs the deploy. After merge, check https://backtoschool.help/api/v1/nixamp/connection answers 401 when signed out, and that nixamp.com/.well-known/oauth-authorization-server lists streams.

Not in this PR

  • Anthony's own OpenProfile exists only locally (myna profile); nothing serves it at profullstack.com yet, so the import has nowhere to read from until it is published.
  • Accounts still share one users table. The product framing is separate; the storage is not.

🤖 Generated with Claude Code

ralyodio and others added 2 commits September 16, 2026 14:08
… 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>
…ost 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>
@ralyodio
ralyodio merged commit 81cfc9c into main Sep 16, 2026
4 checks passed
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