Commit Graph
2 Commits
Author SHA1 Message Date
jwinterm 586d29efe7 chore: cargo fmt with current stable rustfmt (repo-wide)
The repo pins channel=stable (no rustfmt version), so CI now pulls
rustfmt 1.9.0, which reformats code last touched by an older rustfmt.
main itself failed `cargo fmt --check` under the current toolchain;
this is a formatting-only sweep across 24 files to make the fmt gate
green. No behavior change; tests + clippy -D warnings still pass.
2026-07-19 03:44:47 -04:00
jwinterm b32b8a9059 security(auth): make gated registration fully atomic (F3/F4 fast-follow)
The prior fixes closed the common cases with pre-checks; this closes the
residual races by consuming the single-use gate token(s) AND creating the
user AND persisting keys in ONE transaction, so a failure never burns a
token without an account.

- New Database::create_user_consuming_gates: claims the invite + consumes
  the payment invoice + inserts the user + upserts keys inside a tx;
  rolls the whole thing back on a username collision (mapped to 409) or a
  raced/already-spent token.
- New plan_gate_consume: resolves which tokens to spend WITHOUT consuming
  (the payment settled-check stays non-consuming), so `all`-mode verifies
  the payment is settled before anything is spent, then both tokens are
  consumed atomically at creation.
- extension_register + nostr_register route NEW users through the atomic
  path (returning users keep the ordinary backfill path); the npub F2
  fail-closed check runs before the tx. Removed the now-dead
  enforce_method_gates / enforce_invite / enforce_payment.
- tests/registration_atomicity.rs proves the rollback: a username
  collision keeps the invite; an already-spent payment keeps the invite.

Validated against Postgres: full suite 286 passed / 0 failed.
2026-07-06 05:58:04 -04:00