Skip to content

Chat and People spam limits: Discovery relay caps and Community rate limits (#139) - #262

Open
irzhywau wants to merge 5 commits into
developfrom
fix/139-spam-limits
Open

irzhywau wants to merge 5 commits into
developfrom
fix/139-spam-limits

Conversation

@irzhywau

@irzhywau irzhywau commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Spam limits for Chat and People, the "Spam limits" part of #139. It adds limits to the Discovery relay and to Community messages.

Why

#139 asks for a per-sender limit on Community messages with a clear "Slow down" message, and a per-person cap in the Discovery relay so one person cannot fill the list. Today one Home can fill the shared Visible now list and the relay's request store, and one sender can flood the Community room for every Home.

What changes

Discovery relay (collaboration_discovery_runtime.rs)

  • The relay accepts a listing, query or contact request only from the Carrier endpoint that signed it. It refuses a call without an authenticated endpoint. A Home's Carrier endpoint is its signing device: server_infra.rs gives the Carrier node and collaboration the same key. So another Home cannot replay a withdrawn public listing to use up its owner's slots.
  • One Home lists at most 4 people. The relay stores at most 8 contact requests per sender Profile and 16 per Home.
  • Renewing a stored listing and resending a stored request remain allowed.

Community messages (collaboration_rate_limit.rs, collaboration_core.rs, collaboration_transport.rs)

  • Send: a Profile can send 5 messages in any 10 seconds. The count comes from the messages the Home saved, so a send that failed to save does not count. The sixth gets HTTP 429 with Retry-After. Chat shows "Slow down. You can send another message in N seconds." and keeps the draft.
  • Receive: a Home accepts at most 5 messages per sender Profile in 10 seconds, the same as the send limit (Anders, 8 Oct), and keeps at most 8 per sender waiting for Chat. Network delay can bunch an honest sender's messages into one window; the Home holds them and lets them in as the window slides.
    • Past either limit, the Home holds the message and retries it itself. The sender stops resending once any other Home accepts the message, so this Home cannot rely on a resend.
    • Other senders' messages in the same batch keep flowing.
    • The held queue keeps at most 5 messages per sender and 64 in total. When it is full, the sender holding the most messages gives up its newest one. If every sender holds as few, the batch waits and retries later. A fair sender's message is never dropped.
  • Not counted: a retry of a stored message, presence, and direct messages.

Docs: a new "Spam Limits" section in docs/PEOPLE_CONVERSATIONS.md, and a changelog entry.

Not in this PR

Refused-case tests

  • Relay:
    • listing limit per Home, including through query;
    • a replay of a withdrawn listing from another Home is refused;
    • request limits per sender and per Home;
    • a request a Home did not sign is refused;
    • a call without a source is refused.
  • Send:
    • a burst gets the typed refusal, and the state on disk is unchanged;
    • retries are not counted;
    • a send that failed before the write does not count, and one that failed after the rename does;
    • HTTP 429 with Retry-After on the Chat route;
    • the Chat UI text.
  • Receive (through the real transport driver):
    • a flood is held back while other senders keep flowing;
    • an honest message past the limit lands once the window slides, without the sender resending it;
    • an honest message keeps its place when flooders fill the held queue (the honest sender reaches its Chat backlog);
    • limiter and held-queue bounds, fair eviction by message count and by size, and a refusal that leaves the queue unchanged.

Verification (local, macOS arm64, rebased on develop 34b2e5c5)

  • just test-elastos on 4c566791: 4,111 passed, 0 failed.
  • cargo fmt --check, workspace cargo clippy --all-targets -D warnings and the Chat UI and IPFS provider clippy are clean.
  • Script suites, product data and the Home, People and Chat smokes pass, including chat-room-product-behavior-smoke.mjs.
  • Known local failures outside this PR, also failing on unchanged develop on this Mac: two tests in release-platform-input-test.py and one Python 3.14 tarfile case in update-hop-compare-test.py.

Independent adversarial review (#173)

Codex reviewed the branch over five rounds and found 9 real problems; all are fixed (PASS at 3182ee21, then a2625b29 for the bundle). After the rebase onto develop 34b2e5c5, Codex reviewed the new head for semantic conflicts with develop's changes (the new FileLock, update planner, components by CID) and confirmed the source changes match a2625b29 line for line: Independent adversarial review (Codex) of fix/139-spam-limits @ b7d9054a VERDICT: PASS.

The rebase moved the changelog bullet under [Unreleased] (develop moved the old notes into alpha.9) and rebuilt the Chat bundle with develop's path-independent build script, under the new cache version chat-room-ui-20261008a.

The receive limit change to 5 was reviewed on its own: Independent adversarial review (Codex) of fix/139-spam-limits @ 4c566791 VERDICT: PASS.

This PR adds no new public route, approval type, or app/provider capability.

@irzhywau

irzhywau commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Independent adversarial review (Codex) of fix/139-spam-limits @ 3182ee21 VERDICT: PASS
Covers the current head: the squashed tree is byte-identical to 3182ee21, and the rebase onto develop changed only CHANGELOG.md.

@irzhywau

irzhywau commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Decision: one Home can list at most 4 people in Discovery (proposed 2 on #139), so a Home with several accounts or guests still shows them. It's one constant, MAX_DISCOVERY_ADVERTISEMENTS_PER_DEVICE.
@andersalm, please confirm or give another value. The per-browser guest sign-up limit is in #260 for triage.

@irzhywau
irzhywau requested a review from andersalm October 6, 2026 15:52
@andersalm

Copy link
Copy Markdown
Contributor

Decision (6 Oct): 4 Discovery listings per device, confirmed. Several accounts share one Home's device, and the relay still enforces its global cap of 64 (collaboration_discovery_runtime.rs:2248).

@irzhywau

irzhywau commented Oct 6, 2026

Copy link
Copy Markdown
Contributor Author

Independent adversarial review (Codex) of fix/139-spam-limits @ a2625b2 VERDICT: PASS
a2625b29 rebuilds the committed Chat bundle so the "Slow down" text actually ships; before, only the Rust source had changed.
Merge note: #123 also rebuilds this bundle, so whichever PR merges second must rerun scripts/build-chat-room-ui.sh after rebasing.

A Home's Carrier endpoint is its signing device, so the relay accepts a
listing, query or contact request only from the device that signed it and
refuses a call without an authenticated endpoint. Another Home cannot
replay a withdrawn public listing to spend its owner's slots. One Home
lists at most 4 people, and the relay stores at most 8 contact requests
per sender Profile and 16 per Home. Renewals and resends of stored items
stay free.
A Home sends at most 5 Community messages per Profile in 10 seconds,
counted from its saved messages; the next gets HTTP 429 with Retry-After
and Chat shows "Slow down" with the draft kept. Receiving Homes accept at
most 10 per sender Profile in 10 seconds and keep at most 8 per sender
waiting for Chat. A message refused by either limit is held and retried by
the receiving Home itself, since its sender stops resending once any other
Home accepts it, and other senders in the batch keep flowing. Held frames
are bounded per sender and per Home; a full queue makes room from the
largest holder or keeps the batch for a later retry, and never drops a
fair sender's frame. Retries of a stored message, presence and direct
messages are not counted.
@irzhywau irzhywau added this to the 0.8.0 milestone Oct 8, 2026
The shipped Chat bundle is compiled from chat-room-ui and committed; the
send-limit message changed only the source. Rebuilt with
scripts/build-chat-room-ui.sh under a new cache version, and the product
smoke now reads that version from the startup file instead of a hard-coded
one.
@irzhywau
irzhywau force-pushed the fix/139-spam-limits branch from a2625b2 to b7d9054 Compare October 8, 2026 11:37
@irzhywau

irzhywau commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

Independent adversarial review (Codex) of fix/139-spam-limits @ b7d9054 VERDICT: PASS
Rebased on current develop with the Chat bundle rebuilt; just test-elastos passes (4,111/0).
Decision, @andersalm: #139 says a receiving Home accepts 5 messages per 10 s per sender; #262 accepts 10, twice the send limit, so an honest Home that reconnects and sends its queued messages isn't held back. Keep 10, or set 5?

@andersalm

Copy link
Copy Markdown
Contributor

Receive limit (Anders, 8 Oct): keep the recorded 5 messages per 10 s per sender (#139), not 10. No fixed number avoids every bunching after delays, and held frames above the limit are dropped anyway (collaboration_rate_limit.rs:197-198); the held-message retry and Community catch-up recover them. A different burst policy needs a test and Anders's approval.

#139 records 5 messages per 10 seconds per sender on the receiving side, the
same as the send limit, and Anders confirmed it on #262 (8 Oct). No fixed
number avoids every bunching after network delay; a receiving Home holds the
bunched messages and lets them in as the window slides, and at most 5 per
sender are held, so a flood beyond that is still dropped.

With the limit below the per-sender Chat backlog (8), the rate binds first.
The transport tests now name the limit that binds; the held-place test sets
up an honest sender whose earlier messages Chat has not shown yet, so it
still reaches the backlog while flooders fill the held queue; the capacity
test spreads its messages over two windows to reach the backlog refusal.
@irzhywau

irzhywau commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

Independent adversarial review (Codex) of fix/139-spam-limits @ 4c56679 VERDICT: PASS
Receive limit set to 5 per sender per your decision; the rate now binds before the Chat backlog, so the held-queue tests were reworked. just test-elastos passes (4,111/0).
Offer, @andersalm: a Home setting community_receive_limit (5 to 20, default 5, a change needs only a restart) is written and tested on a local branch. Do you want it in #262?

Takes the alpha.10 train. Only elastos/CHANGELOG.md conflicted: the spam-limits bullet stays under [Unreleased], above the new 0.8.0-alpha.10 notes.
@irzhywau

irzhywau commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

@andersalm this one is done my side, should it be merged to #123? or just leave it here

@andersalm

Copy link
Copy Markdown
Contributor

This PR is superseded by #140 / #309.
Please close it when convenient; its retained work continues there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants