diff --git a/src/engine/db/mod.rs b/src/engine/db/mod.rs index 0f09260..59ae3cf 100644 --- a/src/engine/db/mod.rs +++ b/src/engine/db/mod.rs @@ -839,7 +839,7 @@ impl EventLog { } let global = event.scope() == Scope::Global; let entry = if global { - self.lamport += 1; + self.lamport = self.lamport.saturating_add(1); LogEntry { origin: self.origin.clone(), seq: self.next_seq(), lamport: self.lamport, event } } else { LogEntry { origin: self.origin.clone(), seq: 0, lamport: 0, event } @@ -876,7 +876,7 @@ impl EventLog { return Ok(None); // already have it } self.persist(&entry)?; - self.lamport = self.lamport.max(entry.lamport) + 1; // Lamport receive rule + self.lamport = self.lamport.max(entry.lamport).saturating_add(1); // Lamport receive rule self.versions.insert(entry.origin.clone(), entry.seq); let event = entry.event.clone(); self.notify(&entry); @@ -958,7 +958,7 @@ impl EventLog { let mut snapshot = Vec::with_capacity(events.len()); for event in events { let entry = if event.scope() == Scope::Global { - self.lamport += 1; + self.lamport = self.lamport.saturating_add(1); let e = LogEntry { origin: self.origin.clone(), seq, lamport: self.lamport, event }; last_global = Some(seq); seq += 1; diff --git a/src/engine/sasl.rs b/src/engine/sasl.rs index dc77e8a..4c3e91a 100644 --- a/src/engine/sasl.rs +++ b/src/engine/sasl.rs @@ -189,7 +189,14 @@ impl Engine { } }; match fingerprints.iter().find_map(|fp| self.db.certfp_owner(fp)) { - Some(account) if authzid.is_empty() || authzid.eq_ignore_ascii_case(account) => { + // Accept an authzid that is empty, matches the cert's account, OR resolves + // to it via a grouped nick — mirroring the PLAIN/SCRAM paths, which resolve + // aliases (else naming your own grouped nick is wrongly refused). + Some(account) + if authzid.is_empty() + || authzid.eq_ignore_ascii_case(account) + || self.db.resolve_account(&authzid).is_some_and(|a| a.eq_ignore_ascii_case(account)) => + { let account = account.to_string(); self.sasl_login("SASL EXTERNAL", agent, client, account) }