diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-10-01 11:47:39 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-10-01 11:47:39 +0200 |
| commit | 752b160c7c5e671e0db8f402a52fac27bb85ab06 (patch) | |
| tree | 61be38fa0f5d38e2bda291b69aa1037f36112f23 /packages/meshbay-hub/src/meshbay_hub/db/models.py | |
| parent | 15e117673d2303bf476d4f78699e47913ce1aec0 (diff) | |
| download | meshbay-752b160c7c5e671e0db8f402a52fac27bb85ab06.tar.gz | |
fix(hub): a stranger who knows your name locks only browsers you never used
A sign-in from a browser that presented no token is answered with one
(known_browser, kept hashed, twenty per account); a later sign-in presenting it
counts failures on its own row, which nobody else can spend. Passphrase checks
inside an open session (change, e-mail, deletion, device, pepper) count on the
account's own row, so a locked name no longer stops its owner there either; /me
reports that row. Reset and erasure forget the browsers (F-15).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/db/models.py')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/db/models.py | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/db/models.py b/packages/meshbay-hub/src/meshbay_hub/db/models.py index 1e652a6..dbc0f10 100644 --- a/packages/meshbay-hub/src/meshbay_hub/db/models.py +++ b/packages/meshbay-hub/src/meshbay_hub/db/models.py @@ -429,6 +429,25 @@ class MailQuota(Base): last_sent: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) +class KnownBrowser(Base): + """A browser this account has signed in from, for the sign-in lockout. + + Its own failure counter, which a stranger cannot spend: the lockout keyed by + username alone let anyone who knew a name keep its owner out of every + browser, four requests an hour. Only a hash of the token is kept. It is not + a credential — a sign-in presenting it still needs the passphrase. + """ + + __tablename__ = "known_browsers" + + id: Mapped[str] = mapped_column(String(36), primary_key=True, default=_uuid) + user_id: Mapped[str] = mapped_column(ForeignKey("users.id"), nullable=False, + index=True) + token_hash: Mapped[str] = mapped_column(String(64), unique=True, nullable=False) + created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_now) + last_used_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_now) + + class LoginThrottle(Base): """Wrong passphrases per username, for the sign-in lockout (`login_throttle.py`). |