fix(auth): reopen a pre-dated approval instead of auto-granting it
Replaces the activation added in ea931dc, which round 2 of the review showed was
a real weakening: on a no-SMTP instance it made a standing whitelist entry a
bearer grant — the first anonymous party to register an approved-but-unclaimed
address got an immediately usable account under that identity, with no
attestation, no admin action and no signal anywhere. The verify-time activation
had the same shape one step removed, and neither site ran the SEC-10 preset-
password guard or left an audit trail.
Keep a human in the loop instead. An approval granted before any account existed
was a decision about the ADDRESS, so registration reopens the invite
(upsert_pending_invite gains revive_approved, used only by the register worker).
The request lands in the Access-requests queue, approving it runs
_activate_user_by_email — and with it revoke_preset_password_if_unverified — and
the account activates. One mechanism, already audited, no new grant path, and
the "awaiting admin approval" copy is honest again.
The explicit commit from the previous commit still matters: with an invite
already pending, upsert returns without committing and _issue_token is gated on
SMTP, so a no-SMTP registration was still being rolled back.
Also from round 2: gate the admin notice on a fresh decision (matching the two
other upsert callers) so a retry no longer re-pings every admin, and reset the
module-level rate limiters between tests — the suite pooled every login into one
300s window and was two logins short of failing an unrelated test with a 429.
This commit is contained in:
@@ -18,13 +18,15 @@ export const RELEASE_NOTES: ReleaseEntry[] = [
|
||||
version: "0.78.5",
|
||||
date: "2026-09-01",
|
||||
summary:
|
||||
"Signing up with an address the admin had already approved now works end to end — the account is created, and confirming your email lets you straight in instead of parking you behind an approval that already happened.",
|
||||
"Two ways a sign-up could quietly go nowhere are fixed: on an instance that sends no email the account was discarded outright, and an address the admin had whitelisted in advance landed in a request no admin screen ever showed.",
|
||||
fixes: [
|
||||
"Signing up with an address an admin had already approved now actually creates the account. Before, the sign-up reported success and the account was discarded on the spot, so the person could neither sign in nor ask for access again — they simply had no account at all.",
|
||||
"Such an account no longer waits for an approval it already has. Confirming the emailed link now activates it straight away, and on an instance that sends no email the admin's whitelist alone is enough — previously the sign-up landed in a state the Access-requests screen never showed, because the request had already been decided.",
|
||||
"On an instance that sends no email, signing up with an address that already had a request on file created nothing at all. The sign-up reported success, no account existed, and trying again did the same — so the person could neither sign in nor get back into the queue.",
|
||||
"Whitelisting someone before they sign up now works the way it looks like it should. Their sign-up reopens the request so it appears under Users → Access requests, where approving it lets them in; previously it landed against a decision already made, which the queue does not list and the Approve action refuses, leaving nobody able to complete it.",
|
||||
"Retrying a sign-up while a request is already pending no longer emails every admin again.",
|
||||
],
|
||||
chores: [
|
||||
"Registration commits the new account explicitly: for an already-approved email, upsert_pending_invite() returns without committing and the only other commit on that path is gated on working SMTP, so with mail unavailable the flushed user row was rolled back when the background task's session closed. Activation is now derived from is_allowed() at the moment ownership is attested — at email verification, or at registration when the instance has no email to verify with. Covered by one regression test plus guards for every other branch of the worker, and the first end-to-end tests of the /auth/register route itself.",
|
||||
"Registration commits the new account explicitly — upsert_pending_invite() commits only when it actually writes an invite row, and the only other commit on that path is gated on working SMTP, so with mail unavailable the flushed user row was rolled back when the background task's session closed. An approval that predates the account now reopens the invite instead of being treated as a standing grant, which keeps a human (and with them the SEC-10 preset-password guard in _activate_user_by_email) between a whitelisted address and whoever registers it. The admin notice is gated on a fresh decision, matching the other two callers.",
|
||||
"Two regression tests (no-SMTP with a request already pending, and the reopen-then-approve loop) plus guards for the unknown-email, previously-denied and SMTP-on branches, the first end-to-end tests of the /auth/register route and its allow_registration gate, and an autouse fixture that resets the module-level rate limiters between tests so their windows stop pooling across the suite.",
|
||||
"Operator note: an incomplete SMTP setting makes Siftlode skip every message silently by design. If your instance has never delivered mail, check Configuration → Email and use “Send test email”.",
|
||||
],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user