Public: anyone can read this; nobody can change it.

An invite link opens signup once while signup is invite: the form, the passkey door and the API take its token, and the account and the invite's use are one write #49

Merged opened this view on origin

Check · Review · Land done · Live — Landed; nothing deploys from this branch, so this is the end of its path.

Merged

**Depends on #43.** This branch is on top of #43 (`createUser` takes a required `origin`). Its first commit is #43's commit. Review only the top commit, c146f52b. Merge #43 first.

shipped merged

opened this view on origin

Depends on #43. This branch is on top of #43 (createUser takes a required origin). Its first commit is #43's commit. Review only the top commit, c146f52b. Merge #43 first.

Problem. Invite links did nothing. The admin can make, list and revoke them (#2353, #2377, #2361). But signup never read an invite. In invite mode, /signup?invite=… said "Signup is closed". used_at and used_by were never written.

Root cause. The signup gate had no invite input. newAccountsClosed treated invite the same as closed ("until #1143").

Fix.

  • The signup and passkey origins of createUser can carry an invite token beside their SignupSlot. parent and edge cannot. The gate in createUser lets a stranger in while signup is invite only with an open invite. The invite is not used, not revoked and not expired. The forge finds it by its sha256 hash, so no code compares the secret.
  • redeemInvite is one conditional UPDATE ... WHERE token_hash = ? AND used_at IS NULL AND revoked_at IS NULL AND expires_at > now. It runs in the same transaction as the user INSERT. Two sign-ups with one link make one account. A taken name gives the invite back. A passkey sign-up whose key is refused also gives it back (discardFreshUser).
  • Doors: the form and the passkey door read ?invite= from their own URL. The form action keeps it. POST /api/v1/users reads invite from the body. The sign-up window still applies. In open mode the forge does not use an invite. In closed mode an invite opens nothing.
  • README and settings/signup.ts say this. The terminal has no invite input.

Test. test/invite-redeem.test.ts: the form, the API (two requests at the same time) and the passkey door each use a link one time. Used, revoked, expired and unknown links make nothing. A taken name does not use the link. In closed mode nothing is made. In open mode the link is not used. On #43: 4 of 7 fail (the 3 guard tests pass). With the fix: 7 of 7 pass.

Validate (fast). Result: flaky, no new failure. contain.test.ts is baseline. tui-sentinel, returns and og-png failed one time under box load. They are not red on main 833e7f51, and they pass when run alone. tsc passes.

After this lands, the MCP signup tool text in #46 ("invite links are not redeemed yet") must change.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs