summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-19 14:39:38 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-19 14:39:38 +0200
commit9e7b75bb0f6f6649fb00f2dc97059e90b7d52875 (patch)
tree94463bba19b424fdce6db0d4dacbc1901af8ea95 /packages/meshbay-hub/src
parent86188385cbdae1ee90c1dca7a7b9db2edef1ecd4 (diff)
downloadmeshbay-9e7b75bb0f6f6649fb00f2dc97059e90b7d52875.tar.gz
style: the 98 ruff could not fix, so the linter is a signal again
The pass before this applied ruff's own fixes. These are the ones needing a decision, and the point of doing them is that `ruff check .` now passes: a linter reporting 98 known-acceptable findings reports nothing, because the next real one arrives invisible. **Lines over 100 (70).** Mostly wrapped where they stood. Two exceptions: the aligned trailing comments in `protocol.py`'s message table were shortened rather than wrapped, because wrapping one row of a table breaks the table; and in `models.py` the column comments moved above their columns for the same reason. **Imports below the first statement (14).** `csam.py` kept its FastAPI imports under a section header halfway down the file; two node tests had a constant and a `pytestmark` wedged between two import blocks. Moved, not suppressed. **Bindings nothing reads (4).** Three in tests, where the call stays and only the name goes — `_user(client, "listener")` is there to create the user, not to return one. The fourth was in `revocation.py` and was not a lint finding at all: `_connect_and_listen` opened an httpx stream to the WebSocket URL, did `pass`, and then opened the real connection through the `websockets` library. One pointless request per connect, left over from before that library was used directly. Removed, and `httpx` with it. **`l` as a name (4)**, **semicolons (6)** in the POC spikes, and the rest. 2893 passed, the same count as the two commits before it. `meshbay_node/revocation.py` is worth a decision separately: 154 lines that nothing imports, superseded by `hub_client.maintain_ws`'s `on_revocation`. This commit only stopped it failing the linter. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/src')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/api/admin.py11
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/api/relay.py3
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/api/users.py4
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/api/webapp.py3
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/csam.py10
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/db/models.py17
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/tasks/cleanup.py3
7 files changed, 33 insertions, 18 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/api/admin.py b/packages/meshbay-hub/src/meshbay_hub/api/admin.py
index d8e13e9..b4b2f4f 100644
--- a/packages/meshbay-hub/src/meshbay_hub/api/admin.py
+++ b/packages/meshbay-hub/src/meshbay_hub/api/admin.py
@@ -317,7 +317,8 @@ async def admin_patch_user(
if body.role not in ("user", "moderator", "admin"):
raise HTTPException(status_code=422, detail="role must be user, moderator, or admin")
user.role = body.role
- log.info("User %s role changed to %s by %s", user.username, body.role, current_user.username)
+ log.info("User %s role changed to %s by %s",
+ user.username, body.role, current_user.username)
await create_notification(
db, user.id, "role_change",
f"Your role has been changed to {body.role}",
@@ -325,7 +326,9 @@ async def admin_patch_user(
if body.status is not None:
if body.status not in ("active", "suspended", "revoked"):
- raise HTTPException(status_code=422, detail="status must be active, suspended, or revoked")
+ raise HTTPException(
+ status_code=422,
+ detail="status must be active, suspended, or revoked")
user.status = body.status
log.info("User %s status changed to %s by %s",
user.username, body.status, current_user.username)
@@ -483,7 +486,9 @@ async def admin_patch_group(
if body.status is not None:
if body.status not in ("active", "suspended", "revoked"):
- raise HTTPException(status_code=422, detail="status must be active, suspended, or revoked")
+ raise HTTPException(
+ status_code=422,
+ detail="status must be active, suspended, or revoked")
group.status = body.status
log.info("Group %s status changed to %s by %s",
group.name, body.status, current_user.username)
diff --git a/packages/meshbay-hub/src/meshbay_hub/api/relay.py b/packages/meshbay-hub/src/meshbay_hub/api/relay.py
index 08d935b..7bb3f66 100644
--- a/packages/meshbay-hub/src/meshbay_hub/api/relay.py
+++ b/packages/meshbay-hub/src/meshbay_hub/api/relay.py
@@ -102,7 +102,8 @@ async def relay_register(
approved = _relays.get(body.relay_id)
if not approved or approved.get("pk") != body.pk_relay:
raise HTTPException(status_code=403,
- detail="Relay not approved — ask hub admin to run POST /v1/relays/approve")
+ detail="Relay not approved — ask the hub admin to "
+ "run POST /v1/relays/approve")
if body.timestamp is None or not body.signature:
raise HTTPException(
diff --git a/packages/meshbay-hub/src/meshbay_hub/api/users.py b/packages/meshbay-hub/src/meshbay_hub/api/users.py
index ee8aabc..2666e86 100644
--- a/packages/meshbay-hub/src/meshbay_hub/api/users.py
+++ b/packages/meshbay-hub/src/meshbay_hub/api/users.py
@@ -1312,7 +1312,9 @@ async def register_node_key(
if len(raw) != 32:
raise ValueError
except Exception:
- raise HTTPException(status_code=400, detail="Invalid Ed25519 public key (need 32 bytes base64)")
+ raise HTTPException(
+ status_code=400,
+ detail="Invalid Ed25519 public key (need 32 bytes base64)")
current_user.pk_node_ed25519 = body.pk_node_ed25519
await db.commit()
diff --git a/packages/meshbay-hub/src/meshbay_hub/api/webapp.py b/packages/meshbay-hub/src/meshbay_hub/api/webapp.py
index 3e23961..054d04a 100644
--- a/packages/meshbay-hub/src/meshbay_hub/api/webapp.py
+++ b/packages/meshbay-hub/src/meshbay_hub/api/webapp.py
@@ -168,7 +168,8 @@ _HTML = """\
though it had scrolled away. This asks for the keyboard to resize the
layout viewport instead, so what is pinned stays where it is looked at.
Ignored by browsers that do not know it. -->
- <meta name="viewport" content="width=device-width, initial-scale=1, interactive-widget=resizes-content">
+ <meta name="viewport"
+ content="width=device-width, initial-scale=1, interactive-widget=resizes-content">
<title>MeshBay</title>
<link rel="stylesheet" href="/a/{v}/style.css">
</head>
diff --git a/packages/meshbay-hub/src/meshbay_hub/csam.py b/packages/meshbay-hub/src/meshbay_hub/csam.py
index e540068..b8e8d04 100644
--- a/packages/meshbay-hub/src/meshbay_hub/csam.py
+++ b/packages/meshbay-hub/src/meshbay_hub/csam.py
@@ -22,6 +22,11 @@ must be reported to NCMEC (US law) or relevant authority immediately.
import logging
from pathlib import Path
+from fastapi import APIRouter, Depends, HTTPException
+
+from meshbay_hub.api.deps import require_admin
+from meshbay_hub.db.models import User
+
log = logging.getLogger(__name__)
# Default path for the CSAM hash database (blake3 hex hashes, one per line)
@@ -121,11 +126,6 @@ def check_content_hash(blake3_hex: str) -> bool:
# ── Hub API integration ───────────────────────────────────────────────────────
-from fastapi import APIRouter, Depends, HTTPException
-
-from meshbay_hub.api.deps import require_admin
-from meshbay_hub.db.models import User
-
csam_router = APIRouter(prefix="/v1/admin/csam", tags=["csam"])
diff --git a/packages/meshbay-hub/src/meshbay_hub/db/models.py b/packages/meshbay-hub/src/meshbay_hub/db/models.py
index 38c4723..ac1828f 100644
--- a/packages/meshbay-hub/src/meshbay_hub/db/models.py
+++ b/packages/meshbay-hub/src/meshbay_hub/db/models.py
@@ -53,10 +53,12 @@ class User(Base):
# the node does the wrapping, nothing reads a key from this directory. Keys
# are generated per node and pinned there (meshbay_node/roster.py).
email_hash: Mapped[str | None] = mapped_column(String(64), nullable=True) # HMAC blind index
- pk_node_ed25519: Mapped[str | None] = mapped_column(String(64), nullable=True) # node daemon key
+ pk_node_ed25519: Mapped[str | None] = mapped_column(String(64), nullable=True)
hub_id: Mapped[str] = mapped_column(String(128), nullable=False)
- role: Mapped[str] = mapped_column(String(16), default="user") # user|moderator|admin
- status: Mapped[str] = mapped_column(String(16), default="active") # active|suspended|revoked
+ # user|moderator|admin
+ role: Mapped[str] = mapped_column(String(16), default="user")
+ # active|suspended|revoked
+ status: Mapped[str] = mapped_column(String(16), default="active")
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_now)
nodes: Mapped[list["Node"]] = relationship(back_populates="user")
@@ -105,7 +107,8 @@ class Group(Base):
visibility: Mapped[str] = mapped_column(String(16), default="private") # public|private
join_policy: Mapped[str] = mapped_column(String(16), default="invite") # open|request|invite
description: Mapped[str | None] = mapped_column(String(512))
- status: Mapped[str] = mapped_column(String(16), default="active") # active|suspended|revoked
+ # active|suspended|revoked
+ status: Mapped[str] = mapped_column(String(16), default="active")
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_now)
# First time a node registered on /v1/nodes/ws announcing that it hosts this
# group. Until then the group has no files, no key and nobody to serve it, so
@@ -382,7 +385,8 @@ class IPLog(Base):
__tablename__ = "ip_logs"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
- user_id: Mapped[str | None] = mapped_column(ForeignKey("users.id")) # null for failed logins
+ # null for failed logins
+ user_id: Mapped[str | None] = mapped_column(ForeignKey("users.id"))
# The name this account had, written when it is deleted. The username is
# released on deletion and the row itself is tombstoned, so the join that
# normally supplies the name would answer "deleted-3f9a1c" for exactly the
@@ -390,7 +394,8 @@ class IPLog(Base):
username: Mapped[str | None] = mapped_column(String(64))
event: Mapped[str] = mapped_column(String(32), nullable=False)
ip_address: Mapped[str] = mapped_column(String(45), nullable=False) # IPv4 or IPv6
- detail: Mapped[str | None] = mapped_column(String(256)) # e.g. username on fail
+ # e.g. username on fail
+ detail: Mapped[str | None] = mapped_column(String(256))
timestamp: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_now)
user: Mapped["User | None"] = relationship(back_populates="ip_logs")
diff --git a/packages/meshbay-hub/src/meshbay_hub/tasks/cleanup.py b/packages/meshbay-hub/src/meshbay_hub/tasks/cleanup.py
index 429575f..1ef7796 100644
--- a/packages/meshbay-hub/src/meshbay_hub/tasks/cleanup.py
+++ b/packages/meshbay-hub/src/meshbay_hub/tasks/cleanup.py
@@ -50,7 +50,8 @@ async def cleanup_loop(get_session):
async with get_session() as db:
deleted = await purge_old_ip_logs(db)
if deleted:
- log.info("Purged %d IP log entries older than %d days", deleted, RETENTION_DAYS)
+ log.info("Purged %d IP log entries older than %d days",
+ deleted, RETENTION_DAYS)
expired = await purge_expired_verifications(db)
if expired:
log.info("Purged %d expired email verifications", expired)