Skip to content

Let teachers create a late student's account, and stop Join reporting failure for an account it made - #1487

Merged
amyjko merged 5 commits into
mainfrom
late-student-accounts
Nov 8, 2026
Merged

amyjko merged 5 commits into
mainfrom
late-student-accounts

Conversation

@amyjko

@amyjko amyjko commented Nov 8, 2026

Copy link
Copy Markdown
Collaborator

Context

A teacher partner reported two problems after making a password-sign-in class for her 6th graders:

  1. No way to add one more student account. Student accounts could only be made when a class was created. The class page's "email/username" field only adds an account that already exists, so she signed up as the student in a private window, then added that account.
  2. Join said it failed when it had made the account. She saw "We couldn't make the account", and then, on retry, "Someone claimed that username just now".

Cause of (2): joinAccount's password path created the account and assigned the username, then returned a custom sign-in token. Any failure after the account existed fell into a catch that only freed the name reservation. That does nothing once the name is assigned, so the account stayed and the client was told failed. The likeliest failing step is createCustomToken, which in deployed functions needs the signBlob IAM permission; nothing in the repo grants it, and the emulator doesn't need it. Cloud Logging isn't checked yet; the line to look for is "Could not create a password account".

Changes

Join

  • joinAccount rolls back fully on failure: it deletes the account and unassigns the name. It also returns no token.
  • The Join page signs in with the password it already holds. Before saying "taken" or "failed", it tries that same sign-in first, so a retry after any partial success lands in the account.
  • If the account exists but sign-in fails, a new message says so, instead of "couldn't make the account".
  • "Taken" is shown once, by the username field. The duplicate notice and its string are removed.

Class page

  • New addClassStudent callable (App Check, noProxy). It makes one account in an existing password class and adds it to the class and its galleries.
  • It refuses anyone who isn't a teacher of that class, email classes, and classes already at 50 students. That check is the pure classStudentRefusal, which has unit tests.
  • createClass's account creation (reserve, create, assign, roll back) moved to mintAccounts.ts, which both callables use. createClass's behavior is unchanged.
  • The page now shows two explained ways to add a student: "Add an existing account" (the old field, moved out of the table) and "Create a new account" (password classes only). New credentials are shown once to write down.
  • Labels on this page are lowercased to match the site.

locales-fix bug (separate commit)

  • removeExtraKeys pruned script from ur-Latn-PK and nan-Latn-TW, because en-US declares none.
  • That renamed them to ur-PK and nan-TW, deleted their manifests, and overwrote en-US.webmanifest with Roman Urdu set right to left.
  • script is now exempt, like terms and glossary forms. A new test fails without the fix.

New strings are translated into all 36 locales. Two import-graph byte budgets moved by 0.01MB for the new en-US strings.

Related issues

  • None filed; reported directly by a teacher partner.

Verification

  • npm run check:now, npm run test:run, npm run test:sweep and npm run locales pass. functions builds.
  • New e2e test in join.spec.ts: join, join again with the same credentials and land on the profile, then try a different password and see "taken". It passes against the emulator.
  • Screens captured against the emulator in both color schemes and at phone width, and reviewed.
  • Deployed to test.wordplay.dev:
    • A password join created the account and signed in, with no custom token.
    • A different password on an existing name showed "taken" on the field only.
    • The same-credentials retry couldn't be checked headlessly: real App Check refused the headless browser.
  • Not yet done:
    • Teacher flow on dev (needs a teacher account there).
    • Screen reader pass.
    • Keyboard-only pass.

Checklist

  • Same-credentials Join retry checked in a real browser on test.wordplay.dev
  • Teacher creates a student on dev, then signs in as them
  • VoiceOver and keyboard pass of the class page's two sections

🤖 Generated with Claude Code

amyjko and others added 5 commits November 7, 2026 16:33
The changelog skill said version bumps belonged to the release process, so
#1486 added a 0.41.0 section and left package.json at 0.40.1, and the bump
then needed a second commit and a second full CI run.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
locales-fix removes every key en-US lacks, and en-US declares no `script`, so
each run renamed ur-Latn-PK to ur-PK and nan-Latn-TW to nan-TW: their manifests
were deleted and en-US's was overwritten with Roman Urdu set right to left.
`script` now joins `terms` and glossary `forms` as a key a locale chooses for
itself.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…g failure for an account it made

A teacher with a password class had no way to make an account for a student
who arrived later, short of signing up as them in a private window. The class
page now has two explained ways to add a student: add an existing account, or
create a new one (password classes only), through a new `addClassStudent`
callable that shares `mintAccounts` with `createClass`.

The same teacher saw Join say "We couldn't make the account" for an account it
had made, then "taken" on retry. joinAccount's password path returned a custom
token after the account existed, and a failure there left the account behind
while reporting failure. It now rolls back fully on failure and returns no
token: the Join page signs in with the password it holds, and tries that
sign-in before saying a name is taken. The duplicate "taken" notice is gone.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…anslation

Lowercasing "Delete this class" flagged ten translations in scripts with no
letter case (Japanese, Chinese, Hindi, ...), which were already right; marking
them would buy re-translations that write the same bytes, so the gate could
never clear.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@amyjko
amyjko merged commit 3d5dcec into main Nov 8, 2026
17 checks passed
@amyjko
amyjko deleted the late-student-accounts branch November 8, 2026 02:09
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