-
Notifications
You must be signed in to change notification settings - Fork 13k
fix(federation): previous states on initial state and remove emitter #37677
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
🦋 Changeset detectedLatest commit: 444c5b7 The changes in this PR will be included in the next version bump. This PR includes changesets to release 41 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Looks like this PR is ready to merge! 🎉 |
|
Caution Review failedThe pull request is closed. Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughRefactors federation event wiring to use the centralized Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Setup as Setup (init)
participant SDK as federationSDK.eventEmitterService
participant Handlers as events/* handlers
participant Synapse as Synapse Test Client / Homeserver
Setup->>SDK: registerEvents() -> handlers subscribe
SDK-->>Handlers: homeserver.matrix.* events published
Synapse->>SDK: emits homeserver.matrix.{message,membership,reaction,edu,...}
SDK-->>Handlers: dispatch event to matching handler
Handlers->>Handlers: process (invite/join/message/redaction/edu)
Handlers-->>Synapse: side-effects / result observable in tests (membership, messages)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro Disabled knowledge base sources:
📒 Files selected for processing (1)
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. Comment |
ae0a9a2 to
88070a2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request refactors the federation-matrix package to use the SDK's built-in event emitter service instead of maintaining a local Emitter instance. The changes also improve error messages by adding contextual information.
Key Changes
- Removes local
Emitterinstantiation and passes the SDK'seventEmitterServiceto event handlers instead - Updates all event handler functions to access
federationSDK.eventEmitterServicedirectly - Improves error messages in room event handlers by including
roomIdanduserIdcontext - Changes room name event handler to use
senderfield instead ofstate_key
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| ee/packages/federation-matrix/src/setup.ts | Removes local Emitter instantiation and unused imports, simplifies initialization |
| ee/packages/federation-matrix/src/events/index.ts | Updates function signatures to remove emitter parameter |
| ee/packages/federation-matrix/src/events/room.ts | Changes event emitter usage, switches from state_key to sender field, improves error messages |
| ee/packages/federation-matrix/src/events/reaction.ts | Updates to use SDK's event emitter service, removes unused imports |
| ee/packages/federation-matrix/src/events/ping.ts | Updates to use SDK's event emitter service |
| ee/packages/federation-matrix/src/events/message.ts | Updates to use SDK's event emitter service, consolidates imports |
| ee/packages/federation-matrix/src/events/member.ts | Updates to use SDK's event emitter service, reorganizes imports |
| ee/packages/federation-matrix/src/events/edu.ts | Updates to use SDK's event emitter service |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| throw new Error(`mapped room not found: ${roomId}`); | ||
| } | ||
|
|
||
| const localUserId = await Users.findOneByUsername(userId, { projection: { _id: 1 } }); |
Copilot
AI
Dec 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sender field in Matrix events contains the full Matrix user ID (format: @username:server.domain), but Users.findOneByUsername() expects only the username part. This will cause the user lookup to fail. Use the getUsernameServername utility function to extract the username, similar to how it's done in the room.role event handler (line 63).
| room_id: roomId, | ||
| content: { name }, | ||
| state_key: userId, | ||
| sender: userId, |
Copilot
AI
Dec 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The variable name userId is misleading as it contains the full Matrix user ID from sender (format: @username:server.domain), not just a local user ID. Consider renaming to senderId or senderMatrixId for clarity, and then use getUsernameServername() to extract the actual username before calling Users.findOneByUsername().
88070a2 to
32b5876
Compare
dba8733 to
85183c9
Compare
85183c9 to
aa7354e
Compare
ea084df to
b57caa1
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## feat/invites #37677 +/- ##
================================================
+ Coverage 54.01% 54.21% +0.20%
================================================
Files 2629 2629
Lines 50050 50051 +1
Branches 11212 11212
================================================
+ Hits 27033 27135 +102
+ Misses 20886 20769 -117
- Partials 2131 2147 +16
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
82d2031 to
9525467
Compare
9525467 to
7204642
Compare
36e006f to
65ca437
Compare
7204642 to
50f76bd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
ee/packages/federation-matrix/src/events/room.ts:82
- The error messages in this event handler are inconsistent. Lines 17 and 22 were updated to include context (roomId and userId), but similar error messages on lines 37, 42, 58, 71, and 82 still lack this context. For better debugging and consistency, these error messages should also include the relevant IDs like:
- Line 37:
throw new Error(\mapped room not found: ${roomId}`);` - Line 42:
throw new Error(\mapped user not found: ${userId}`);` - Line 58:
throw new Error(\mapped room not found: ${roomId}`);` - Line 71:
throw new Error(\mapped user not found: ${userId}`);` - Line 82:
throw new Error(\mapped user not found: ${senderId}`);`
throw new Error('mapped room not found');
}
const localUser = await Users.findOneByUsername(userId, { projection: { _id: 1, federation: 1, federated: 1 } });
if (!localUser) {
throw new Error('mapped user not found');
}
await Room.saveRoomTopic(localRoomId._id, topic, {
_id: localUser._id,
username: userId,
federation: localUser.federation,
federated: localUser.federated,
});
});
federationSDK.eventEmitterService.on('homeserver.matrix.room.role', async (data) => {
const { room_id: roomId, user_id: userId, sender_id: senderId, role } = data;
const localRoomId = await Rooms.findOne({ 'federation.mrid': roomId }, { projection: { _id: 1 } });
if (!localRoomId) {
throw new Error('mapped room not found');
}
const serverName = federationSDK.getConfig('serverName');
const [allegedUsernameLocal, , allegedUserLocalIsLocal] = getUsernameServername(userId, serverName);
const localUserId = allegedUserLocalIsLocal && (await Users.findOneByUsername(allegedUsernameLocal, { projection: { _id: 1 } }));
if (!allegedUserLocalIsLocal) {
return;
}
if (!localUserId) {
throw new Error('mapped user not found');
}
const [senderUsername, , senderIsLocal] = getUsernameServername(senderId, serverName);
if (senderIsLocal) {
return;
}
const localSenderId = await Users.findOneByUsername(senderUsername, { projection: { _id: 1 } });
if (!localSenderId) {
throw new Error('mapped user not found');
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| await acceptRoomInvite(rid, rc1AdminRequestConfig); | ||
| }, 15000); | ||
|
|
||
| describe('It should reflect all the members and messagens on the rocket.chat side', () => { |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in the describe block: "messagens" should be "messages".
| describe('It should reflect all the members and messagens on the rocket.chat side', () => { | |
| describe('It should reflect all the members and messages on the rocket.chat side', () => { |
| expect(members.members.length).toBe(3); | ||
| expect(members.members.find((member: IUser) => member.username === federationConfig.rc1.adminUser)).not.toBeNull(); | ||
| expect( | ||
| members.members.find((member: IUser) => member.username === federationConfig.rc1.additionalUser1.username), |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test is checking for the wrong user. Line 1616 checks for federationConfig.rc1.additionalUser1.username, but this user was never invited to the room. Based on the setup in beforeAll, the three members should be:
- The Synapse admin who created the room
- The Synapse user1 (
federationConfig.hs1.additionalUser1.matrixUserId) who was invited on line 1594 - The RC admin (
federationConfig.rc1.adminUser) who was invited on line 1597
This assertion should check for federationConfig.hs1.additionalUser1.matrixUserId instead of federationConfig.rc1.additionalUser1.username.
| members.members.find((member: IUser) => member.username === federationConfig.rc1.additionalUser1.username), | |
| members.members.find((member: IUser) => member.username === federationConfig.hs1.additionalUser1.matrixUserId), |
| if (!this.matrixClient) { | ||
| throw new Error('Matrix client is not initialized'); | ||
| } | ||
| await this.matrixClient.invite(userId, roomId); |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameter order in the inviteUserToRoom method wrapper is inconsistent with the direct usage of matrixClient.invite elsewhere in the test file. On lines 1594 and 1597, matrixClient.invite is called with (roomId, userId) order, but this wrapper method calls it with (userId, roomId) on line 159.
Either the wrapper should match the direct usage pattern, or the direct calls should be updated to use the consistent wrapper method. This inconsistency could lead to confusion and bugs when the wrapper is actually used.
| await this.matrixClient.invite(userId, roomId); | |
| await this.matrixClient.invite(roomId, userId); |
50f76bd to
5555b14
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
ee/packages/federation-matrix/src/events/room.ts (1)
28-51: Same Matrix ID format issue in topic handler.The
room.topichandler has the same problem asroom.name: it usessender(full Matrix ID) directly forUsers.findOneByUsername()and also passes it asusernametosaveRoomTopic. Apply the same fix usinggetUsernameServername().federationSDK.eventEmitterService.on('homeserver.matrix.room.topic', async ({ event }) => { const { room_id: roomId, content: { topic }, - sender: userId, + sender, } = event; const localRoomId = await Rooms.findOne({ 'federation.mrid': roomId }, { projection: { _id: 1 } }); if (!localRoomId) { throw new Error('mapped room not found'); } - const localUser = await Users.findOneByUsername(userId, { projection: { _id: 1, federation: 1, federated: 1 } }); + const [username] = getUsernameServername(sender, serverName); + const localUser = await Users.findOneByUsername(username, { projection: { _id: 1, federation: 1, federated: 1 } }); if (!localUser) { throw new Error('mapped user not found'); } await Room.saveRoomTopic(localRoomId._id, topic, { _id: localUser._id, - username: userId, + username, federation: localUser.federation, federated: localUser.federated, }); });ee/packages/federation-matrix/src/events/edu.ts (1)
23-27: Add user validation before broadcasting typing indicator.The typing handler should validate that the federated user exists and is properly mapped to Rocket.Chat before broadcasting, consistent with the message and reaction handlers. Currently, it broadcasts
data.user_iddirectly without verifying the user exists in Rocket.Chat or is actually federated. Add a lookup like the presence handler does (lines 40-43), or at minimum validate the user before broadcast:const matrixUser = await Users.findOneByUsername(data.user_id); if (!matrixUser) { logger.debug(`No federated user found for Matrix user_id: ${data.user_id}`); return; }Then use
matrixUser._idin the broadcast instead of the rawdata.user_id.
♻️ Duplicate comments (4)
ee/packages/federation-matrix/tests/helper/synapse-client.ts (1)
155-160: Incorrect parameter order inmatrixClient.invite()call.The Matrix JS SDK's
invitemethod expects(roomId, userId)order, but the code passes(userId, roomId). This will cause invitations to fail.Apply this diff to fix the parameter order:
async inviteUserToRoom(roomId: string, userId: string): Promise<void> { if (!this.matrixClient) { throw new Error('Matrix client is not initialized'); } - await this.matrixClient.invite(userId, roomId); + await this.matrixClient.invite(roomId, userId); }ee/packages/federation-matrix/src/events/room.ts (1)
7-26: User lookup will fail: Matrix sender ID format mismatch.The
senderfield contains the full Matrix user ID (e.g.,@username:server.domain), butUsers.findOneByUsername()expects the local username. Theroom.rolehandler (lines 63-64) correctly usesgetUsernameServername()to extract the username, but this handler does not.Apply consistent handling:
+ const serverName = federationSDK.getConfig('serverName'); + federationSDK.eventEmitterService.on('homeserver.matrix.room.name', async ({ event }) => { const { room_id: roomId, content: { name }, - sender: userId, + sender, } = event; const localRoomId = await Rooms.findOne({ 'federation.mrid': roomId }, { projection: { _id: 1 } }); if (!localRoomId) { throw new Error(`mapped room not found: ${roomId}`); } - const localUserId = await Users.findOneByUsername(userId, { projection: { _id: 1 } }); + const [username] = getUsernameServername(sender, serverName); + const localUserId = await Users.findOneByUsername(username, { projection: { _id: 1 } }); if (!localUserId) { - throw new Error(`mapped user not found: ${userId}`); + throw new Error(`mapped user not found: ${sender}`); } await Room.saveRoomName(localRoomId._id, localUserId._id, name); });ee/packages/federation-matrix/tests/end-to-end/room.spec.ts (2)
1610-1610: Typo: "messagens" should be "messages".- describe('It should reflect all the members and messagens on the rocket.chat side', () => { + describe('It should reflect all the members and messages on the rocket.chat side', () => {
1614-1618: Incorrect member assertion - checking wrong user.The test checks for
federationConfig.rc1.additionalUser1.username(line 1616), but this user was never invited. Based on the setup, the three members are:
federationConfig.hs1.adminMatrixUserId(room creator)federationConfig.hs1.additionalUser1.matrixUserId(invited at line 1594)federationConfig.rc1.adminUser(invited at line 1597)expect(members.members.find((member: IUser) => member.username === federationConfig.rc1.adminUser)).not.toBeNull(); - expect( - members.members.find((member: IUser) => member.username === federationConfig.rc1.additionalUser1.username), - ).not.toBeNull(); + expect( + members.members.find((member: IUser) => member.username === federationConfig.hs1.additionalUser1.matrixUserId), + ).not.toBeNull(); expect(members.members.find((member: IUser) => member.username === federationConfig.hs1.adminMatrixUserId)).not.toBeNull();
🧹 Nitpick comments (4)
ee/packages/federation-matrix/tests/helper/synapse-client.ts (1)
142-153: Redundant null checks given the getter throws.The
matrixClientgetter (lines 54-59) already throws if_matrixClientis null. The explicit null checks increateRoom,inviteUserToRoom, and other methods are now redundant when accessing viathis.matrixClient.Consider removing the redundant checks since the getter handles this:
async createRoom(roomName: string, visibility: Visibility = Visibility.Private): Promise<string> { - if (!this.matrixClient) { - throw new Error('Matrix client is not initialized'); - } - const room = await this.matrixClient.createRoom({ name: roomName, visibility, }); return room.room_id; }The same applies to
inviteUserToRoomand other methods that accessthis.matrixClientafter the getter was introduced.ee/packages/federation-matrix/src/events/ping.ts (1)
3-7: Unnecessaryasynckeyword.The
pingfunction no longer awaits anything directly—it only registers an event listener. Theasynckeyword on the outer function is unnecessary and could be removed for clarity.-export const ping = async () => { +export const ping = () => { federationSDK.eventEmitterService.on('homeserver.ping', async (data) => { console.log('Message received from homeserver', data); }); };ee/packages/federation-matrix/src/events/reaction.ts (1)
17-28: Unused parsed values from sender validation.Lines 17-21 extract
userPartanddomainfrom the sender but neither is used—the code proceeds to use the fullevent.senderasinternalUsername. This is consistent with other handlers (e.g.,message.ts) where federated users are stored with the full Matrix ID as username. However, the unused variables could be removed if the validation is only meant to confirm format.- const [userPart, domain] = event.sender.split(':'); - if (!userPart || !domain) { + if (!event.sender.includes(':')) { logger.error({ sender: event.sender, msg: 'Invalid Matrix sender ID format' }); return; }ee/packages/federation-matrix/tests/end-to-end/room.spec.ts (1)
1605-1605: Simplify assertion pattern.Mixing optional chaining (
?.) with non-null assertion (!) is confusing. Since line 1603 already assertspendingInvitationis defined, use the cleaner form:- rid = pendingInvitation?.rid!; + rid = pendingInvitation!.rid;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (11)
apps/meteor/tests/data/rooms.helper.ts(1 hunks)ee/packages/federation-matrix/src/events/edu.ts(2 hunks)ee/packages/federation-matrix/src/events/index.ts(1 hunks)ee/packages/federation-matrix/src/events/member.ts(2 hunks)ee/packages/federation-matrix/src/events/message.ts(5 hunks)ee/packages/federation-matrix/src/events/ping.ts(1 hunks)ee/packages/federation-matrix/src/events/reaction.ts(2 hunks)ee/packages/federation-matrix/src/events/room.ts(3 hunks)ee/packages/federation-matrix/src/setup.ts(1 hunks)ee/packages/federation-matrix/tests/end-to-end/room.spec.ts(2 hunks)ee/packages/federation-matrix/tests/helper/synapse-client.ts(6 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)
**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation
Files:
ee/packages/federation-matrix/src/events/index.tsee/packages/federation-matrix/src/events/edu.tsee/packages/federation-matrix/src/events/member.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/reaction.tsee/packages/federation-matrix/src/events/message.tsee/packages/federation-matrix/tests/helper/synapse-client.tsee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/src/events/ping.tsapps/meteor/tests/data/rooms.helper.tsee/packages/federation-matrix/tests/end-to-end/room.spec.ts
**/*.spec.ts
📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)
**/*.spec.ts: Use descriptive test names that clearly communicate expected behavior in Playwright tests
Use.spec.tsextension for test files (e.g.,login.spec.ts)
Files:
ee/packages/federation-matrix/tests/end-to-end/room.spec.ts
🧠 Learnings (17)
📓 Common learnings
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37357
File: ee/packages/federation-matrix/src/setup.ts:103-120
Timestamp: 2025-11-05T21:04:35.787Z
Learning: In Rocket.Chat's federation-matrix setup (ee/packages/federation-matrix/src/setup.ts and apps/meteor/ee/server/startup/federation.ts), configureFederationMatrixSettings does not need to be called before setupFederationMatrix. The SDK's init() establishes infrastructure (database, event handlers, APIs) first, and the configuration can be applied later via settings watchers before actual federation events are processed. The config only matters when events actually occur, at which point all infrastructure is already configured.
📚 Learning: 2025-11-05T21:04:35.787Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37357
File: ee/packages/federation-matrix/src/setup.ts:103-120
Timestamp: 2025-11-05T21:04:35.787Z
Learning: In Rocket.Chat's federation-matrix setup (ee/packages/federation-matrix/src/setup.ts and apps/meteor/ee/server/startup/federation.ts), configureFederationMatrixSettings does not need to be called before setupFederationMatrix. The SDK's init() establishes infrastructure (database, event handlers, APIs) first, and the configuration can be applied later via settings watchers before actual federation events are processed. The config only matters when events actually occur, at which point all infrastructure is already configured.
Applied to files:
ee/packages/federation-matrix/src/events/index.tsee/packages/federation-matrix/src/events/edu.tsee/packages/federation-matrix/src/events/member.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/reaction.tsee/packages/federation-matrix/src/events/message.tsee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/src/events/ping.ts
📚 Learning: 2025-11-16T19:09:43.823Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37496
File: packages/apps-engine/tests/server/runtime/deno/LivenessManager.spec.ts:3-3
Timestamp: 2025-11-16T19:09:43.823Z
Learning: In Node.js, `EventEmitter` can be imported from either the 'events' module or the 'stream' module—both export the same reference. While 'events' is the canonical module, importing from 'stream' is valid and works correctly.
Applied to files:
ee/packages/federation-matrix/src/events/index.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/ping.ts
📚 Learning: 2025-09-19T15:15:04.642Z
Learnt from: rodrigok
Repo: RocketChat/Rocket.Chat PR: 36991
File: apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts:219-221
Timestamp: 2025-09-19T15:15:04.642Z
Learning: The Federation_Matrix_homeserver_domain setting in apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts is part of the old federation system and is being deprecated/removed, so configuration issues with this setting should not be flagged for improvement.
Applied to files:
ee/packages/federation-matrix/src/events/edu.tsee/packages/federation-matrix/src/events/member.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/reaction.tsee/packages/federation-matrix/src/events/message.tsee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/src/events/ping.ts
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
Applied to files:
ee/packages/federation-matrix/src/events/edu.tsee/packages/federation-matrix/src/events/member.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/reaction.tsee/packages/federation-matrix/src/events/message.tsee/packages/federation-matrix/tests/helper/synapse-client.tsee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/tests/end-to-end/room.spec.ts
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.
Applied to files:
ee/packages/federation-matrix/src/events/edu.tsee/packages/federation-matrix/src/events/member.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/reaction.tsee/packages/federation-matrix/src/events/message.tsee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/tests/end-to-end/room.spec.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings (mapping subscription documents to room IDs), never undefined, even when user has no room subscriptions.
Applied to files:
ee/packages/federation-matrix/src/events/member.tsee/packages/federation-matrix/src/events/room.tsapps/meteor/tests/data/rooms.helper.tsee/packages/federation-matrix/tests/end-to-end/room.spec.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.
Applied to files:
ee/packages/federation-matrix/src/events/member.tsee/packages/federation-matrix/src/events/room.tsapps/meteor/tests/data/rooms.helper.tsee/packages/federation-matrix/tests/end-to-end/room.spec.ts
📚 Learning: 2025-11-27T17:56:26.050Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37557
File: apps/meteor/client/views/admin/ABAC/AdminABACRooms.tsx:115-116
Timestamp: 2025-11-27T17:56:26.050Z
Learning: In Rocket.Chat, the GET /v1/abac/rooms endpoint (implemented in ee/packages/abac/src/index.ts) only returns rooms where abacAttributes exists and is not an empty array (query: { abacAttributes: { $exists: true, $ne: [] } }). Therefore, in components consuming this endpoint (like AdminABACRooms.tsx), room.abacAttributes is guaranteed to be defined for all returned rooms, and optional chaining before calling array methods like .join() is sufficient without additional null coalescing.
Applied to files:
ee/packages/federation-matrix/src/events/member.tsee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/tests/end-to-end/room.spec.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: UserBridge.doGetUserRoomIds in packages/apps-engine/src/server/bridges/UserBridge.ts has a bug where it implicitly returns undefined when the app lacks read permission (missing return statement in the else case of the permission check).
Applied to files:
ee/packages/federation-matrix/tests/helper/synapse-client.ts
📚 Learning: 2025-09-16T13:33:49.237Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36890
File: apps/meteor/tests/e2e/e2e-encryption/e2ee-otr.spec.ts:21-26
Timestamp: 2025-09-16T13:33:49.237Z
Learning: The im.delete API endpoint accepts either a `roomId` parameter (requiring the actual DM room _id) or a `username` parameter (for the DM partner's username). Constructing slug-like identifiers like `user2${Users.userE2EE.data.username}` doesn't work for this endpoint.
Applied to files:
ee/packages/federation-matrix/src/events/room.ts
📚 Learning: 2025-11-19T18:20:37.116Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: apps/meteor/server/services/media-call/service.ts:141-141
Timestamp: 2025-11-19T18:20:37.116Z
Learning: In apps/meteor/server/services/media-call/service.ts, the sendHistoryMessage method should use call.caller.id or call.createdBy?.id as the message author, not call.transferredBy?.id. Even for transferred calls, the message should appear in the DM between the two users who are calling each other, not sent by the person who transferred the call.
Applied to files:
ee/packages/federation-matrix/src/events/room.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts
Applied to files:
ee/packages/federation-matrix/tests/end-to-end/room.spec.ts
📚 Learning: 2025-11-10T19:06:20.146Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37408
File: apps/meteor/client/views/admin/ABAC/useRoomAttributeOptions.tsx:53-69
Timestamp: 2025-11-10T19:06:20.146Z
Learning: In the Rocket.Chat repository, do not provide suggestions or recommendations about code sections marked with TODO comments. The maintainers have already identified these as future work and external reviewers lack the full context about implementation plans and timing.
Applied to files:
ee/packages/federation-matrix/tests/end-to-end/room.spec.ts
📚 Learning: 2025-11-19T18:20:07.720Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: packages/i18n/src/locales/en.i18n.json:918-921
Timestamp: 2025-11-19T18:20:07.720Z
Learning: Repo: RocketChat/Rocket.Chat — i18n/formatting
Learning: This repository uses a custom message formatting parser in UI blocks/messages; do not assume standard Markdown rules. For keys like Call_ended_bold, Call_not_answered_bold, Call_failed_bold, and Call_transferred_bold in packages/i18n/src/locales/en.i18n.json, retain the existing single-asterisk emphasis unless maintainers request otherwise.
Applied to files:
ee/packages/federation-matrix/tests/end-to-end/room.spec.ts
📚 Learning: 2025-10-06T20:32:23.658Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/utilities.ts:557-573
Timestamp: 2025-10-06T20:32:23.658Z
Learning: In packages/apps-engine/tests/test-data/utilities.ts, the field name `isSubscripbedViaBundle` in the `IMarketplaceSubscriptionInfo` type should not be flagged as a typo, as it may match the upstream API's field name.
Applied to files:
ee/packages/federation-matrix/tests/end-to-end/room.spec.ts
📚 Learning: 2025-11-19T12:32:29.696Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37547
File: packages/i18n/src/locales/en.i18n.json:634-634
Timestamp: 2025-11-19T12:32:29.696Z
Learning: Repo: RocketChat/Rocket.Chat
Context: i18n workflow
Learning: In this repository, new translation keys should be added to packages/i18n/src/locales/en.i18n.json only; other locale files are populated via the external translation pipeline and/or fall back to English. Do not request adding the same key to all locale files in future reviews.
Applied to files:
ee/packages/federation-matrix/tests/end-to-end/room.spec.ts
🧬 Code graph analysis (4)
ee/packages/federation-matrix/src/events/index.ts (6)
ee/packages/federation-matrix/src/events/ping.ts (1)
ping(3-7)ee/packages/federation-matrix/src/events/message.ts (1)
message(113-412)ee/packages/federation-matrix/src/events/reaction.ts (1)
reaction(9-92)ee/packages/federation-matrix/src/events/member.ts (1)
member(229-252)ee/packages/federation-matrix/src/events/edu.ts (1)
edus(9-84)ee/packages/federation-matrix/src/events/room.ts (1)
room(7-87)
ee/packages/federation-matrix/src/setup.ts (1)
ee/packages/federation-matrix/src/events/index.ts (1)
registerEvents(8-15)
apps/meteor/tests/data/rooms.helper.ts (3)
apps/meteor/tests/data/users.helper.ts (1)
IRequestConfig(18-21)apps/meteor/tests/data/api-data.ts (2)
request(10-10)credentials(39-42)packages/rest-typings/src/index.ts (1)
Endpoints(50-97)
ee/packages/federation-matrix/tests/end-to-end/room.spec.ts (1)
apps/meteor/tests/data/rooms.helper.ts (4)
rejectRoomInvite(492-508)getSubscriptions(467-479)acceptRoomInvite(439-455)getRoomMembers(259-274)
🔇 Additional comments (14)
apps/meteor/tests/data/rooms.helper.ts (1)
457-479: LGTM!The
getSubscriptionshelper follows the established patterns in this file, with proper typing using theEndpointsinterface and consistent handling of the optionalconfigparameter. This addition supports federation subscription verification as intended.ee/packages/federation-matrix/tests/helper/synapse-client.ts (1)
33-33: LGTM on the private field refactoring.The rename to
_matrixClientwith a getter that enforces initialization is a clean pattern that provides better encapsulation and fail-fast behavior.Also applies to: 54-59, 73-73, 694-694
ee/packages/federation-matrix/src/setup.ts (1)
109-109: Clean refactor removing explicit emitter wiring.The change to call
registerEvents()without parameters aligns with the broader migration to usefederationSDK.eventEmitterServiceinternally. Based on learnings, the init() establishes infrastructure first, so event registration after init is correct.ee/packages/federation-matrix/src/events/member.ts (2)
229-251: LGTM on the event registration refactor.The migration from an injected emitter to
federationSDK.eventEmitterServiceis clean and consistent with the other event handlers. The membership handling logic (invite/join/leave) remains unchanged, which is appropriate since the PR focuses on the wiring, not the business logic.
3-3: Import change is appropriate.The import correctly brings in
federationSDKfor event subscription while retaining the type imports (HomeserverEventSignatures,PduForType) that are still used within the handler functions.ee/packages/federation-matrix/src/events/index.ts (1)
8-15: Clean refactoring to centralized event emitter pattern.The migration from injected emitter parameters to a parameterless
registerEvents()that relies onfederationSDK.eventEmitterServiceis clean and consistent with the broader architectural change across all event modules.ee/packages/federation-matrix/src/events/reaction.ts (1)
9-10: Migration to centralized event emitter is correct.The function signature and event subscription pattern align with the broader refactoring across all federation event modules.
ee/packages/federation-matrix/src/events/message.ts (2)
113-114: Migration to centralized event emitter is correct.The function signature change and event subscription pattern align with the broader refactoring. The three event handlers (
homeserver.matrix.message,homeserver.matrix.encrypted,homeserver.matrix.redaction) are properly subscribed.
246-261: LGTM on the message saving logic.The text message handling path correctly formats and saves messages with federation event IDs and thread context.
ee/packages/federation-matrix/src/events/room.ts (1)
53-86: Role handler correctly usesgetUsernameServername.This handler properly extracts the username from Matrix IDs using
getUsernameServername(), which should be the pattern for theroom.nameandroom.topichandlers as well.ee/packages/federation-matrix/src/events/edu.ts (2)
9-10: Migration to centralized event emitter is correct.The function signature change and event subscription pattern align with the broader refactoring.
39-44: User lookup uses Matrix ID as username - consistent pattern.The
Users.findOneByUsername(data.user_id)call uses the Matrix user ID format, consistent with other federation handlers (message.ts,reaction.ts). This assumes federated users are stored with their full Matrix ID as the username field.ee/packages/federation-matrix/tests/end-to-end/room.spec.ts (2)
12-13: LGTM!New imports for
getRoomMembersandgetSubscriptionsare correctly added and used in the new test suite.
1568-1580: LGTM!Multiline formatting improves readability without changing assertion behavior.
fddb5b3 to
cb7d33a
Compare
3591e8f to
78f37b5
Compare
5555b14 to
917d175
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
ee/packages/federation-matrix/tests/helper/synapse-client.ts (1)
33-60:matrixClientgetter +close()semantics: avoid throwing when uninitializedWith the new
_matrixClient+matrixClientgetter,matrixClientis now either a validMatrixClientor throws. That makes this pattern inclose()problematic:async close(): Promise<void> { if (this.matrixClient) { // ... this._matrixClient = null; } }If
_matrixClientisnull(e.g., tests callclose()without a priorinitialize()), accessingthis.matrixClientwill throw before theifcheck can do anything. Previously,close()was effectively a no-op in that case.Recommend guarding on
_matrixClientdirectly and working with a local variable:async close(): Promise<void> { - if (this.matrixClient) { - this.matrixClient.stopClient(); - await this.matrixClient.store?.deleteAllData?.(); - await this.matrixClient.clearStores?.(); - this.matrixClient.removeAllListeners(); - await this.matrixClient.logout(true); - this._matrixClient = null; - } + const client = this._matrixClient; + if (!client) { + return; + } + + client.stopClient(); + await client.store?.deleteAllData?.(); + await client.clearStores?.(); + client.removeAllListeners(); + await client.logout(true); + this._matrixClient = null; }As an optional follow-up, most
if (!this.matrixClient)checks in other methods are now redundant, since the getter already throws when uninitialized; you can simplify by just usingconst client = this.matrixClient;and operating onclient.Also applies to: 687-695
♻️ Duplicate comments (2)
ee/packages/federation-matrix/src/events/room.ts (1)
8-51: Matrixsendershould likely be parsed viagetUsernameServernamebeforeUsers.findOneByUsernameBoth
room.nameandroom.topichandlers are using the rawsendervalue asuserIdand passing it directly intoUsers.findOneByUsername(userId). In Matrix,event.senderis normally the full Matrix user ID (e.g.@user:server), whileUsers.findOneByUsername()expects the local Rocket.Chat username.You’re already using
getUsernameServernameplusfederationSDK.getConfig('serverName')in theroom.rolehandler to split Matrix IDs and decide what is “local”. For consistency and to avoid failed lookups here, consider doing the same in theroom.nameandroom.topichandlers and using the extracted username when querying and when populating theusernamefield passed toRoom.saveRoomTopic.Example shape (adjust to your needs):
const serverName = federationSDK.getConfig('serverName'); const [username] = getUsernameServername(userId, serverName); const localUser = await Users.findOneByUsername(username, { projection: { _id: 1, federation: 1, federated: 1 } });Then use
usernameinstead of the raw Matrix ID when saving.ee/packages/federation-matrix/tests/helper/synapse-client.ts (1)
142-160:inviteUserToRoompassesroomId/userIdtoMatrixClient.invitein the wrong orderThe
matrix-js-sdkMatrixClient.invitesignature isinvite(roomId: string, userId: string, opts?). Here the wrapper does:await this.matrixClient.invite(userId, roomId);So the room ID and user ID are swapped, which will either fail at runtime or invite the wrong target if the SDK doesn’t validate aggressively. This was already pointed out in a previous review and still needs correction.
Suggested fix:
async inviteUserToRoom(roomId: string, userId: string): Promise<void> { - if (!this.matrixClient) { - throw new Error('Matrix client is not initialized'); - } - await this.matrixClient.invite(userId, roomId); + const client = this.matrixClient; + await client.invite(roomId, userId); }(This also leverages the non-nullable getter instead of manually checking.)
What is the parameter order for the `invite` method on `MatrixClient` in the `matrix-js-sdk` library?
🧹 Nitpick comments (2)
ee/packages/federation-matrix/src/events/ping.ts (1)
3-7: Consider usingLoggerinstead ofconsole.logfor consistency.Other event modules in this package (edu.ts, reaction.ts, member.ts, message.ts, room.ts) use
@rocket.chat/loggerfor structured logging. Usingconsole.loghere breaks the logging consistency pattern.+import { Logger } from '@rocket.chat/logger'; + +const logger = new Logger('federation-matrix:ping'); + export const ping = async () => { federationSDK.eventEmitterService.on('homeserver.ping', async (data) => { - console.log('Message received from homeserver', data); + logger.debug('Message received from homeserver', data); }); };ee/packages/federation-matrix/src/events/message.ts (1)
3-411: Centralizing event wiring onmessage()looks correct; just ensure it’s only registered onceThe switch from an injected emitter to
federationSDK.eventEmitterServicekeeps handler logic intact for plain, encrypted, and redaction events. The only thing to watch is thatmessage()is invoked exactly once in the lifecycle; otherwise you’ll accumulate duplicate listeners on the shared emitter.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (11)
apps/meteor/tests/data/rooms.helper.ts(1 hunks)ee/packages/federation-matrix/src/events/edu.ts(2 hunks)ee/packages/federation-matrix/src/events/index.ts(1 hunks)ee/packages/federation-matrix/src/events/member.ts(2 hunks)ee/packages/federation-matrix/src/events/message.ts(5 hunks)ee/packages/federation-matrix/src/events/ping.ts(1 hunks)ee/packages/federation-matrix/src/events/reaction.ts(2 hunks)ee/packages/federation-matrix/src/events/room.ts(3 hunks)ee/packages/federation-matrix/src/setup.ts(1 hunks)ee/packages/federation-matrix/tests/end-to-end/room.spec.ts(2 hunks)ee/packages/federation-matrix/tests/helper/synapse-client.ts(6 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- ee/packages/federation-matrix/src/events/member.ts
- ee/packages/federation-matrix/tests/end-to-end/room.spec.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)
**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation
Files:
ee/packages/federation-matrix/tests/helper/synapse-client.tsee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/src/events/reaction.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/edu.tsee/packages/federation-matrix/src/events/ping.tsee/packages/federation-matrix/src/events/index.tsee/packages/federation-matrix/src/events/message.tsapps/meteor/tests/data/rooms.helper.ts
🧠 Learnings (15)
📓 Common learnings
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:00.324Z
Learning: In Rocket.Chat's federation invite handling (ee/packages/federation-matrix/src/FederationMatrix.ts), when a user rejects an invite via federationSDK.rejectInvite(), the subscription cleanup happens automatically through an event-driven flow: Matrix emits a leave event back, which is processed by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, and that function calls Room.performUserRemoval() to clean up the subscription. No explicit cleanup is needed in the reject branch of handleInvite() because the leave event handler takes care of it.
<!-- </add_learning>
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37357
File: ee/packages/federation-matrix/src/setup.ts:103-120
Timestamp: 2025-11-05T21:04:35.787Z
Learning: In Rocket.Chat's federation-matrix setup (ee/packages/federation-matrix/src/setup.ts and apps/meteor/ee/server/startup/federation.ts), configureFederationMatrixSettings does not need to be called before setupFederationMatrix. The SDK's init() establishes infrastructure (database, event handlers, APIs) first, and the configuration can be applied later via settings watchers before actual federation events are processed. The config only matters when events actually occur, at which point all infrastructure is already configured.
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
Applied to files:
ee/packages/federation-matrix/tests/helper/synapse-client.tsee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/src/events/reaction.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/edu.tsee/packages/federation-matrix/src/events/message.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: UserBridge.doGetUserRoomIds in packages/apps-engine/src/server/bridges/UserBridge.ts has a bug where it implicitly returns undefined when the app lacks read permission (missing return statement in the else case of the permission check).
Applied to files:
ee/packages/federation-matrix/tests/helper/synapse-client.ts
📚 Learning: 2025-12-09T20:01:00.324Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:00.324Z
Learning: When reviewing federation invite handling in Rocket.Chat (specifically under ee/packages/federation-matrix), understand that rejecting an invite via federationSDK.rejectInvite() triggers an event-driven cleanup: a leave event is emitted and handled by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, which calls Room.performUserRemoval() to remove the subscription. Do not add explicit cleanup in the reject branch of handleInvite(); rely on the existing leave-event flow for cleanup. If making changes, ensure this invariant remains and that any related paths still funnel cleanup through the leave event to avoid duplicate or missing removals.
Applied to files:
ee/packages/federation-matrix/tests/helper/synapse-client.tsee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/src/events/reaction.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/edu.tsee/packages/federation-matrix/src/events/ping.tsee/packages/federation-matrix/src/events/index.tsee/packages/federation-matrix/src/events/message.ts
📚 Learning: 2025-09-19T15:15:04.642Z
Learnt from: rodrigok
Repo: RocketChat/Rocket.Chat PR: 36991
File: apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts:219-221
Timestamp: 2025-09-19T15:15:04.642Z
Learning: The Federation_Matrix_homeserver_domain setting in apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts is part of the old federation system and is being deprecated/removed, so configuration issues with this setting should not be flagged for improvement.
Applied to files:
ee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/src/events/reaction.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/edu.tsee/packages/federation-matrix/src/events/ping.tsee/packages/federation-matrix/src/events/message.ts
📚 Learning: 2025-09-16T13:33:49.237Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36890
File: apps/meteor/tests/e2e/e2e-encryption/e2ee-otr.spec.ts:21-26
Timestamp: 2025-09-16T13:33:49.237Z
Learning: The im.delete API endpoint accepts either a `roomId` parameter (requiring the actual DM room _id) or a `username` parameter (for the DM partner's username). Constructing slug-like identifiers like `user2${Users.userE2EE.data.username}` doesn't work for this endpoint.
Applied to files:
ee/packages/federation-matrix/src/events/room.ts
📚 Learning: 2025-11-19T18:20:37.116Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: apps/meteor/server/services/media-call/service.ts:141-141
Timestamp: 2025-11-19T18:20:37.116Z
Learning: In apps/meteor/server/services/media-call/service.ts, the sendHistoryMessage method should use call.caller.id or call.createdBy?.id as the message author, not call.transferredBy?.id. Even for transferred calls, the message should appear in the DM between the two users who are calling each other, not sent by the person who transferred the call.
Applied to files:
ee/packages/federation-matrix/src/events/room.ts
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.
Applied to files:
ee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/src/events/reaction.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/edu.tsee/packages/federation-matrix/src/events/message.ts
📚 Learning: 2025-11-05T21:04:35.787Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37357
File: ee/packages/federation-matrix/src/setup.ts:103-120
Timestamp: 2025-11-05T21:04:35.787Z
Learning: In Rocket.Chat's federation-matrix setup (ee/packages/federation-matrix/src/setup.ts and apps/meteor/ee/server/startup/federation.ts), configureFederationMatrixSettings does not need to be called before setupFederationMatrix. The SDK's init() establishes infrastructure (database, event handlers, APIs) first, and the configuration can be applied later via settings watchers before actual federation events are processed. The config only matters when events actually occur, at which point all infrastructure is already configured.
Applied to files:
ee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/src/events/reaction.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/edu.tsee/packages/federation-matrix/src/events/ping.tsee/packages/federation-matrix/src/events/index.tsee/packages/federation-matrix/src/events/message.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.
Applied to files:
ee/packages/federation-matrix/src/events/room.tsapps/meteor/tests/data/rooms.helper.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings (mapping subscription documents to room IDs), never undefined, even when user has no room subscriptions.
Applied to files:
ee/packages/federation-matrix/src/events/room.tsapps/meteor/tests/data/rooms.helper.ts
📚 Learning: 2025-11-27T17:56:26.050Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37557
File: apps/meteor/client/views/admin/ABAC/AdminABACRooms.tsx:115-116
Timestamp: 2025-11-27T17:56:26.050Z
Learning: In Rocket.Chat, the GET /v1/abac/rooms endpoint (implemented in ee/packages/abac/src/index.ts) only returns rooms where abacAttributes exists and is not an empty array (query: { abacAttributes: { $exists: true, $ne: [] } }). Therefore, in components consuming this endpoint (like AdminABACRooms.tsx), room.abacAttributes is guaranteed to be defined for all returned rooms, and optional chaining before calling array methods like .join() is sufficient without additional null coalescing.
Applied to files:
ee/packages/federation-matrix/src/events/room.ts
📚 Learning: 2025-11-16T19:09:43.823Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37496
File: packages/apps-engine/tests/server/runtime/deno/LivenessManager.spec.ts:3-3
Timestamp: 2025-11-16T19:09:43.823Z
Learning: In Node.js, `EventEmitter` can be imported from either the 'events' module or the 'stream' module—both export the same reference. While 'events' is the canonical module, importing from 'stream' is valid and works correctly.
Applied to files:
ee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/ping.tsee/packages/federation-matrix/src/events/index.ts
📚 Learning: 2025-10-06T20:32:23.658Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/utilities.ts:557-573
Timestamp: 2025-10-06T20:32:23.658Z
Learning: In packages/apps-engine/tests/test-data/utilities.ts, the field name `isSubscripbedViaBundle` in the `IMarketplaceSubscriptionInfo` type should not be flagged as a typo, as it may match the upstream API's field name.
Applied to files:
apps/meteor/tests/data/rooms.helper.ts
📚 Learning: 2025-12-09T20:01:00.324Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:00.324Z
Learning: In Rocket.Chat's federation invite handling (ee/packages/federation-matrix/src/FederationMatrix.ts), when a user rejects an invite via federationSDK.rejectInvite(), the subscription cleanup happens automatically through an event-driven flow: Matrix emits a leave event back, which is processed by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, and that function calls Room.performUserRemoval() to clean up the subscription. No explicit cleanup is needed in the reject branch of handleInvite() because the leave event handler takes care of it.
<!-- </add_learning>
Applied to files:
apps/meteor/tests/data/rooms.helper.ts
🧬 Code graph analysis (3)
ee/packages/federation-matrix/src/setup.ts (1)
ee/packages/federation-matrix/src/events/index.ts (1)
registerEvents(8-15)
ee/packages/federation-matrix/src/events/index.ts (6)
ee/packages/federation-matrix/src/events/ping.ts (1)
ping(3-7)ee/packages/federation-matrix/src/events/message.ts (1)
message(113-412)ee/packages/federation-matrix/src/events/reaction.ts (1)
reaction(9-92)ee/packages/federation-matrix/src/events/member.ts (1)
member(238-261)ee/packages/federation-matrix/src/events/edu.ts (1)
edus(9-84)ee/packages/federation-matrix/src/events/room.ts (1)
room(7-87)
apps/meteor/tests/data/rooms.helper.ts (3)
apps/meteor/tests/data/users.helper.ts (1)
IRequestConfig(18-21)apps/meteor/tests/data/api-data.ts (2)
request(10-10)credentials(39-42)packages/rest-typings/src/index.ts (1)
Endpoints(50-97)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: 📦 Build Packages
- GitHub Check: CodeQL-Build
- GitHub Check: CodeQL-Build
🔇 Additional comments (6)
ee/packages/federation-matrix/src/setup.ts (1)
109-109: LGTM!Clean simplification of the setup flow. Removing the emitter argument aligns with the centralized event handling through
federationSDK.eventEmitterService. Based on learnings, this ordering is correct sinceinit()establishes infrastructure before event handlers are registered.ee/packages/federation-matrix/src/events/index.ts (1)
8-14: LGTM!The parameterless
registerEvents()function cleanly orchestrates all event module registrations. Each module now internally subscribes viafederationSDK.eventEmitterService, eliminating the need for emitter threading through this coordinator.ee/packages/federation-matrix/src/events/reaction.ts (1)
9-10: LGTM!Clean migration to
federationSDK.eventEmitterServicefor both reaction and redaction event handling. Error handling and early-return guards are preserved correctly.Also applies to: 49-49
ee/packages/federation-matrix/src/events/edu.ts (1)
9-10: LGTM!The EDU (typing/presence) event handlers are correctly migrated to
federationSDK.eventEmitterService. Config checks viafederationSDK.getConfig('edu')continue to work as expected, ensuring events are only processed when the respective features are enabled.Also applies to: 33-33
apps/meteor/tests/data/rooms.helper.ts (1)
457-479: NewgetSubscriptionshelper is consistent with existing REST helpersThe implementation follows the same pattern and typing as
getRoomInfo/getRoomMembers/getGroupHistory, including optionalIRequestConfigoverrides, so this looks good.ee/packages/federation-matrix/src/events/room.ts (1)
53-86: Role handler’s use ofgetUsernameServernameand sender/target checks is coherentThe
room.rolehandler correctly:
- Maps the target Matrix user ID via
getUsernameServernameand only proceeds when the target is local.- Ignores role updates originating from local senders to avoid loops.
- Resolves both target and sender to local users before calling
Room.addUserRoleRoomScoped.This logic is consistent with the rest of the federation mapping strategy.
…rvice and remove Emitter dependency
…sure proper member and message reflection
917d175 to
a9db532
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (5)
ee/packages/federation-matrix/src/events/room.ts (2)
8-26: Extract username from Matrix ID before user lookup.The
senderfield contains the full Matrix user ID (format:@username:server.domain), butUsers.findOneByUsername()expects only the username part. UsegetUsernameServername()to extract the username, as done correctly in theroom.roleevent handler at line 63.Apply this diff:
federationSDK.eventEmitterService.on('homeserver.matrix.room.name', async ({ event }) => { const { room_id: roomId, content: { name }, - sender: userId, + sender: senderId, } = event; const localRoomId = await Rooms.findOne({ 'federation.mrid': roomId }, { projection: { _id: 1 } }); if (!localRoomId) { throw new Error(`mapped room not found: ${roomId}`); } - const localUserId = await Users.findOneByUsername(userId, { projection: { _id: 1 } }); + const serverName = federationSDK.getConfig('serverName'); + const [senderUsername] = getUsernameServername(senderId, serverName); + const localUserId = await Users.findOneByUsername(senderUsername, { projection: { _id: 1 } }); if (!localUserId) { - throw new Error(`mapped user not found: ${userId}`); + throw new Error(`mapped user not found: ${senderId}`); } await Room.saveRoomName(localRoomId._id, localUserId._id, name); });
28-51: Extract username from Matrix ID before user lookup.Same issue as the
room.namehandler: thesenderfield contains the full Matrix user ID, butUsers.findOneByUsername()expects only the username part.Apply this diff:
federationSDK.eventEmitterService.on('homeserver.matrix.room.topic', async ({ event }) => { const { room_id: roomId, content: { topic }, - sender: userId, + sender: senderId, } = event; const localRoomId = await Rooms.findOne({ 'federation.mrid': roomId }, { projection: { _id: 1 } }); if (!localRoomId) { throw new Error('mapped room not found'); } - const localUser = await Users.findOneByUsername(userId, { projection: { _id: 1, federation: 1, federated: 1 } }); + const serverName = federationSDK.getConfig('serverName'); + const [senderUsername] = getUsernameServername(senderId, serverName); + const localUser = await Users.findOneByUsername(senderUsername, { projection: { _id: 1, federation: 1, federated: 1 } }); if (!localUser) { throw new Error('mapped user not found'); } await Room.saveRoomTopic(localRoomId._id, topic, { _id: localUser._id, - username: userId, + username: senderId, federation: localUser.federation, federated: localUser.federated, }); });ee/packages/federation-matrix/tests/end-to-end/room.spec.ts (2)
1610-1610: Fix typo in describe block."messagens" should be "messages".
- describe('It should reflect all the members and messagens on the rocket.chat side', () => { + describe('It should reflect all the members and messages on the rocket.chat side', () => {
1611-1619: Verify the correct user in member assertion.Line 1616 checks for
federationConfig.rc1.additionalUser1.username, but this user was never invited to the room. Based on the setup inbeforeAll, the three members should be:
- The Synapse admin who created the room
- The Synapse user1 (
federationConfig.hs1.additionalUser1.matrixUserId) who was invited on line 1594- The RC admin (
federationConfig.rc1.adminUser) who was invited on line 1597Apply this diff:
it('It should show all the three users in the members list', async () => { const members = await getRoomMembers(rid, rc1AdminRequestConfig); expect(members.members.length).toBe(3); expect(members.members.find((member: IUser) => member.username === federationConfig.rc1.adminUser)).not.toBeNull(); expect( - members.members.find((member: IUser) => member.username === federationConfig.rc1.additionalUser1.username), + members.members.find((member: IUser) => member.username === federationConfig.hs1.additionalUser1.matrixUserId), ).not.toBeNull(); expect(members.members.find((member: IUser) => member.username === federationConfig.hs1.adminMatrixUserId)).not.toBeNull(); });ee/packages/federation-matrix/tests/helper/synapse-client.ts (1)
155-160: inviteUserToRoom likely swapsroomIdanduserIdparameters
MatrixClient.inviteis typically called asinvite(roomId, userId), and past direct usages in this file (and a previous review comment) follow that order. Here the wrapper calls:await this.matrixClient.invite(userId, roomId);which appears reversed and would either fail or invite the wrong target.
This should almost certainly be:
await this.matrixClient.invite(roomId, userId);Please double‑check against the
matrix-js-sdkversion you’re using (API forMatrixClient.invite) and any existing direct usages in the repo, then update the argument order accordingly.
🧹 Nitpick comments (2)
ee/packages/federation-matrix/tests/helper/synapse-client.ts (2)
33-59: Getter + backing field pattern is sound; guards usingthis.matrixClientare redundantUsing a private
_matrixClientwith a throwingmatrixClientgetter is a good way to enforce initialization before use. However, constructs likeif (!this.matrixClient) { throw new Error(...) }will never see a falsy value—the getter already throws when uninitialized. You can simplify by either:
- Checking
_matrixClientdirectly in those guards, or- Dropping the explicit
if (!this.matrixClient)checks and relying on the getter’s error.Not urgent, but it would reduce noise and double-accesses.
687-695: close() cleanup correctly resets backing field after shutdownUsing the getter inside
close()to stop the client, clear stores, remove listeners, and log out, then nulling_matrixClientis consistent with the new encapsulation. Just be aware this will now throw ifclose()is called before initialization; if you ever need idempotentclose(), you could guard on_matrixClientdirectly.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (11)
apps/meteor/tests/data/rooms.helper.ts(1 hunks)ee/packages/federation-matrix/src/events/edu.ts(2 hunks)ee/packages/federation-matrix/src/events/index.ts(1 hunks)ee/packages/federation-matrix/src/events/member.ts(2 hunks)ee/packages/federation-matrix/src/events/message.ts(5 hunks)ee/packages/federation-matrix/src/events/ping.ts(1 hunks)ee/packages/federation-matrix/src/events/reaction.ts(2 hunks)ee/packages/federation-matrix/src/events/room.ts(3 hunks)ee/packages/federation-matrix/src/setup.ts(1 hunks)ee/packages/federation-matrix/tests/end-to-end/room.spec.ts(2 hunks)ee/packages/federation-matrix/tests/helper/synapse-client.ts(6 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/meteor/tests/data/rooms.helper.ts
- ee/packages/federation-matrix/src/events/index.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)
**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation
Files:
ee/packages/federation-matrix/src/events/reaction.tsee/packages/federation-matrix/src/events/member.tsee/packages/federation-matrix/src/events/edu.tsee/packages/federation-matrix/tests/helper/synapse-client.tsee/packages/federation-matrix/tests/end-to-end/room.spec.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/src/events/message.tsee/packages/federation-matrix/src/events/ping.ts
**/*.spec.ts
📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)
**/*.spec.ts: Use descriptive test names that clearly communicate expected behavior in Playwright tests
Use.spec.tsextension for test files (e.g.,login.spec.ts)
Files:
ee/packages/federation-matrix/tests/end-to-end/room.spec.ts
🧠 Learnings (18)
📓 Common learnings
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:00.324Z
Learning: In Rocket.Chat's federation invite handling (ee/packages/federation-matrix/src/FederationMatrix.ts), when a user rejects an invite via federationSDK.rejectInvite(), the subscription cleanup happens automatically through an event-driven flow: Matrix emits a leave event back, which is processed by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, and that function calls Room.performUserRemoval() to clean up the subscription. No explicit cleanup is needed in the reject branch of handleInvite() because the leave event handler takes care of it.
<!-- </add_learning>
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37357
File: ee/packages/federation-matrix/src/setup.ts:103-120
Timestamp: 2025-11-05T21:04:35.787Z
Learning: In Rocket.Chat's federation-matrix setup (ee/packages/federation-matrix/src/setup.ts and apps/meteor/ee/server/startup/federation.ts), configureFederationMatrixSettings does not need to be called before setupFederationMatrix. The SDK's init() establishes infrastructure (database, event handlers, APIs) first, and the configuration can be applied later via settings watchers before actual federation events are processed. The config only matters when events actually occur, at which point all infrastructure is already configured.
📚 Learning: 2025-11-05T21:04:35.787Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37357
File: ee/packages/federation-matrix/src/setup.ts:103-120
Timestamp: 2025-11-05T21:04:35.787Z
Learning: In Rocket.Chat's federation-matrix setup (ee/packages/federation-matrix/src/setup.ts and apps/meteor/ee/server/startup/federation.ts), configureFederationMatrixSettings does not need to be called before setupFederationMatrix. The SDK's init() establishes infrastructure (database, event handlers, APIs) first, and the configuration can be applied later via settings watchers before actual federation events are processed. The config only matters when events actually occur, at which point all infrastructure is already configured.
Applied to files:
ee/packages/federation-matrix/src/events/reaction.tsee/packages/federation-matrix/src/events/member.tsee/packages/federation-matrix/src/events/edu.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/src/events/message.tsee/packages/federation-matrix/src/events/ping.ts
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
Applied to files:
ee/packages/federation-matrix/src/events/reaction.tsee/packages/federation-matrix/src/events/member.tsee/packages/federation-matrix/src/events/edu.tsee/packages/federation-matrix/tests/helper/synapse-client.tsee/packages/federation-matrix/tests/end-to-end/room.spec.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/src/events/message.ts
📚 Learning: 2025-09-19T15:15:04.642Z
Learnt from: rodrigok
Repo: RocketChat/Rocket.Chat PR: 36991
File: apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts:219-221
Timestamp: 2025-09-19T15:15:04.642Z
Learning: The Federation_Matrix_homeserver_domain setting in apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts is part of the old federation system and is being deprecated/removed, so configuration issues with this setting should not be flagged for improvement.
Applied to files:
ee/packages/federation-matrix/src/events/reaction.tsee/packages/federation-matrix/src/events/member.tsee/packages/federation-matrix/src/events/edu.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/src/events/message.tsee/packages/federation-matrix/src/events/ping.ts
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.
Applied to files:
ee/packages/federation-matrix/src/events/reaction.tsee/packages/federation-matrix/src/events/member.tsee/packages/federation-matrix/src/events/edu.tsee/packages/federation-matrix/tests/end-to-end/room.spec.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/src/events/message.ts
📚 Learning: 2025-12-09T20:01:00.324Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:00.324Z
Learning: When reviewing federation invite handling in Rocket.Chat (specifically under ee/packages/federation-matrix), understand that rejecting an invite via federationSDK.rejectInvite() triggers an event-driven cleanup: a leave event is emitted and handled by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, which calls Room.performUserRemoval() to remove the subscription. Do not add explicit cleanup in the reject branch of handleInvite(); rely on the existing leave-event flow for cleanup. If making changes, ensure this invariant remains and that any related paths still funnel cleanup through the leave event to avoid duplicate or missing removals.
Applied to files:
ee/packages/federation-matrix/src/events/reaction.tsee/packages/federation-matrix/src/events/member.tsee/packages/federation-matrix/src/events/edu.tsee/packages/federation-matrix/tests/helper/synapse-client.tsee/packages/federation-matrix/tests/end-to-end/room.spec.tsee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/room.tsee/packages/federation-matrix/src/events/message.tsee/packages/federation-matrix/src/events/ping.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings (mapping subscription documents to room IDs), never undefined, even when user has no room subscriptions.
Applied to files:
ee/packages/federation-matrix/src/events/member.tsee/packages/federation-matrix/tests/end-to-end/room.spec.tsee/packages/federation-matrix/src/events/room.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.
Applied to files:
ee/packages/federation-matrix/src/events/member.tsee/packages/federation-matrix/tests/end-to-end/room.spec.tsee/packages/federation-matrix/src/events/room.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: UserBridge.doGetUserRoomIds in packages/apps-engine/src/server/bridges/UserBridge.ts has a bug where it implicitly returns undefined when the app lacks read permission (missing return statement in the else case of the permission check).
Applied to files:
ee/packages/federation-matrix/tests/helper/synapse-client.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts
Applied to files:
ee/packages/federation-matrix/tests/end-to-end/room.spec.ts
📚 Learning: 2025-11-10T19:06:20.146Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37408
File: apps/meteor/client/views/admin/ABAC/useRoomAttributeOptions.tsx:53-69
Timestamp: 2025-11-10T19:06:20.146Z
Learning: In the Rocket.Chat repository, do not provide suggestions or recommendations about code sections marked with TODO comments. The maintainers have already identified these as future work and external reviewers lack the full context about implementation plans and timing.
Applied to files:
ee/packages/federation-matrix/tests/end-to-end/room.spec.ts
📚 Learning: 2025-11-19T18:20:07.720Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: packages/i18n/src/locales/en.i18n.json:918-921
Timestamp: 2025-11-19T18:20:07.720Z
Learning: Repo: RocketChat/Rocket.Chat — i18n/formatting
Learning: This repository uses a custom message formatting parser in UI blocks/messages; do not assume standard Markdown rules. For keys like Call_ended_bold, Call_not_answered_bold, Call_failed_bold, and Call_transferred_bold in packages/i18n/src/locales/en.i18n.json, retain the existing single-asterisk emphasis unless maintainers request otherwise.
Applied to files:
ee/packages/federation-matrix/tests/end-to-end/room.spec.ts
📚 Learning: 2025-10-06T20:32:23.658Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/utilities.ts:557-573
Timestamp: 2025-10-06T20:32:23.658Z
Learning: In packages/apps-engine/tests/test-data/utilities.ts, the field name `isSubscripbedViaBundle` in the `IMarketplaceSubscriptionInfo` type should not be flagged as a typo, as it may match the upstream API's field name.
Applied to files:
ee/packages/federation-matrix/tests/end-to-end/room.spec.ts
📚 Learning: 2025-11-19T12:32:29.696Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37547
File: packages/i18n/src/locales/en.i18n.json:634-634
Timestamp: 2025-11-19T12:32:29.696Z
Learning: Repo: RocketChat/Rocket.Chat
Context: i18n workflow
Learning: In this repository, new translation keys should be added to packages/i18n/src/locales/en.i18n.json only; other locale files are populated via the external translation pipeline and/or fall back to English. Do not request adding the same key to all locale files in future reviews.
Applied to files:
ee/packages/federation-matrix/tests/end-to-end/room.spec.ts
📚 Learning: 2025-11-27T17:56:26.050Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37557
File: apps/meteor/client/views/admin/ABAC/AdminABACRooms.tsx:115-116
Timestamp: 2025-11-27T17:56:26.050Z
Learning: In Rocket.Chat, the GET /v1/abac/rooms endpoint (implemented in ee/packages/abac/src/index.ts) only returns rooms where abacAttributes exists and is not an empty array (query: { abacAttributes: { $exists: true, $ne: [] } }). Therefore, in components consuming this endpoint (like AdminABACRooms.tsx), room.abacAttributes is guaranteed to be defined for all returned rooms, and optional chaining before calling array methods like .join() is sufficient without additional null coalescing.
Applied to files:
ee/packages/federation-matrix/tests/end-to-end/room.spec.tsee/packages/federation-matrix/src/events/room.ts
📚 Learning: 2025-11-16T19:09:43.823Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37496
File: packages/apps-engine/tests/server/runtime/deno/LivenessManager.spec.ts:3-3
Timestamp: 2025-11-16T19:09:43.823Z
Learning: In Node.js, `EventEmitter` can be imported from either the 'events' module or the 'stream' module—both export the same reference. While 'events' is the canonical module, importing from 'stream' is valid and works correctly.
Applied to files:
ee/packages/federation-matrix/src/setup.tsee/packages/federation-matrix/src/events/ping.ts
📚 Learning: 2025-09-16T13:33:49.237Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36890
File: apps/meteor/tests/e2e/e2e-encryption/e2ee-otr.spec.ts:21-26
Timestamp: 2025-09-16T13:33:49.237Z
Learning: The im.delete API endpoint accepts either a `roomId` parameter (requiring the actual DM room _id) or a `username` parameter (for the DM partner's username). Constructing slug-like identifiers like `user2${Users.userE2EE.data.username}` doesn't work for this endpoint.
Applied to files:
ee/packages/federation-matrix/src/events/room.ts
📚 Learning: 2025-11-19T18:20:37.116Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: apps/meteor/server/services/media-call/service.ts:141-141
Timestamp: 2025-11-19T18:20:37.116Z
Learning: In apps/meteor/server/services/media-call/service.ts, the sendHistoryMessage method should use call.caller.id or call.createdBy?.id as the message author, not call.transferredBy?.id. Even for transferred calls, the message should appear in the DM between the two users who are calling each other, not sent by the person who transferred the call.
Applied to files:
ee/packages/federation-matrix/src/events/room.ts
🧬 Code graph analysis (3)
ee/packages/federation-matrix/tests/end-to-end/room.spec.ts (1)
apps/meteor/tests/data/rooms.helper.ts (4)
rejectRoomInvite(492-508)getSubscriptions(467-479)acceptRoomInvite(439-455)getRoomMembers(259-274)
ee/packages/federation-matrix/src/setup.ts (1)
ee/packages/federation-matrix/src/events/index.ts (1)
registerEvents(8-15)
ee/packages/federation-matrix/src/events/room.ts (1)
packages/core-services/src/index.ts (1)
Room(169-169)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: 📦 Build Packages
- GitHub Check: CodeQL-Build
- GitHub Check: CodeQL-Build
🔇 Additional comments (10)
ee/packages/federation-matrix/src/setup.ts (1)
109-109: LGTM! Clean transition to centralized event handling.The removal of the emitter parameter aligns with the shift to
federationSDK.eventEmitterServiceacross all event modules.ee/packages/federation-matrix/src/events/reaction.ts (1)
9-47: LGTM! Consistent refactor to centralized event handling.The transition from local emitter to
federationSDK.eventEmitterServiceis correct, and the reaction processing logic remains intact.ee/packages/federation-matrix/src/events/ping.ts (1)
3-7: LGTM! Clean refactor.The transition to
federationSDK.eventEmitterServiceis correct.ee/packages/federation-matrix/tests/end-to-end/room.spec.ts (1)
1584-1608: Good test coverage for FB-52.The new test scenario validates that when a user joins an in-progress room (with existing members and messages), the room state is properly reflected on the Rocket.Chat side. This directly addresses the PR objective.
ee/packages/federation-matrix/src/events/message.ts (1)
113-265: LGTM! Event wiring refactored correctly.The transition to
federationSDK.eventEmitterServicefor message handling is correct, and all message processing logic remains intact.ee/packages/federation-matrix/src/events/edu.ts (1)
9-31: LGTM! Typing and presence event handling refactored correctly.The event wiring transition to
federationSDK.eventEmitterServiceis correct, and the EDU processing logic is preserved.ee/packages/federation-matrix/src/events/member.ts (1)
238-260: The refactored event subscription and membership handling correctly process Matrix membership state.The test "It should show all the three users in the members list" validates that room members are properly reflected when a user joins an already in-progress room with prior messages. The
handleJoin()function correctly processes join events for existing rooms, and the new event subscription wiring viafederationSDK.eventEmitterServiceis the proper implementation approach. No additional changes are needed.ee/packages/federation-matrix/tests/helper/synapse-client.ts (3)
10-10: Visibility import and usage look consistent with createRoom helperImporting
Visibilityand using it as the defaultedvisibilityparameter increateRoomis a clean, typed way to constrain room visibility in tests; no issues here.
71-74: initialize() assignment to backing field is correctCreating the client, starting it, and then assigning to
_matrixClientaligns with the new getter pattern and avoids exposing a half‑initialized client. This change looks good.
142-153: createRoom helper aligns with matrix-js-sdk usageWrapping
matrixClient.createRoomwith a typed helper that takesroomNameandvisibility(defaulting toVisibility.Private) is consistent with the SDK’s createRoom options and improves test readability. Implementation looks correct.If you want to be extra sure this matches the exact version of
matrix-js-sdkin use, please confirm thecreateRoomoptions shape in the installed SDK docs.
https://rocketchat.atlassian.net/browse/FB-52
"Room state is not reflected on Rocket.Chat after joining a room"
When a user enters a room that is already in progress, the room is not reflecting the previous members.
Proposed changes (including videos or screenshots)
Issue(s)
Steps to test or reproduce
Further comments
Summary by CodeRabbit
Tests
Refactor
Chores
✏️ Tip: You can customize this high-level summary in your review settings.