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

A test proves invite links: only an admin mints, lists or revokes, and the token is in no event, log line or listing #7522

Merged opened this

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

Merged

Adds `test/invites-action.test.ts`, the first test that imports `src/actions/invites.ts` directly. Every check passed against the current code, so `src/actions/invites.ts` is unchanged: it had no fault.

shipped production is serving it deploy 9e284d9

opened this

Adds test/invites-action.test.ts, the first test that imports src/actions/invites.ts directly. Every check passed against the current code, so src/actions/invites.ts is unchanged: it had no fault.

What the test covers:

  • Mint: an admin's mint returns the token once, as an invite_… value, with inviteLink building the /signup?invite= URL. The expiry is exactly days × 86 400 000 ms after creation.
  • No leaks: the test looks for three things — the token, its SHA-256 hash and the token without its prefix. None appears in the events the bus appended for the mint and the revoke, in list's output, or in any console line written during mint, list and revoke. Lines are captured at debug level. The invite.minted payload is exactly { id, expiresAt } and the invite.revoked payload is exactly { id }.
  • Revoke: a revoked link's signUp returns signup_closed and makes no account, and revoking it again gives not_found. An open link from the same admin does sign someone up.
  • Who may call: a member, a guest (a non-member account) and an anonymous caller each get not_found from all three functions. So does an account with the admin flag whose kind is agent. None of these calls adds an event or changes the invite list.
  • Days: 0, -1, 31, 1.5, "7", NaN, Infinity and {} each get invalid_days and mint nothing. 1 and 30 are accepted.

To check that the test can actually fail, I briefly put the token into the invite.minted payload: the event-scan test failed, then I put the file back.

Not done: the HTTP, MCP and TUI routes into these functions already have their own suites, so this test stays at the action layer.

Try it: bun test test/invites-action.test.ts (4 pass, 52 expects). bun x tsc --noEmit is clean.

🤖 Generated with Claude Code

Closes #7513

commented

Adds test/invites-action.test.ts, the first test that imports src/actions/invites.ts directly. Every check passed against the current code, so src/actions/invites.ts is unchanged: it had no fault.

What the test covers:

  • Mint: an admin's mint returns the token once, as an invite_… value, with inviteLink building the /signup?invite= URL. The expiry is exactly days × 86 400 000 ms after creation.
  • No leaks: the test looks for three things — the token, its SHA-256 hash and the token without its prefix. None appears in the events the bus appended for the mint and the revoke, in list's output, or in any console line written during mint, list and revoke. Lines are captured at debug level. The invite.minted payload is exactly { id, expiresAt } and the invite.revoked payload is exactly { id }.
  • Revoke: a revoked link's signUp returns signup_closed and makes no account, and revoking it again gives not_found. An open link from the same admin does sign someone up.
  • Who may call: a member, a guest (a non-member account) and an anonymous caller each get not_found from all three functions. So does an account with the admin flag whose kind is agent. None of these calls adds an event or changes the invite list.
  • Days: 0, -1, 31, 1.5, "7", NaN, Infinity and {} each get invalid_days and mint nothing. 1 and 30 are accepted.

To check that the test can actually fail, I briefly put the token into the invite.minted payload: the event-scan test failed, then I put the file back.

Not done: the HTTP, MCP and TUI routes into these functions already have their own suites, so this test stays at the action layer.

Try it: bun test test/invites-action.test.ts (4 pass, 52 expects). bun x tsc --noEmit is clean.

🤖 Generated with Claude Code

Approved

Approved. A test-only pull: src/actions/invites.ts is unchanged and matches what the test asserts (admin and kind==user gate, parseDays, token absent from the event payloads). I did not run the new file: it is not in my checkout of the branch, so I read it from the diff. It covers the admin-only mint/list/revoke, the token-leak scan over events, listing and logs, the revoked link refusing signup, and the days bounds. Each has an assertion that would fail if the behaviour broke. No new dependency and no dead code. Two things I would do next: (1) add one test at the HTTP/MCP/tty layer that the token shows up only in the mint response and not in the listing page or the terminal view, so the doors are pinned as well as the action; (2) have the revoke test assert that a revoked link also fails when presented on the signup page (GET /signup?invite=), so the person-facing wording is covered.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs