Skip to content

fix: dont send transaction to invited server#393

Merged
ggazzo merged 1 commit intomainfrom
dont-send-transaction-to-invited-server
Mar 31, 2026
Merged

fix: dont send transaction to invited server#393
ggazzo merged 1 commit intomainfrom
dont-send-transaction-to-invited-server

Conversation

@sampaiodiego
Copy link
Copy Markdown
Member

@sampaiodiego sampaiodiego commented Mar 30, 2026

As per Matrix Spec:

https://spec.matrix.org/v1.18/server-server-api/#pdus

Persistent Data Units (PDUs): These events are broadcast from one homeserver to any others that have joined the same room (identified by Room ID).

FGA-58

Summary by CodeRabbit

  • Refactor
    • Refined event distribution logic to prevent redundant notifications in federated invite scenarios.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 30, 2026

Walkthrough

Updated sendEventToAllServersInRoom to accept an optional omitDestinations parameter for excluding specific servers from event broadcasts. Modified InviteService.inviteUserToRoom to exclude the invited server when notifying servers about remotely-signed invite events, narrowing the broadcast scope.

Changes

Cohort / File(s) Summary
Federation Event Broadcasting
packages/federation-sdk/src/services/federation.service.ts
Added optional omitDestinations: string[] = [] parameter to sendEventToAllServersInRoom method. Event destination selection now filters out origin, local server, and specified omit destinations using includes check.
Invite Notification Updates
packages/federation-sdk/src/services/invite.service.ts
Updated federated notification for remotely-signed invite events to pass invited server domain in omitDestinations array, restricting broadcast to "everyone else" rather than all servers in room.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Suggested labels

type: bug

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main change: preventing transaction dispatch to the invited server by adding an omitDestinations parameter used in the invite flow.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

@codecov-commenter
Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 60.00000% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 50.80%. Comparing base (1bba45f) to head (f876ff5).

Files with missing lines Patch % Lines
.../federation-sdk/src/services/federation.service.ts 62.50% 3 Missing ⚠️
...ages/federation-sdk/src/services/invite.service.ts 50.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main     #393   +/-   ##
=======================================
  Coverage   50.80%   50.80%           
=======================================
  Files         101      101           
  Lines       11482    11484    +2     
=======================================
+ Hits         5833     5835    +2     
  Misses       5649     5649           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/federation-sdk/src/services/federation.service.ts (1)

208-211: Consider using a Set for omitted-destination checks.

omitDestinations.includes(server) is linear per destination. Converting once to a Set makes this path simpler and keeps lookups constant-time.

♻️ Suggested refactor
 async sendEventToAllServersInRoom(event: PersistentEventBase, omitDestinations: string[] = []): Promise<void> {
+	const omitted = new Set(omitDestinations);
 	// TODO we need a map of rooms and destinations to avoid having to get rooms state just to send an event to all servers in the room.
 	const servers = await this.stateService.getServerSetInRoom(event.roomId);
@@
 	// Filter out the event origin, local server, and any additional omitted destinations
 	const destinations = Array.from(servers).filter(
-		(server) => server !== event.origin && server !== this.configService.serverName && !omitDestinations.includes(server),
+		(server) => server !== event.origin && server !== this.configService.serverName && !omitted.has(server),
 	);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/federation-sdk/src/services/federation.service.ts` around lines 208
- 211, Summary: Replace the linear includes check with a Set lookup to make
omitted-destination checks constant-time. Fix: before building destinations,
create a Set from omitDestinations (e.g., const omitDestinationsSet = new
Set(omitDestinations)) and then change the filter on servers (the destinations
computation) to use !omitDestinationsSet.has(server) instead of
!omitDestinations.includes(server); keep the other checks (server !==
event.origin and server !== this.configService.serverName) unchanged and
preserve types/signatures around destinations and servers.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/federation-sdk/src/services/invite.service.ts`:
- Around line 128-129: The code is broadcasting and returning the singly-signed
inviteEvent instead of the doubly-signed inviteResponse.event that was
persisted; change uses of inviteEvent in
federationService.sendEventToAllServersInRoom(...) and the function return to
use inviteResponse.event (the event returned from the invited HS signing) so the
broadcasted/returned event is the doubly-signed version required by the SPEC;
update any local variables or parameters that expect inviteEvent accordingly
(e.g., replace sending/returning inviteEvent with inviteResponse.event and
ensure inviteResponse.event is passed to sendEventToAllServersInRoom and the
function's return value).

---

Nitpick comments:
In `@packages/federation-sdk/src/services/federation.service.ts`:
- Around line 208-211: Summary: Replace the linear includes check with a Set
lookup to make omitted-destination checks constant-time. Fix: before building
destinations, create a Set from omitDestinations (e.g., const
omitDestinationsSet = new Set(omitDestinations)) and then change the filter on
servers (the destinations computation) to use !omitDestinationsSet.has(server)
instead of !omitDestinations.includes(server); keep the other checks (server !==
event.origin and server !== this.configService.serverName) unchanged and
preserve types/signatures around destinations and servers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1eaadb27-6eaf-4641-a4d7-2f925bc6759b

📥 Commits

Reviewing files that changed from the base of the PR and between 1bba45f and f876ff5.

📒 Files selected for processing (2)
  • packages/federation-sdk/src/services/federation.service.ts
  • packages/federation-sdk/src/services/invite.service.ts
📜 Review details
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-10T22:18:31.655Z
Learnt from: sampaiodiego
Repo: RocketChat/homeserver PR: 224
File: packages/federation-sdk/src/services/event-authorization.service.ts:261-268
Timestamp: 2025-10-10T22:18:31.655Z
Learning: In packages/federation-sdk/src/services/state.service.ts, the method `StateService.getLatestRoomState(roomId: string)` has return type `Promise<State>` and never returns undefined. If the state is not found, it throws an error with message "No state found for room ${roomId}" instead of returning undefined.

Applied to files:

  • packages/federation-sdk/src/services/federation.service.ts
🔇 Additional comments (1)
packages/federation-sdk/src/services/federation.service.ts (1)

197-225: Good change: destination omission is scoped cleanly without breaking existing callers.

The optional omitDestinations with default [] preserves old behavior and enables the invite-specific exclusion flow cleanly.

Comment on lines +128 to +129
// let everyone else know
void federationService.sendEventToAllServersInRoom(inviteEvent, [invitedServer]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In Matrix federation v2 invite flow, when the inviting server relays the invite event to other room servers, must the relayed event include both inviter and invitee server signatures?

💡 Result:

Yes, in the Matrix federation v2 invite flow, when the inviting server relays the invite event to other room servers (via /send), the relayed event must include both the inviter server signature (origin server) and the invitee server signature.

Citations:


🏁 Script executed:

cat -n packages/federation-sdk/src/services/invite.service.ts | sed -n '115,145p'

Repository: RocketChat/homeserver

Length of output: 1168


🏁 Script executed:

cat -n packages/federation-sdk/src/services/invite.service.ts | sed -n '80,125p'

Repository: RocketChat/homeserver

Length of output: 1892


🏁 Script executed:

cat -n packages/federation-sdk/src/services/invite.service.ts | sed -n '50,100p'

Repository: RocketChat/homeserver

Length of output: 1979


🏁 Script executed:

cat -n packages/federation-sdk/src/services/invite.service.ts | sed -n '50,60p'

Repository: RocketChat/homeserver

Length of output: 428


Broadcast and return the doubly-signed invite event, not the single-signed one.

On Line 126 you persist inviteResponse.event, but on Lines 129 and 132-133 you broadcast and return inviteEvent. The SPEC comment on Line 97 explicitly requires the event to be "signed by both the inviting homeserver and the invited homeserver" before being sent to all servers. Broadcasting the single-signed inviteEvent violates the Matrix specification and will cause federation rejection.

🐛 Proposed fix
-		await stateService.handlePdu(PersistentEventFactory.createFromRawEvent(inviteResponse.event, roomVersion));
+		const signedInviteEvent = PersistentEventFactory.createFromRawEvent(inviteResponse.event, roomVersion);
+		await stateService.handlePdu(signedInviteEvent);

 		// let everyone else know
-		void federationService.sendEventToAllServersInRoom(inviteEvent, [invitedServer]);
+		void federationService.sendEventToAllServersInRoom(signedInviteEvent, [invitedServer]);

 		return {
-			event_id: inviteEvent.eventId,
-			event: PersistentEventFactory.createFromRawEvent(inviteEvent.event, roomVersion),
+			event_id: signedInviteEvent.eventId,
+			event: signedInviteEvent,
 			room_id: roomId,
 		};
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/federation-sdk/src/services/invite.service.ts` around lines 128 -
129, The code is broadcasting and returning the singly-signed inviteEvent
instead of the doubly-signed inviteResponse.event that was persisted; change
uses of inviteEvent in federationService.sendEventToAllServersInRoom(...) and
the function return to use inviteResponse.event (the event returned from the
invited HS signing) so the broadcasted/returned event is the doubly-signed
version required by the SPEC; update any local variables or parameters that
expect inviteEvent accordingly (e.g., replace sending/returning inviteEvent with
inviteResponse.event and ensure inviteResponse.event is passed to
sendEventToAllServersInRoom and the function's return value).

@ggazzo ggazzo merged commit 15ac1f8 into main Mar 31, 2026
4 checks passed
@ggazzo ggazzo deleted the dont-send-transaction-to-invited-server branch March 31, 2026 13:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants