<feed xmlns='http://www.w3.org/2005/Atom'>
<title>meshbay.git/packages/meshbay-node/tests/test_chat_is_bounded.py, branch 0.15</title>
<subtitle>MeshBay — read-only public mirror</subtitle>
<id>https://git.meshbay.org/meshbay.git/atom?h=0.15</id>
<link rel='self' href='https://git.meshbay.org/meshbay.git/atom?h=0.15'/>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/'/>
<updated>2026-09-19T12:24:13Z</updated>
<entry>
<title>style: ruff's own fixes, mechanically applied</title>
<updated>2026-09-19T12:24:13Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-09-19T12:24:13Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=86188385cbdae1ee90c1dca7a7b9db2edef1ecd4'/>
<id>urn:sha1:86188385cbdae1ee90c1dca7a7b9db2edef1ecd4</id>
<content type='text'>
`ruff check .` had gone unrun long enough to report 568 errors, which is the
same as having no linter: the next real finding would have been invisible in the
noise. This is the 521 it fixes by itself, in 173 files, and nothing else — the
98 it cannot fix are the next commit.

What actually changed: import sorting (225), imports nobody used (87, none of
them a re-export — no `__init__.py` is touched, which was the one way this could
have broken an import elsewhere), `datetime.timezone.utc` to `datetime.UTC` (69)
and `asyncio.TimeoutError` to `TimeoutError` (18), both plain aliases on the 3.12
this project requires, `Optional[X]` to `X | None` (24), and f-strings with
nothing to interpolate (19).

Checked rather than assumed: every module in the three packages still imports,
and the suite is 2893 passed — the same count, test for test, as the merge
before it.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat(node): per-file upload ceiling is an operator setting, default 8 GB</title>
<updated>2026-09-18T23:49:56Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-09-18T23:02:05Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=c2c49182e6d4f1f1ef3ed3ba5e8699912f9a27bd'/>
<id>urn:sha1:c2c49182e6d4f1f1ef3ed3ba5e8699912f9a27bd</id>
<content type='text'>
Was a 4 GB constant in webrtc_server.py, the same on a small board and on
a machine holding a library. Now max_upload_gb in node.toml, on the Node
page and via `meshbay-node transfers max-size`, read from the transport
context per chunk so a change reaches an upload already running.

MESHBAY_DESIGN.md §6.4; §15.3 records a defect found beside it.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>fix(node): chat is bounded in size and in rate</title>
<updated>2026-09-13T18:28:52Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-09-13T18:28:52Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=729d28030746bb8b3688f85833c228acd304be61'/>
<id>urn:sha1:729d28030746bb8b3688f85833c228acd304be61</id>
<content type='text'>
A chat message is the plainest member-supplied write there is: the node stores
it in `chat.db`, where nothing expires it — retention is a manual command
(§6.6) — relays it to every other connected member, and has the hub write a
notification for every member of the group. Nothing bounded any of it. The only
ceiling was the DataChannel frame, 64 MB once the handshake is done, so one
member in a loop filled the operator's disk and saturated everyone else's
connection, and the node's answer to each message was `ack`.

Uploads, the other member-supplied write, have carried a filename allowlist,
strict chunk ordering, a no-overwrite rule and a 4 GB cap since C5a — because
somebody asked what one member costs the others on that path. Nobody had asked
it on this one.

Two bounds, for the two halves of the question: **64 KB of ciphertext** for what
one message may cost, and **60 a minute per account per group** for how often
one member may impose it. Both are checked before anything is stored or relayed;
a refusal names itself and is audited, so "why is my disk full" has an answer.
The rate is keyed by account, not by connection: a second tab does not make
anyone type faster, and keying on the session would hand a script one budget per
socket it opens.

No node-wide ceiling beside it, deliberately. The link-preview limiter has one
because a preview spends the *node's* egress and its third-party quota, which is
one shared thing; a chat message spends the sender's own group, and a node-wide
ceiling would let a busy group silence a quiet one — this same defect one level
up. The last test in the new file is that property: a member at their limit has
not spent anybody else's.

Two things stay open on purpose and are named rather than quietly done:
retention still keeps everything, because a default that deletes people's
history is not a review's call; and the composer still offers to send an
oversized message, so this is §6.4's pattern with only the node half built.

§6.6 gains the rule, §13.5b the label — AV20, with AV21–AV23 registering the
three fixes this week that closed the same kind of gap elsewhere.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01UMxEQadpzPkYLFf5CYKhpW
</content>
</entry>
</feed>
