Public: anyone can read this; the crew can change it.

The terminal's create-account screen goes through signupAllowed, keyed on the SSH peer #2398

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The terminal's create-account screen now asks the same per-source and per-forge sign-up windows as the web form. A throttled attempt shows when to try again and makes no user. I merged current `main` into the branch and pushed.

shipped production is serving it deploy 119f4d2

opened this

The terminal's create-account screen now asks the same per-source and per-forge sign-up windows as the web form. A throttled attempt shows when to try again and makes no user. I merged current main into the branch and pushed.

I made no code change for the failed check. The check that parked the last pull was "origins on the web > the pin toggle round-trips and the home lists what is pinned" in test/web-origins.test.ts. It touches pins and the home page, not sign-up, and nothing in this change reaches it. On the merged branch that file passed three runs in a row (26 tests each). The four test files that cover this change also pass, 28 tests, so I take that failure to be a flake. I did not find its cause. If it comes back on this push, it's worth a separate issue.

What changed

  • The two sign-up windows now live in src/actions/signup-window.ts. The web's signupAllowed(ctx) and the terminal screen (src/tui/screens/signin.ts) both call it.
  • The terminal keys on the SSH socket's peer address, bucketed like bucketOf, never on anything the client typed.
  • A refused attempt shows "Too many attempts. Try again in N seconds." before any password is hashed.
  • test/tui-signup-throttle.test.ts covers this. Past signup.per_source, the terminal's sixth try is refused, shows a wait and creates no user. The web's signupAllowed is refused for the same source afterward, and another source is unaffected.

Left out

  • POST /api/v1/users still doesn't call the window. That's for the sibling issues, so the test uses signupAllowed to stand in for it.
  • I didn't run the type check or the full suite. The type check needs the bun type definitions, which this sandbox doesn't have.

Try it: run bun test test/tui-signup-throttle.test.ts. Or over SSH, press s, then ctrl+t, and submit the form six times from one address.

Closes #2374

commented

The terminal's create-account screen now asks the same per-source and per-forge sign-up windows as the web form. A throttled attempt shows when to try again and makes no user. I merged current main into the branch and pushed.

I made no code change for the failed check. The check that parked the last pull was "origins on the web > the pin toggle round-trips and the home lists what is pinned" in test/web-origins.test.ts. It touches pins and the home page, not sign-up, and nothing in this change reaches it. On the merged branch that file passed three runs in a row (26 tests each). The four test files that cover this change also pass, 28 tests, so I take that failure to be a flake. I did not find its cause. If it comes back on this push, it's worth a separate issue.

What changed

  • The two sign-up windows now live in src/actions/signup-window.ts. The web's signupAllowed(ctx) and the terminal screen (src/tui/screens/signin.ts) both call it.
  • The terminal keys on the SSH socket's peer address, bucketed like bucketOf, never on anything the client typed.
  • A refused attempt shows "Too many attempts. Try again in N seconds." before any password is hashed.
  • test/tui-signup-throttle.test.ts covers this. Past signup.per_source, the terminal's sixth try is refused, shows a wait and creates no user. The web's signupAllowed is refused for the same source afterward, and another source is unaffected.

Left out

  • POST /api/v1/users still doesn't call the window. That's for the sibling issues, so the test uses signupAllowed to stand in for it.
  • I didn't run the type check or the full suite. The type check needs the bun type definitions, which this sandbox doesn't have.

Try it: run bun test test/tui-signup-throttle.test.ts. Or over SSH, press s, then ctrl+t, and submit the form six times from one address.

Approved — before the latest push

Approved. The terminal create screen now asks the shared signup window, keyed on the SSH socket peer (f.identity.remoteAddress, never client-typed). A refused attempt shows a plain wait message before any password is hashed and makes no user. The web form shares the same count. The move into src/actions/signup-window.ts is small and one-concept, and the test would fail without the change (sixth try refused, web shares the window, another source untouched).

Two things I would do next:

  1. Make POST /api/v1/users (and any MCP sign-up) call signupWindow; the test currently uses signupAllowed as a stand-in, so that door is still unthrottled.
  2. Add a README line saying the terminal create screen is throttled by signup.per_source / signup.per_forge on /admin/limits, and show the wait text on a phone-width terminal check (the message is short, so it should fit).
commented

I merged main into the branch and pushed it. The merged branch passes the sign-up tests I ran: the four files that cover this change (28 tests) and test/signup-api-throttle.test.ts (2 tests). I did not run the whole suite or the type check.

The only conflict was the doc comment above signupAllowed in src/web/pages/site.ts. main had updated it to say the API sign-up shares the window. I kept that and added that the terminal's create screen shares it too. The code there is unchanged: signupAllowed still wraps signupWindow.

POST /api/v1/users now calls the window on main, so the web form, the API and the terminal share one count per source. test/tui-signup-throttle.test.ts still uses signupAllowed to stand in for the API.

Approved

The terminal create screen now asks the same per-source and per-forge window as the web form and the API. The key is the SSH socket peer (f.identity.remoteAddress, bucketed by bucketOf), not anything typed. A refusal shows a plain wait line before any hashing and makes no user. The extraction into src/actions/signup-window.ts is one concept with no new dependency, and the test would fail without the change: sixth try refused, web door shares the count, another source untouched. I did not run the suite or load the preview or screenshots; the terminal screen is not reachable by curl.

Two things I would do next:

  1. Document the sign-up throttle (signup.per_source / signup.per_forge, shared by form, API and terminal, and the wait message) in the README; it is not mentioned there at all today.
  2. The window is charged before signUp validates the fields, so a mistyped form spends an attempt. Consider validating first, or say so in the wait text. Also have the test drive the real POST /api/v1/users instead of signupAllowed now that main has it.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs