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
Check · Review · Land · Live done — Landed and live in production.
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
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
mintreturns the token once, as aninvite_…value, withinviteLinkbuilding the/signup?invite=URL. The expiry is exactlydays × 86 400 000 msafter 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 duringmint,listandrevoke. Lines are captured at debug level. Theinvite.mintedpayload is exactly{ id, expiresAt }and theinvite.revokedpayload is exactly{ id }. - Revoke: a revoked link's
signUpreturnssignup_closedand makes no account, and revoking it again givesnot_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_foundfrom all three functions. So does an account with the admin flag whose kind isagent. None of these calls adds an event or changes the invite list. - Days:
0,-1,31,1.5,"7",NaN,Infinityand{}each getinvalid_daysand mint nothing.1and30are 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. 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.
Adds
test/invites-action.test.ts, the first test that importssrc/actions/invites.tsdirectly. Every check passed against the current code, sosrc/actions/invites.tsis unchanged: it had no fault.What the test covers:
mintreturns the token once, as aninvite_…value, withinviteLinkbuilding the/signup?invite=URL. The expiry is exactlydays × 86 400 000 msafter creation.list's output, or in any console line written duringmint,listandrevoke. Lines are captured at debug level. Theinvite.mintedpayload is exactly{ id, expiresAt }and theinvite.revokedpayload is exactly{ id }.signUpreturnssignup_closedand makes no account, and revoking it again givesnot_found. An open link from the same admin does sign someone up.not_foundfrom all three functions. So does an account with the admin flag whose kind isagent. None of these calls adds an event or changes the invite list.0,-1,31,1.5,"7",NaN,Infinityand{}each getinvalid_daysand mint nothing.1and30are accepted.To check that the test can actually fail, I briefly put the token into the
invite.mintedpayload: 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 --noEmitis clean.🤖 Generated with Claude Code
Closes #7513