fix(auth): the reading of the fixes' nits

- The background delivery of session notices logs (its failure warning
  was never written: its session had logging off).
- A sign-in's and a phrase proof's begin check the address's ceiling
  after the network's limits, which hold a flood back before it costs
  the ceiling's queries (one an UPDATE, pushing resets).
- The module's README lists every pruning step a host schedules
  (forgetLapsedResets, deliverSessionNotices) and which mode each is for.

(The check of a member's clock ahead, which counted the register's
processing time as skew, went with C1's fix.)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-21 16:08:01 +02:00
commit 8c910f8cfc
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
2 changed files with 21 additions and 12 deletions

View file

@ -692,7 +692,6 @@ Future<PasswordChallenge> beginPasswordSignIn(
final pod = session.serverpod;
final keys = requirePasswordKeys(pod);
final hash = _hashOfTyped(pod, address);
await _refuseAddressProvingTooOften(session, hash);
// The address first: a sign-in it can't begin takes nothing of the
// network's.
if (!await _beginsPerAddressAndNetwork.tryRecordAttempt(
@ -702,6 +701,9 @@ Future<PasswordChallenge> beginPasswordSignIn(
!await _beginsPerNetwork.tryRecordAttempt(session, key: network)) {
throw refusedFor(PasswordRefusal.tooManyAttempts);
}
// The address's ceiling after the network's limits, which hold a flood
// back before it costs the ceiling's queries (the reading of the fixes).
await _refuseAddressProvingTooOften(session, hash);
// Both, always: an account's sign-in takes as long as a decoy's.
final decoy = _decoyAccount(keys.decoyKey, hash);
final password = await _passwordWithAddress(session, hash);
@ -1333,7 +1335,6 @@ Future<KeyProofChallenge> beginKeyProof(
final pod = session.serverpod;
final keys = requirePasswordKeys(pod);
final hash = _hashOfTyped(pod, address);
await _refuseAddressProvingTooOften(session, hash);
if (!await _keyProofsPerAddressAndNetwork.tryRecordAttempt(
session,
key: '$hash|$network',
@ -1341,6 +1342,7 @@ Future<KeyProofChallenge> beginKeyProof(
!await _beginsPerNetwork.tryRecordAttempt(session, key: network)) {
throw refusedFor(PasswordRefusal.tooManyAttempts);
}
await _refuseAddressProvingTooOften(session, hash);
final decoy = await _decoyKeys(keys.decoyKey, hash);
final password = await _passwordWithAddress(session, hash);
final nonce = _randomBytes(32);

View file

@ -102,9 +102,10 @@ Future<void> announceSessionsEnded(Session session, UuidValue account) async {
final _deliveries = <Future<void>>{};
/// Tells the members of [account]'s ended sessions, on a session of its
/// own: the request's may close first.
/// own: the request's may close first. It logs, so a failure is written
/// (persisting session logs stays off everywhere, `config/`).
Future<void> _deliverInBackground(Serverpod pod, UuidValue account) async {
final session = await pod.createSession(enableLogging: false);
final session = await pod.createSession();
try {
await deliverSessionNotices(session, account: account);
} on Object catch (error) {