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

A test pins account recovery links: `spendRecovery` works once and never after expiry #6808

Merged opened this

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

Merged

I added `test/verify-recovery.test.ts`, which pins account recovery links. Its 7 tests and `tsc --noEmit` pass. It found no bug, so `src/core/verify.ts` is unchanged.

shipped production is serving it deploy fc82d1a

opened this

I added test/verify-recovery.test.ts, which pins account recovery links. Its 7 tests and tsc --noEmit pass. It found no bug, so src/core/verify.ts is unchanged.

What the tests prove, passing now in each time:

  • Owner before spend: a recovery token names its account through recoveryOwner, and reading it spends nothing.
  • Spend once: spendRecovery returns the account the first time and undefined the second.
  • Expiry: a spend at exactly RECOVERY_TTL_MS and one after it both return undefined. One millisecond before expiry still works.
  • Unknown tokens: an unknown or empty token returns undefined from both spendRecovery and recoveryOwner.
  • Other accounts: spending one account's link leaves another account's link working.
  • Verification links: a pending verification link from issueLink opens no recovery, and issueRecovery returns undefined for an unproven account.
  • markUnproven: it writes an unproven row for an account that has none, and it leaves a proven account's row alone. No other account's row changes.

Left out: the issue says issueLink mints the recovery token, but recovery tokens come from issueRecovery. issueLink mints the verification link, so I used it only for the check that a verification link opens no recovery. I did not test issueLink's resend window or daily cap.

Try it: bun test test/verify-recovery.test.ts

Closes #6790

commented

I added test/verify-recovery.test.ts, which pins account recovery links. Its 7 tests and tsc --noEmit pass. It found no bug, so src/core/verify.ts is unchanged.

What the tests prove, passing now in each time:

  • Owner before spend: a recovery token names its account through recoveryOwner, and reading it spends nothing.
  • Spend once: spendRecovery returns the account the first time and undefined the second.
  • Expiry: a spend at exactly RECOVERY_TTL_MS and one after it both return undefined. One millisecond before expiry still works.
  • Unknown tokens: an unknown or empty token returns undefined from both spendRecovery and recoveryOwner.
  • Other accounts: spending one account's link leaves another account's link working.
  • Verification links: a pending verification link from issueLink opens no recovery, and issueRecovery returns undefined for an unproven account.
  • markUnproven: it writes an unproven row for an account that has none, and it leaves a proven account's row alone. No other account's row changes.

Left out: the issue says issueLink mints the recovery token, but recovery tokens come from issueRecovery. issueLink mints the verification link, so I used it only for the check that a verification link opens no recovery. I did not test issueLink's resend window or daily cap.

Try it: bun test test/verify-recovery.test.ts

Approved

Test-only pull; it matches src/core/verify.ts. Expiry is pinned at TTL-1, TTL and TTL+1. Spend-once, read-does-not-spend, unknown/empty tokens, cross-account isolation, and a pending verification link opening no recovery are all covered. markUnproven is covered for writing a missing row and leaving a proven row alone. No UI, tty or dependency is involved, so the both-doors and security items do not apply. I did not run the file: the review checkout is at the base and does not contain it. Two things I would do next: (1) add a case that issueRecovery overwritten by a second issueRecovery kills the first token (one slot per account); (2) add a case that markVerified or resetVerification clears an outstanding recovery token.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs