Skip to content

Conversation

@sampaiodiego
Copy link
Member

@sampaiodiego sampaiodiego commented Sep 22, 2025

Proposed changes (including videos or screenshots)

Issue(s)

Steps to test or reproduce

Further comments

Summary by CodeRabbit

  • New Features

    • Improved native Matrix federation: richer federated room/user context included in federation actions and direct room creation.
  • Bug Fixes

    • More reliable invites, message delivery, typing and presence updates.
    • Room name/topic changes and deletions now reflect the correct user context.
  • Refactor

    • Removed legacy bridging layers; streamlined federation flows and callbacks.
  • Chores

    • Updated federation metadata handling and federation-related statistics.

@sampaiodiego sampaiodiego requested review from a team as code owners September 22, 2025 23:37
@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Sep 22, 2025

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Sep 22, 2025

⚠️ No Changeset found

Latest commit: ce2a254

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 22, 2025

Walkthrough

Replaces MatrixBridged models/helpers with native federation fields (mrid/mui/origin), updates federation APIs to accept full room/user objects and new return shapes, adjusts callback payloads to include full IUser, changes Rooms.setAsFederated to store mrid/origin, and removes bridging models and typings.

Changes

Cohort / File(s) Summary
Callback payloads & delete message
apps/meteor/app/channel-settings/server/functions/saveRoomName.ts, apps/meteor/app/channel-settings/server/functions/saveRoomTopic.ts, apps/meteor/lib/callbacks.ts, apps/meteor/app/lib/server/functions/deleteMessage.ts, apps/meteor/ee/server/lib/engagementDashboard/messages.ts, apps/meteor/app/discussion/server/hooks/propagateDiscussionMetadata.ts
Modified callback signatures/payloads: afterRoomNameChange/afterRoomTopicChange now receive user: IUser (full user) instead of userId; afterDeleteMessage now receives { room, user }; call sites/types updated.
Direct room creation callback
apps/meteor/app/lib/server/functions/createDirectRoom.ts
Added optional federatedRoomId option and include mrid in afterCreateDirectRoom callback payload.
Create room extraData assembly
apps/meteor/app/lib/server/functions/createRoom.ts
Compute extraData earlier (spread optionalExtraData), conditionally add federated: true and federation.version, and pass into prepareCreateRoomCallback.
Local active-status only (removed remote sync)
apps/meteor/app/lib/server/functions/setUserActiveStatus.ts
Removed remote federated-user synchronization and related federation/license imports; local active-status behavior retained.
EE federation hooks & call-site updates
apps/meteor/ee/server/hooks/federation/index.ts
Use native-federation guards (isUserNativeFederated), pass full room/user objects to FederationMatrix calls, update many call-sites to object-based signatures (kick, updateName/topic, deleteMessage, updateMessage, addUserRole, etc.).
FederationMatrix API and native-federation migration
ee/packages/federation-matrix/src/FederationMatrix.ts, packages/core-services/src/types/IFederationMatrixService.ts, packages/core-typings/src/IRoom.ts, packages/core-typings/src/IUser.ts
Replace bridged mappings with native federation data (mrid/mui/origin); change method signatures and return type for createRoom; update delete/update/kick/invite method signatures to accept room objects/matrix IDs and full users.
API handlers & event handlers: remove bridged helpers
ee/packages/federation-matrix/src/api/_matrix/invite.ts, ee/packages/federation-matrix/src/events/*
Removed MatrixBridged* helpers; use direct Rooms/Users lookups by federation keys, create federated users/rooms directly when needed; tighten error handling and use _id plus federation fields.
Remove MatrixBridged types, models, mappings, helpers*
packages/core-typings/src/federation/{IMatrixBridgedRoom.ts,IMatrixBridgedUser.ts,index.ts}, packages/model-typings/src/models/{IMatrixBridgedRoomModel.ts,IMatrixBridgedUserModel.ts}, packages/models/src/models/{MatrixBridgedRoom.ts,MatrixBridgedUser.ts}, packages/models/src/{index.ts,modelClasses.ts}, apps/meteor/server/models.ts, ee/packages/federation-matrix/src/helpers/identifiers.ts
Deleted bridged user/room typings, model classes, identifier helpers, registrations, and removed their exports from public surfaces.
Rooms model signature & new API
packages/models/src/models/Rooms.ts, packages/model-typings/src/models/IRoomsModel.ts
setAsFederated now accepts { mrid, origin } and stores federation.mrid/origin; added countDistinctFederationRoomsExcluding(...).
Subscriptions aggregation update
packages/models/src/models/Subscriptions.ts
Removed aggregation $lookup to bridged rooms; derive externalRoomId from room.federation.mrid.
Statistics adapter source change
apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Statistics.ts
Replaced MatrixBridgedRoom usage with Rooms.countDistinctFederationRoomsExcluding(...) to compute external servers.
SendMessage user lookup
apps/meteor/app/lib/server/methods/sendMessage.ts
Replaced projected user lookup with full findOneById(uid) to access full user document fields.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant RC as Rocket.Chat
  participant FM as FederationMatrix
  participant Rooms as Rooms Model
  Note over RC,FM: Federated room creation (native)

  User->>RC: createRoom(payload)
  RC->>RC: build extraData (optionalExtra, federated?, federation.version)
  RC->>FM: createRoom(room, owner, members)
  FM-->>RC: { room_id, event_id }
  RC->>Rooms: setAsFederated(roomId, { mrid: room_id, origin })
  RC-->>User: success
Loading
sequenceDiagram
  autonumber
  actor Sender as Federated User
  participant RC as Rocket.Chat
  participant FM as FederationMatrix
  participant Rooms as Rooms Model
  participant Users as Users Model
  Note over RC,FM: Sending a federated message

  Sender->>RC: postMessage(roomId, message)
  RC->>Rooms: findOne({ _id: roomId, 'federation.mrid': ... })
  RC->>Users: findOne({ 'federation.mui': ... })
  RC->>FM: sendMessage(message, room(native), user)
  FM-->>RC: ack / error
  RC-->>Sender: delivered locally
Loading
sequenceDiagram
  autonumber
  participant HS as Homeserver
  participant RC as Rocket.Chat
  participant Users as Users Model
  participant Rooms as Rooms Model
  Note over HS,RC: Incoming Matrix invite

  HS->>RC: inviteEvent(sender, roomId, ...)
  RC->>Users: findOne({ 'federation.mui': sender })
  alt not found
    RC->>Users: insertOne(federated user with mui/origin,...)
  end
  RC->>Rooms: findOne({ 'federation.mrid': roomId })
  alt not found
    RC->>RC: create internal room (DM/public)
  end
  RC-->>HS: 200 OK
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested labels

stat: ready to merge, stat: QA assured

Suggested reviewers

  • ricardogarim
  • rodrigok

Poem

I hopped through code and cleared the tracks,
MRIDs and MUIs now sit in stacks.
Bridges gone, native fields run free,
Carrots for tests and CI — whee! 🥕🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title is concise and accurately reflects the main change: removal of Matrix bridged collections/models and related bridged artifacts. The raw_summary shows widespread deletion of MatrixBridgedRoom/MatrixBridgedUser models, typings, and related call sites, so the title is relevant and specific enough for reviewers to understand the primary change.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch remove-bridged-models

📜 Recent 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.

📥 Commits

Reviewing files that changed from the base of the PR and between 2d74b20 and ce2a254.

📒 Files selected for processing (37)
  • apps/meteor/app/channel-settings/server/functions/saveRoomName.ts (1 hunks)
  • apps/meteor/app/channel-settings/server/functions/saveRoomTopic.ts (1 hunks)
  • apps/meteor/app/discussion/server/hooks/propagateDiscussionMetadata.ts (1 hunks)
  • apps/meteor/app/lib/server/functions/createDirectRoom.ts (2 hunks)
  • apps/meteor/app/lib/server/functions/createRoom.ts (1 hunks)
  • apps/meteor/app/lib/server/functions/deleteMessage.ts (1 hunks)
  • apps/meteor/app/lib/server/functions/setUserActiveStatus.ts (1 hunks)
  • apps/meteor/app/lib/server/methods/sendMessage.ts (1 hunks)
  • apps/meteor/ee/server/hooks/federation/index.ts (8 hunks)
  • apps/meteor/ee/server/lib/engagementDashboard/messages.ts (1 hunks)
  • apps/meteor/lib/callbacks.ts (3 hunks)
  • apps/meteor/server/models.ts (0 hunks)
  • apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Statistics.ts (2 hunks)
  • ee/packages/federation-matrix/src/FederationMatrix.ts (22 hunks)
  • ee/packages/federation-matrix/src/api/_matrix/invite.ts (4 hunks)
  • ee/packages/federation-matrix/src/events/edu.ts (4 hunks)
  • ee/packages/federation-matrix/src/events/invite.ts (3 hunks)
  • ee/packages/federation-matrix/src/events/member.ts (2 hunks)
  • ee/packages/federation-matrix/src/events/message.ts (2 hunks)
  • ee/packages/federation-matrix/src/events/room.ts (1 hunks)
  • ee/packages/federation-matrix/src/helpers/identifiers.ts (0 hunks)
  • packages/core-services/src/types/IFederationMatrixService.ts (2 hunks)
  • packages/core-typings/src/IRoom.ts (1 hunks)
  • packages/core-typings/src/IUser.ts (2 hunks)
  • packages/core-typings/src/federation/IMatrixBridgedRoom.ts (0 hunks)
  • packages/core-typings/src/federation/IMatrixBridgedUser.ts (0 hunks)
  • packages/core-typings/src/federation/index.ts (0 hunks)
  • packages/model-typings/src/index.ts (0 hunks)
  • packages/model-typings/src/models/IMatrixBridgedRoomModel.ts (0 hunks)
  • packages/model-typings/src/models/IMatrixBridgedUserModel.ts (0 hunks)
  • packages/model-typings/src/models/IRoomsModel.ts (2 hunks)
  • packages/models/src/index.ts (0 hunks)
  • packages/models/src/modelClasses.ts (0 hunks)
  • packages/models/src/models/MatrixBridgedRoom.ts (0 hunks)
  • packages/models/src/models/MatrixBridgedUser.ts (0 hunks)
  • packages/models/src/models/Rooms.ts (2 hunks)
  • packages/models/src/models/Subscriptions.ts (1 hunks)
💤 Files with no reviewable changes (12)
  • packages/model-typings/src/index.ts
  • packages/core-typings/src/federation/IMatrixBridgedUser.ts
  • packages/models/src/index.ts
  • packages/models/src/models/MatrixBridgedUser.ts
  • packages/core-typings/src/federation/IMatrixBridgedRoom.ts
  • packages/model-typings/src/models/IMatrixBridgedUserModel.ts
  • packages/model-typings/src/models/IMatrixBridgedRoomModel.ts
  • packages/models/src/models/MatrixBridgedRoom.ts
  • packages/models/src/modelClasses.ts
  • packages/core-typings/src/federation/index.ts
  • ee/packages/federation-matrix/src/helpers/identifiers.ts
  • apps/meteor/server/models.ts
🚧 Files skipped from review as they are similar to previous changes (14)
  • apps/meteor/app/lib/server/methods/sendMessage.ts
  • apps/meteor/app/channel-settings/server/functions/saveRoomName.ts
  • ee/packages/federation-matrix/src/events/member.ts
  • ee/packages/federation-matrix/src/events/edu.ts
  • packages/model-typings/src/models/IRoomsModel.ts
  • apps/meteor/ee/server/lib/engagementDashboard/messages.ts
  • apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Statistics.ts
  • apps/meteor/lib/callbacks.ts
  • apps/meteor/app/channel-settings/server/functions/saveRoomTopic.ts
  • ee/packages/federation-matrix/src/events/room.ts
  • ee/packages/federation-matrix/src/api/_matrix/invite.ts
  • ee/packages/federation-matrix/src/events/invite.ts
  • packages/core-typings/src/IUser.ts
  • packages/core-typings/src/IRoom.ts
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: rodrigok
PR: RocketChat/Rocket.Chat#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.
📚 Learning: 2025-09-19T15:15:04.642Z
Learnt from: rodrigok
PR: RocketChat/Rocket.Chat#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:

  • apps/meteor/app/lib/server/functions/setUserActiveStatus.ts
  • ee/packages/federation-matrix/src/events/message.ts
  • ee/packages/federation-matrix/src/FederationMatrix.ts
  • apps/meteor/ee/server/hooks/federation/index.ts
  • packages/core-services/src/types/IFederationMatrixService.ts
🧬 Code graph analysis (8)
apps/meteor/app/lib/server/functions/createRoom.ts (1)
packages/core-typings/src/IRoom.ts (1)
  • IRoom (21-95)
apps/meteor/app/lib/server/functions/createDirectRoom.ts (1)
apps/meteor/lib/callbacks.ts (1)
  • callbacks (251-259)
ee/packages/federation-matrix/src/events/message.ts (2)
packages/models/src/index.ts (2)
  • Users (205-205)
  • Rooms (196-196)
ee/packages/federation-matrix/src/events/room.ts (1)
  • room (6-59)
apps/meteor/app/lib/server/functions/deleteMessage.ts (1)
apps/meteor/lib/callbacks.ts (1)
  • callbacks (251-259)
packages/models/src/models/Rooms.ts (1)
packages/core-typings/src/IRoom.ts (1)
  • IRoom (21-95)
ee/packages/federation-matrix/src/FederationMatrix.ts (9)
packages/models/src/index.ts (2)
  • Users (205-205)
  • Rooms (196-196)
packages/core-typings/src/IUser.ts (2)
  • isUserNativeFederated (275-276)
  • IUser (186-255)
ee/packages/federation-matrix/src/events/room.ts (1)
  • room (6-59)
packages/core-typings/src/IRoom.ts (3)
  • IRoom (21-95)
  • IRoomNativeFederated (114-120)
  • isRoomNativeFederated (124-125)
ee/packages/federation-matrix/src/events/member.ts (1)
  • member (9-51)
ee/packages/federation-matrix/src/events/message.ts (1)
  • message (123-293)
packages/core-typings/src/IMessage/IMessage.ts (3)
  • IMessage (138-238)
  • isMessageFromMatrixFederation (290-291)
  • isDeletedMessage (275-275)
ee/packages/federation-matrix/src/events/reaction.ts (1)
  • reaction (10-93)
ee/packages/federation-matrix/src/helpers/message.parsers.ts (1)
  • toExternalMessageFormat (201-212)
apps/meteor/ee/server/hooks/federation/index.ts (3)
apps/meteor/server/services/room/hooks/BeforeFederationActions.ts (1)
  • FederationActions (6-30)
ee/packages/federation-matrix/src/FederationMatrix.ts (1)
  • FederationMatrix (46-941)
packages/core-typings/src/IUser.ts (2)
  • isUserNativeFederated (275-276)
  • IUser (186-255)
packages/core-services/src/types/IFederationMatrixService.ts (3)
ee/packages/federation-matrix/src/events/room.ts (1)
  • room (6-59)
packages/core-typings/src/IRoom.ts (2)
  • IRoomFederated (109-112)
  • IRoomNativeFederated (114-120)
ee/packages/federation-matrix/src/events/message.ts (1)
  • message (123-293)
⏰ 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). (4)
  • GitHub Check: 🔨 Test Unit / Unit Tests
  • GitHub Check: 🔎 Code Check / Code Lint
  • GitHub Check: 🔎 Code Check / TypeScript
  • GitHub Check: 📦 Meteor Build - coverage
🔇 Additional comments (32)
apps/meteor/app/lib/server/functions/createRoom.ts (1)

134-145: Good refactor to centralize federated room metadata through extraData.

The refactor properly separates concerns by moving federation metadata handling to a dedicated extraData object that contains both the federated flag and federation version, while preserving the original roomExtraData for other properties like teamId. The conditional federation object construction is clean and follows the expected pattern.

apps/meteor/app/lib/server/functions/createDirectRoom.ts (2)

49-49: Good addition of federatedRoomId parameter.

The addition of federatedRoomId?: string to the options parameter aligns with the federation refactor objective and provides a clean way to pass federated room identifiers to the direct room creation process.


183-187: Verify callback signature compatibility for afterCreateDirectRoom

Callback payload now includes mrid (options?.federatedRoomId). Ensure all afterCreateDirectRoom handlers accept { members, creatorId, mrid } or safely ignore the new field.
Location: apps/meteor/app/lib/server/functions/createDirectRoom.ts:183–187 — only this call was found; no internal handler registrations located. Also verify external/plugin listeners.

apps/meteor/app/lib/server/functions/setUserActiveStatus.ts (1)

3-3: Verify the impact of removing federation imports and logic.

The removal of Federation, FederationEE, License, and MatrixBridgedUser imports suggests that federated user synchronization logic has been completely removed from this function. This aligns with the broader PR objective to remove matrix bridged collections, but we should verify that no critical federation functionality is lost.

apps/meteor/app/discussion/server/hooks/propagateDiscussionMetadata.ts (1)

51-51: LGTM! Callback parameter structure updated correctly.

The change from destructuring { _id, prid } to { room: { _id, prid } } correctly aligns with the new callback signature where room information is now nested under a room property. This maintains the same functionality while conforming to the updated API structure.

apps/meteor/app/lib/server/functions/deleteMessage.ts (1)

96-96: LGTM! Callback signature updated to pass both room and user objects.

The change from passing just room as the third parameter to passing { room, user } correctly follows the updated callback signature pattern. This provides more context to callback handlers while maintaining backward compatibility with the expected data structure.

packages/models/src/models/Subscriptions.ts (1)

2083-2083: LGTM! Federation data migration from bridged to native structure.

The change from matrixRoom.mri[0] to room.federation.mrid[0] correctly reflects the migration from MatrixBridged collections to native federation fields. The elimination of the $lookup to rocketchat_matrix_bridged_rooms and direct use of room.federation.mrid aligns with the broader federation refactoring effort.

ee/packages/federation-matrix/src/events/message.ts (2)

135-139: LGTM! Federation lookups migrated to native federation fields.

The changes correctly replace the removed MatrixBridged helper functions with direct database queries using native federation identifiers:

  • User lookup now uses federation.mui instead of bridged mappings
  • Room lookup now uses federation.mrid instead of bridged mappings
  • Added proper error handling with explicit throws when entities are not found

This aligns with the broader federation refactoring to use native federation data structures.


141-144: LGTM! Room federation lookup updated correctly.

The migration from MatrixBridged room lookups to direct federation.mrid queries is consistent with the federation native approach. The error handling appropriately throws when no mapped room is found, which is correct behavior for federation event processing.

packages/models/src/models/Rooms.ts (2)

670-672: LGTM! Updated setAsFederated signature with federation data object.

The method signature change from setAsFederated(roomId) to setAsFederated(roomId, { mrid, origin }) correctly stores the Matrix room ID (mrid) and origin server in the native federation structure. This replaces the previous bridged approach with direct federation field storage.


2217-2220: ****

The TODO stub for countDistinctFederationRoomsExcluding should be implemented to return federation origins as discussed in previous reviews.

packages/core-services/src/types/IFederationMatrixService.ts (4)

18-18: LGTM! Method signature updated to return federation creation result.

The change from Promise<void> to Promise<{ room_id: string; event_id: string }> provides valuable feedback about the created Matrix room, which can be used for further operations or logging.


22-22: Method signature updated to accept redactor information.

The addition of the uid parameter correctly addresses the need to identify who is performing the deletion for proper Matrix redaction semantics.


27-36: LGTM! Methods updated to use federation-native room objects.

The migration from primitive room IDs to IRoomNativeFederated objects in methods like kickUser, updateMessage, updateRoomTopic, and addUserRoleRoomScoped provides better type safety and ensures these operations can only be performed on properly federated rooms.


1-1: Import federation types needed by updated method signatures.

The updated method signatures reference IRoomNativeFederated which needs to be imported.

-import type { IMessage, IRoomFederated, IRoomNativeFederated, IUser } from '@rocket.chat/core-typings';
+import type { IMessage, IRoom, IRoomFederated, IRoomNativeFederated, IUser } from '@rocket.chat/core-typings';
apps/meteor/ee/server/hooks/federation/index.ts (8)

37-39: LGTM! Federation condition check simplified.

The change to use !FederationActions.shouldPerformFederationAction(room) with early return makes the logic clearer and more consistent with other federation checks in the codebase.


41-51: LGTM! Improved error handling and federation event ID check.

The addition of try-catch error handling and the check for !message.federation?.eventId before sending prevents federation loops and ensures local message saves aren't blocked by federation failures. This is a good defensive programming practice.


59-74: LGTM! Updated callback signature and federation user checks.

The changes correctly:

  1. Update the callback signature to receive { room, user } instead of separate parameters
  2. Add proper checks for federated status and user origin before attempting Matrix operations
  3. Pass the Matrix room ID (room.federation.mrid) and user Matrix ID (user.federation.mui) to the federation service

153-153: LGTM! Method signature updated to pass room object.

The change from FederationMatrix.kickUser(room._id, ...) to FederationMatrix.kickUser(room, ...) correctly follows the updated API that expects the full room object rather than just the ID.


162-164: LGTM! Method signatures updated to pass user objects.

The updates to pass full user objects instead of user IDs in updateRoomName and updateRoomTopic methods align with the federation service API changes and provide better type safety.


190-190: LGTM! Method signature updated for message editing.

The change from FederationMatrix.updateMessage(message._id, message.msg, message.u) to FederationMatrix.updateMessage(room, message) simplifies the API and provides the full context needed for federation operations.


220-227: Fix Matrix room ID parsing for direct messages.

The same server parsing issue exists here. The split(':').pop()! approach can break with complex server names.

-origin: params.mrid.split(':').pop()!,
+origin: params.mrid.slice(params.mrid.indexOf(':') + 1),

24-29: Fix Matrix server parsing to handle ports and IPv6 addresses.

Using split(':')[1] incorrectly drops port numbers and breaks IPv6 addresses. Matrix room IDs have the format !localpart:domain where the domain part can include ports.

-const fromServer = federatedRoomId.split(':')[1];
+const colonIndex = federatedRoomId.indexOf(':');
+const fromServer = colonIndex !== -1 ? federatedRoomId.slice(colonIndex + 1) : federatedRoomId;
ee/packages/federation-matrix/src/FederationMatrix.ts (9)

130-137: LGTM! Fixed federation data projection for user queries.

The addition of federated: 1, federation: 1 to the projection ensures isUserNativeFederated(localUser) can properly check federation status. This fixes the issue where federation fields weren't available for the type guard function.


196-230: LGTM! Method signature and return value updated correctly.

The changes properly:

  1. Update the method signature to return federation creation results
  2. Store federation data using the updated Rooms.setAsFederated API with mrid and origin
  3. Throw appropriate errors when homeserver services aren't available

This maintains consistency with the broader federation migration.


265-289: LGTM! Federation user creation logic updated.

The federated user creation correctly:

  1. Uses the external user ID as the mui field for federation mapping
  2. Stores the remote domain as the origin
  3. Sets the federation version appropriately

This aligns with the native federation data structure.


400-403: LGTM! Direct message room federation setup.

The setAsFederated call correctly stores the Matrix room ID and server name for direct message rooms, completing the federation setup process.


548-575: LGTM! Send message method updated with federation-aware parameters.

The method signature changes correctly:

  1. Accept IRoomNativeFederated to ensure the room is properly federated
  2. Use isUserNativeFederated(user) to determine the correct Matrix user ID
  3. Pass the Matrix room ID (room.federation.mrid) to federation operations

617-642: LGTM! Delete message method signature updated with redactor parameter.

The addition of the uid parameter correctly identifies who is performing the deletion, which is essential for Matrix redaction semantics. The method now properly passes the redactor's Matrix ID to the homeserver service.


793-820: LGTM! Kick user method updated to use room object.

The method signature change to accept IRoomNativeFederated ensures type safety and provides access to federation data. The Matrix user ID computation for both the kicked user and the user performing the kick is handled correctly.


822-855: LGTM! Update message method signature simplified.

The change to accept the full room and message objects instead of individual fields simplifies the API and ensures all necessary context is available for federation operations.


929-931: LGTM! Fixed typing projection for user lookup.

The addition of federation: 1, federated: 1 to the projection correctly ensures federation data is available for the isUserNativeFederated type guard function.


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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
apps/meteor/app/lib/server/functions/setUserActiveStatus.ts (1)

38-44: Group DMs can be reactivated even if some participants remain inactive.

Only the first “other” uid is checked; multi‑user DMs could be re‑enabled while another participant is still inactive. Require all other members to be active before un‑readonly.

Apply:

-  const roomsToReactivate = directConversations.reduce((acc: string[], room) => {
-    const otherUserId = isDirectMessageRoom(room) ? room.uids.find((u: string) => u !== userId) : undefined;
-    if (otherUserId && activeUserIds.includes(otherUserId)) {
-      acc.push(room._id);
-    }
-    return acc;
-  }, []);
+  const roomsToReactivate = directConversations.reduce((acc: string[], room) => {
+    if (!isDirectMessageRoom(room)) {
+      return acc;
+    }
+    const otherUserIds = room.uids.filter((u: string) => u !== userId);
+    if (otherUserIds.length > 0 && otherUserIds.every((id) => activeUserIds.includes(id))) {
+      acc.push(room._id);
+    }
+    return acc;
+  }, []);
apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Statistics.ts (1)

48-53: Critical — fix return-type mismatch: countDistinctFederationRoomsExcluding must return string[] (not number)

packages/model-typings/src/models/IRoomsModel.ts:316 and packages/models/src/models/Rooms.ts:2217 declare/implement countDistinctFederationRoomsExcluding as Promise (TODO returns 0) while apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Statistics.ts (lines 48–51) treats the result as string[] (uses .length and returns servers).

  • Change IRoomsModel.countDistinctFederationRoomsExcluding signature to Promise<string[]> and implement Rooms.countDistinctFederationRoomsExcluding(...) to return the array of server names (packages/model-typings/src/models/IRoomsModel.ts, packages/models/src/models/Rooms.ts:2217).
  • Normalize the settings arg at the call site and keep the UI shape. Apply this call-site change in Statistics.ts:
-		const externalServers = await Rooms.countDistinctFederationRoomsExcluding(settings.get('Federation_Matrix_homeserver_domain'));
+		const selfDomain = settings.get('Federation_Matrix_homeserver_domain');
+		const externalServers = await Rooms.countDistinctFederationRoomsExcluding(selfDomain ? [selfDomain] : []);

Files to fix: packages/model-typings/src/models/IRoomsModel.ts, packages/models/src/models/Rooms.ts (implement and return string[]), and apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Statistics.ts (call-site normalization).

apps/meteor/ee/server/hooks/federation/index.ts (1)

83-83: Fix: deleteMessage call missing the required matrixRoomId parameter.

The deleteMessage method signature changed to require matrixRoomId as the first parameter, but this call only passes the message.

 		if (FederationActions.shouldPerformFederationAction(room)) {
-			await FederationMatrix.deleteMessage(message);
+			await FederationMatrix.deleteMessage(room.federation.mrid, message);
 		}
ee/packages/federation-matrix/src/FederationMatrix.ts (2)

109-109: Bug: MEDIA_ENABLE_THUMBNAILS env cannot disable thumbnails (always true)

process.env.MEDIA_ENABLE_THUMBNAILS === 'true' || true evaluates to true even when explicitly set to 'false'.

Apply this fix so 'true' enables, 'false' disables, and default is true:

-                enableThumbnails: process.env.MEDIA_ENABLE_THUMBNAILS === 'true' || true,
+                enableThumbnails:
+                  process.env.MEDIA_ENABLE_THUMBNAILS === undefined
+                    ? true
+                    : process.env.MEDIA_ENABLE_THUMBNAILS === 'true',

646-667: Normalize invitee Matrix IDs and avoid re‑inviting existing members

Currently forwards raw usernames; ensure '@' prefix and domain for remote users to prevent 400s from the homeserver.

Suggested change:

-          await Promise.all(
-            usersUserName
+          await Promise.all(
+            usersUserName
               .filter((username) => {
                 const isExternalUser = username.includes(':');
                 return isExternalUser;
               })
               .map(async (username) => {
                 const alreadyMember = await Subscriptions.findOneByRoomIdAndUsername(room._id, username, { projection: { _id: 1 } });
                 if (alreadyMember) {
                   return;
                 }
-                await this.homeserverServices.invite.inviteUserToRoom(username, room.federation.mrid, inviterUserId);
+                const invitee = username.startsWith('@') ? username : `@${username}`;
+                await this.homeserverServices.invite.inviteUserToRoom(invitee, room.federation.mrid, inviterUserId);
               }),
           );
🧹 Nitpick comments (15)
apps/meteor/app/lib/server/functions/setUserActiveStatus.ts (1)

29-37: Small optimization: avoid querying self when collecting active users.

Exclude the current userId before fetching active users; it can’t affect the DM reactivation decision.

-  const uniqueUserIds = [...new Set(userIds)];
+  const uniqueUserIds = [...new Set(userIds)].filter((id) => id !== userId);
apps/meteor/app/channel-settings/server/functions/saveRoomName.ts (1)

99-101: Add userId to payload for backward compatibility.

Prevents breaking existing listeners while new user field rolls out.

Apply this diff:

-	await callbacks.run('afterRoomNameChange', { room, name: displayName, oldName: room.name, user });
+	await callbacks.run('afterRoomNameChange', { room, name: displayName, oldName: room.name, user, userId: user._id });
packages/core-typings/src/IUser.ts (1)

229-235: Deprecation marker conflicts with active use of federation fields

You’ve added mui and origin under the // @deprecated federation block. If this object is the authoritative carrier for native federation during the transition, please clarify the deprecation note or point to the new canonical shape to avoid misleading consumers.

-	// @deprecated
-	federation?: {
+	// @deprecated (legacy shape kept during migration; prefer IUserNativeFederated['federation'])
+	federation?: {
ee/packages/federation-matrix/src/events/message.ts (2)

134-144: Project only required fields to reduce payload and GC pressure

You only need _id and username for user and _id, name, t for room. Fetching full docs on every message is expensive.

-const user = await Users.findOne({ 'federation.mui': data.sender });
+const user = await Users.findOne({ 'federation.mui': data.sender }, { projection: { _id: 1, username: 1 } });
 ...
-const room = await Rooms.findOne({ 'federation.mrid': data.room_id });
+const room = await Rooms.findOne({ 'federation.mrid': data.room_id }, { projection: { _id: 1, name: 1, t: 1 } });

Ensure there are DB indexes on Users.federation.mui and Rooms.federation.mrid.


145-151: Minor: unify relation parsing and guard thread fetch

You read content['m.relates_to'] twice. Simplify and guard.

-const replyToRelation = content?.['m.relates_to'];
-const threadRelation = content?.['m.relates_to'];
-const isThreadMessage = threadRelation?.rel_type === 'm.thread';
+const relation = content?.['m.relates_to'];
+const isThreadMessage = relation?.rel_type === 'm.thread';
 const isQuoteMessage = replyToRelation?.['m.in_reply_to']?.event_id && !replyToRelation?.is_falling_back;
-const threadRootEventId = isThreadMessage ? threadRelation.event_id : undefined;
+const threadRootEventId = isThreadMessage ? relation.event_id : undefined;
 const thread = threadRootEventId ? await getThreadMessageId(threadRootEventId) : undefined;
ee/packages/federation-matrix/src/events/room.ts (1)

10-21: LGTM: direct lookups with minimal projections

Using Rooms.findOne({'federation.mrid'}) and Users.findOne({'federation.mui'}) with _id projection is correct and efficient for room.name.

Confirm indexes exist on Rooms.federation.mrid and Users.federation.mui.

ee/packages/federation-matrix/src/events/invite.ts (2)

9-13: Project only what you need from room

You only need _id to add the user to the room.

-const room = await Rooms.findOne({ 'federation.mrid': data.room_id });
+const room = await Rooms.findOne({ 'federation.mrid': data.room_id }, { projection: { _id: 1 } });

27-43: Upsert to avoid race on user creation

Two concurrent invites can race and cause a duplicate username error. Prefer atomic upsert.

-const { insertedId } = await Users.insertOne({
+const upsert = await Users.updateOne(
+	{ username: internalUsername },
+	{
+		$setOnInsert: {
+			username: internalUsername,
+			type: 'user',
+			status: UserStatus.ONLINE,
+			active: true,
+			roles: ['user'],
+			name: data.content.displayname || internalUsername,
+			requirePasswordChange: false,
+			createdAt: new Date(),
+			_updatedAt: new Date(),
+			federated: true,
+			'federation.version': 1,
+			'federation.mui': data.sender,
+			'federation.origin': serverName,
+		},
+	},
+	{ upsert: true },
+);
-const user = await Users.findOneById(insertedId);
+const user = await Users.findOne({ username: internalUsername }, { projection: { _id: 1, username: 1 } });
ee/packages/federation-matrix/src/api/_matrix/invite.ts (2)

179-206: Consider error handling for user creation failure.

The user creation logic correctly creates federated users with all required fields. However, there's no explicit error handling if the insertOne operation fails.

Consider wrapping the insertion in a try-catch:

-		const createdUser = await Users.insertOne({
+		try {
+			const createdUser = await Users.insertOne({
 			// let the _id auto generate we deal with usernames
 			username: inviteEvent.sender,
 			type: 'user',
 			status: 'online' as UserStatus,
 			active: true,
 			roles: ['user'],
 			name: inviteEvent.sender,
 			requirePasswordChange: false,
 			federated: true,
 			federation: {
 				version: 1,
 				mui: inviteEvent.sender,
 				origin: matrixRoom.origin,
 			},
 			createdAt: new Date(),
 			_updatedAt: new Date(),
-		});
+			});
 
-		senderUserId = createdUser.insertedId;
+			senderUserId = createdUser.insertedId;
+		} catch (error) {
+			throw new Error(`Failed to create federated user ${inviteEvent.sender}: ${error}`);
+		}

284-288: TODO comment needs clarification.

The TODO comment questions whether updating the MatrixBridgedRoom is needed. Since the PR removes MatrixBridged* models, this commented code should either be removed entirely or replaced with the appropriate federation field updates.

Consider removing this commented code block entirely since MatrixBridged* models are being removed:

-	// TODO is this needed?
-	// if (isDM) {
-	// 	await MatrixBridgedRoom.createOrUpdateByLocalRoomId(internalRoomId, inviteEvent.roomId, matrixRoom.origin);
-	// }
ee/packages/federation-matrix/src/FederationMatrix.ts (5)

351-355: Prefer plain for..of over for await..of on arrays

These loops iterate arrays, not async iterables; use for..of for clarity.

Example (also shown in the previous diff).

Also applies to: 219-228


732-736: Guard against missing user.username during reaction removal

If user.username is undefined, the filter will never match and the reaction won't be removed.

Apply a fallback:

-          for await (const [eventId, username] of Object.entries(reactionData.federationReactionEventIds)) {
-            if (username !== user.username) {
+          const requester = user.username ?? user._id;
+          for await (const [eventId, username] of Object.entries(reactionData.federationReactionEventIds)) {
+            if (username !== requester) {
               continue;
             }

859-885: API surface consistency (nit): rid vs room object

updateRoomName takes rid: string, while updateRoomTopic and other methods take room: IRoomNativeFederated. Consider aligning parameters for consistency.


931-939: Typing notifications ignore native MUI due to projection

findOneByUsername projects only _id, username; isUserNativeFederated(localUser) will be false and fallback will always use @username:${serverName}. Include federation fields.

Apply:

-    const localUser = await Users.findOneByUsername(user, { projection: { _id: 1, username: 1 } });
+    const localUser = await Users.findOneByUsername(user, { projection: { _id: 1, username: 1, federated: 1, federation: 1 } });

399-399: Log message wording (nit)

"bridged user" is legacy terminology; prefer "federated user" to reflect the new model.

📜 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.

📥 Commits

Reviewing files that changed from the base of the PR and between a8e33e7 and 70ceecd.

📒 Files selected for processing (32)
  • apps/meteor/app/channel-settings/server/functions/saveRoomName.ts (1 hunks)
  • apps/meteor/app/channel-settings/server/functions/saveRoomTopic.ts (1 hunks)
  • apps/meteor/app/lib/server/functions/createRoom.ts (1 hunks)
  • apps/meteor/app/lib/server/functions/setUserActiveStatus.ts (1 hunks)
  • apps/meteor/ee/server/hooks/federation/index.ts (8 hunks)
  • apps/meteor/lib/callbacks.ts (2 hunks)
  • apps/meteor/server/models.ts (0 hunks)
  • apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Statistics.ts (2 hunks)
  • ee/packages/federation-matrix/src/FederationMatrix.ts (22 hunks)
  • ee/packages/federation-matrix/src/api/_matrix/invite.ts (4 hunks)
  • ee/packages/federation-matrix/src/events/edu.ts (4 hunks)
  • ee/packages/federation-matrix/src/events/invite.ts (3 hunks)
  • ee/packages/federation-matrix/src/events/member.ts (2 hunks)
  • ee/packages/federation-matrix/src/events/message.ts (2 hunks)
  • ee/packages/federation-matrix/src/events/room.ts (1 hunks)
  • ee/packages/federation-matrix/src/helpers/identifiers.ts (0 hunks)
  • packages/core-services/src/types/IFederationMatrixService.ts (2 hunks)
  • packages/core-typings/src/IRoom.ts (1 hunks)
  • packages/core-typings/src/IUser.ts (2 hunks)
  • packages/core-typings/src/federation/IMatrixBridgedRoom.ts (0 hunks)
  • packages/core-typings/src/federation/IMatrixBridgedUser.ts (0 hunks)
  • packages/core-typings/src/federation/index.ts (0 hunks)
  • packages/model-typings/src/index.ts (0 hunks)
  • packages/model-typings/src/models/IMatrixBridgedRoomModel.ts (0 hunks)
  • packages/model-typings/src/models/IMatrixBridgedUserModel.ts (0 hunks)
  • packages/model-typings/src/models/IRoomsModel.ts (2 hunks)
  • packages/models/src/index.ts (0 hunks)
  • packages/models/src/modelClasses.ts (0 hunks)
  • packages/models/src/models/MatrixBridgedRoom.ts (0 hunks)
  • packages/models/src/models/MatrixBridgedUser.ts (0 hunks)
  • packages/models/src/models/Rooms.ts (2 hunks)
  • packages/models/src/models/Subscriptions.ts (1 hunks)
💤 Files with no reviewable changes (12)
  • packages/model-typings/src/index.ts
  • packages/core-typings/src/federation/IMatrixBridgedRoom.ts
  • packages/core-typings/src/federation/IMatrixBridgedUser.ts
  • packages/core-typings/src/federation/index.ts
  • packages/model-typings/src/models/IMatrixBridgedRoomModel.ts
  • packages/models/src/models/MatrixBridgedUser.ts
  • packages/models/src/modelClasses.ts
  • ee/packages/federation-matrix/src/helpers/identifiers.ts
  • packages/models/src/index.ts
  • apps/meteor/server/models.ts
  • packages/model-typings/src/models/IMatrixBridgedUserModel.ts
  • packages/models/src/models/MatrixBridgedRoom.ts
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: rodrigok
PR: RocketChat/Rocket.Chat#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.
📚 Learning: 2025-09-19T15:15:04.642Z
Learnt from: rodrigok
PR: RocketChat/Rocket.Chat#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:

  • apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Statistics.ts
  • packages/core-typings/src/IUser.ts
  • apps/meteor/app/lib/server/functions/setUserActiveStatus.ts
  • packages/core-services/src/types/IFederationMatrixService.ts
  • ee/packages/federation-matrix/src/FederationMatrix.ts
  • apps/meteor/ee/server/hooks/federation/index.ts
🧬 Code graph analysis (14)
apps/meteor/lib/callbacks.ts (2)
packages/core-typings/src/IRoom.ts (1)
  • IRoom (21-95)
packages/core-typings/src/IUser.ts (1)
  • IUser (186-255)
packages/model-typings/src/models/IRoomsModel.ts (1)
packages/core-typings/src/IRoom.ts (1)
  • IRoom (21-95)
apps/meteor/app/channel-settings/server/functions/saveRoomTopic.ts (2)
apps/meteor/lib/callbacks.ts (1)
  • callbacks (251-259)
apps/meteor/app/channel-settings/server/methods/saveRoomSettings.ts (1)
  • roomTopic (226-233)
ee/packages/federation-matrix/src/events/room.ts (2)
apps/meteor/app/livechat/server/methods/closeRoom.ts (1)
  • roomId (46-96)
packages/core-services/src/index.ts (1)
  • Room (167-167)
packages/models/src/models/Rooms.ts (1)
packages/core-typings/src/IRoom.ts (1)
  • IRoom (21-95)
ee/packages/federation-matrix/src/events/message.ts (2)
packages/models/src/index.ts (2)
  • Users (205-205)
  • Rooms (196-196)
ee/packages/federation-matrix/src/events/room.ts (1)
  • room (6-59)
apps/meteor/app/channel-settings/server/functions/saveRoomName.ts (2)
apps/meteor/lib/callbacks.ts (1)
  • callbacks (251-259)
ee/packages/federation-matrix/src/events/room.ts (1)
  • room (6-59)
ee/packages/federation-matrix/src/api/_matrix/invite.ts (1)
packages/core-services/src/index.ts (1)
  • Room (167-167)
ee/packages/federation-matrix/src/events/member.ts (2)
ee/packages/federation-matrix/src/events/room.ts (1)
  • room (6-59)
packages/core-services/src/index.ts (1)
  • Room (167-167)
apps/meteor/app/lib/server/functions/createRoom.ts (1)
packages/core-typings/src/IRoom.ts (1)
  • IRoom (21-95)
packages/core-services/src/types/IFederationMatrixService.ts (3)
packages/core-typings/src/IRoom.ts (2)
  • IRoomFederated (109-112)
  • IRoomNativeFederated (114-120)
packages/core-typings/src/IUser.ts (1)
  • IUser (186-255)
packages/core-typings/src/IMessage/IMessage.ts (1)
  • IMessage (138-238)
ee/packages/federation-matrix/src/FederationMatrix.ts (7)
packages/models/src/index.ts (2)
  • Users (205-205)
  • Rooms (196-196)
packages/core-typings/src/IUser.ts (2)
  • isUserNativeFederated (275-276)
  • IUser (186-255)
packages/core-typings/src/IRoom.ts (3)
  • IRoom (21-95)
  • IRoomNativeFederated (114-120)
  • isRoomNativeFederated (124-125)
ee/packages/federation-matrix/src/events/member.ts (1)
  • member (9-51)
ee/packages/federation-matrix/src/events/message.ts (1)
  • message (121-290)
ee/packages/federation-matrix/src/events/reaction.ts (1)
  • reaction (10-93)
ee/packages/federation-matrix/src/helpers/message.parsers.ts (1)
  • toExternalMessageFormat (201-212)
apps/meteor/ee/server/hooks/federation/index.ts (3)
ee/packages/federation-matrix/src/FederationMatrix.ts (1)
  • FederationMatrix (48-940)
apps/meteor/server/services/room/hooks/BeforeFederationActions.ts (1)
  • FederationActions (6-30)
packages/core-typings/src/IUser.ts (1)
  • isUserNativeFederated (275-276)
ee/packages/federation-matrix/src/events/invite.ts (2)
ee/packages/federation-matrix/src/events/room.ts (1)
  • room (6-59)
packages/core-services/src/index.ts (1)
  • Room (167-167)
⏰ 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). (1)
  • GitHub Check: CodeQL-Build
🔇 Additional comments (45)
apps/meteor/app/lib/server/functions/setUserActiveStatus.ts (2)

67-72: Federated guard may be too coarse; confirm intent (local vs remote).

Throwing for any “federated” user may block deactivating locally‑owned federated accounts. If the intent is to block only remote users, narrow the check (e.g., based on user.federation.origin).

Would you like a follow‑up patch that permits local federated users while still blocking remote placeholders?


3-3: Import consolidation OK — @rocket.chat/models exposes required APIs.

All methods in the original checklist are present in the model typings and implementations (see packages/model-typings/src/models/* and packages/models/src/models/Rooms.ts, Users.ts, Subscriptions.ts).

packages/models/src/models/Subscriptions.ts (1)

2081-2084: Derive externalRoomId from room.federation.mrid — looks good; please confirm migration coverage.

LGTM replacing bridged lookup. Verify all federated rooms have federation.mrid populated to avoid undefined externalRoomId; if not guaranteed, consider filtering for rooms where federation.mrid exists.

apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Statistics.ts (1)

2-2: Import swap to Rooms/Users is correct.

Removal of bridged models at import site looks good.

packages/models/src/models/Rooms.ts (1)

670-672: Ensure typings include federation.origin.

Method sets federation.origin, but IRoomNativeFederated originally lacked this field. After adding it in core-typings, this is consistent. No change needed here beyond that.

packages/model-typings/src/models/IRoomsModel.ts (1)

127-127: API surface aligns with setAsFederated changes.

Object param with mrid/origin is consistent with usage.

packages/core-typings/src/IUser.ts (2)

263-263: No action needed

Whitespace-only adjustment.


266-273: Good: required native federation shape on users

Requiring mui and origin alongside version in IUserNativeFederated['federation'] is consistent with the rest of the PR.

Confirm all writers of IUserNativeFederated populate non-empty strings for mui and origin (invite flow, backfills).

ee/packages/federation-matrix/src/events/message.ts (1)

6-6: Import changes OK

Model imports consolidation looks fine.

ee/packages/federation-matrix/src/events/room.ts (2)

26-37: LGTM: topic updates use minimal fields

Passing { _id, username } for the actor is sensible; ensure remote users’ username equals their MUI (as inserted).


42-58: LGTM: role changes flow

Role application via resolved local IDs is consistent with the refactor. Consider validating/whitelisting incoming role values elsewhere to avoid unexpected role names.

ee/packages/federation-matrix/src/events/invite.ts (1)

50-51: LGTM: membership linkage

Adding the (possibly newly created) user to the resolved room is correct.

apps/meteor/app/lib/server/functions/createRoom.ts (1)

134-145: Restore teamId in extraData & use Partial (avoid unsafe cast)

Verified: the grep output shows the only prepareCreateRoomCallback consumer is apps/meteor/app/e2e/server/beforeCreateRoom.ts and it does not reference extraData.teamId — keep teamId in extraData and tighten the type.

-const { teamId, ...optionalExtraData } = roomExtraData || ({} as IRoom);
+const { teamId, ...optionalExtraData } = (roomExtraData ?? {}) as Partial<IRoom>;
 
-const extraData = {
-	...optionalExtraData,
-	...(optionalExtraData.federated && {
-		federated: true,
-		federation: {
-			version: 1,
-			// TODO we should be able to provide all values from here, currently we update on callback afterCreateRoom
-		},
-	}),
-};
+const extraData = {
+	...optionalExtraData,
+	...(teamId && { teamId }),
+	...(optionalExtraData.federated && {
+		federated: true,
+		federation: { version: 1 }, // mrid/origin can be added by callbacks if not known here
+	}),
+};
ee/packages/federation-matrix/src/events/edu.ts (6)

13-17: LGTM! The migration to native federation fields is correct.

The transition from MatrixBridgedRoom to directly querying Rooms with federation.mrid is implemented correctly, maintaining the appropriate projection and error handling.


19-23: LGTM! User lookup correctly migrated to native federation.

The user lookup properly uses federation.mui and correctly validates both user existence and username availability before proceeding.


25-29: LGTM! Broadcast properly uses migrated fields.

The activity broadcast correctly uses matrixUser.username and matrixRoom._id from the migrated lookups.


37-41: LGTM! Presence user lookup properly migrated.

The presence event handling correctly queries users via federation.mui with appropriate error handling for missing users.


50-58: LGTM! User status update uses correct ID.

The status update correctly uses matrixUser._id for the update query and properly sets both status and statusDefault fields.


60-65: LGTM! Presence broadcast uses correct user fields.

The presence status broadcast correctly destructures and uses fields directly from matrixUser, eliminating the need for a separate user lookup.

ee/packages/federation-matrix/src/events/member.ts (4)

18-22: LGTM! Room lookup correctly migrated to native federation.

The room lookup properly uses federation.mrid with appropriate projection and maintains the existing error handling for missing rooms.


25-29: LGTM! User lookup properly migrated with correct logging.

The affected user lookup correctly uses federation.mui and the error log appropriately references data.state_key for the Matrix user identifier.


34-35: LGTM! Voluntary leave correctly uses room._id.

The voluntary leave logic properly uses room._id and passes the complete affectedUser object to the removal service.


38-45: LGTM! Kick logic correctly migrated.

The kick handling properly:

  • Looks up the kicker via federation.mui
  • Uses room._id for the removal operation
  • Maintains the fallback for missing kicker users
  • Correctly logs with updated identifiers
ee/packages/federation-matrix/src/api/_matrix/invite.ts (2)

214-216: LGTM! Room lookup correctly uses native federation fields.

The room lookup properly queries using federation.mrid to find existing mapped rooms.


259-262: Federation metadata is set on room creation — no change required.

Rooms.setAsFederated(...) is called after room creation in ee/packages/federation-matrix/src/FederationMatrix.ts (lines 217, 402) and in apps/meteor/ee/server/hooks/federation/index.ts (lines 30–41); the implementation (packages/models/src/models/Rooms.ts:670–672) sets federated=true and writes federation.mrid and federation.origin.

packages/core-services/src/types/IFederationMatrixService.ts (4)

1-1: LGTM! Import correctly updated to include IRoomNativeFederated.

The import statement properly includes the new IRoomNativeFederated type needed for the migrated federation methods.


18-18: LGTM! createRoom now returns federation identifiers.

The return type change to include room_id and event_id aligns with the federation requirements and allows proper tracking of federated rooms.


27-30: LGTM! Methods correctly updated to use full room and user objects.

The signature changes for kickUser, updateMessage, updateRoomName, and updateRoomTopic properly transition from passing IDs to passing full objects, which provides better type safety and access to federation fields.


31-36: LGTM! addUserRoleRoomScoped correctly uses IRoomNativeFederated.

The method signature properly uses the native federated room type for role management operations.

apps/meteor/ee/server/hooks/federation/index.ts (8)

22-33: LGTM! Room federation setup correctly handles the createRoom result.

The code properly:

  • Handles the result from FederationMatrix.createRoom
  • Extracts the room_id and derives the origin from it
  • Calls setAsFederated with the correct federation data

38-41: LGTM! Federated room ID handling is consistent.

The code properly handles pre-existing federated room IDs by extracting the origin and setting the federation data.


162-162: LGTM! kickUser correctly passes the room object.

The method call properly passes the full room object instead of just the room ID, aligning with the new signature.


171-174: LGTM! Room name change correctly passes user object.

The callback properly passes the full user object to updateRoomName, aligning with the new signature requirements.


182-185: LGTM! Room topic change correctly passes room and user objects.

The callback properly passes both the full room and user objects to updateRoomTopic.


199-199: LGTM! Message update correctly passes room object.

The updateMessage call properly passes the full room object along with the message.


209-209: LGTM! Role change correctly passes room object.

The addUserRoleRoomScoped call properly passes the full room object for scoped role management.


49-51: Clarify conditional: allow federation when FederationActions.shouldPerformFederationAction(room) OR isUserNativeFederated(user).
The guard if (!FederationActions.shouldPerformFederationAction(room) && !isUserNativeFederated(user)) return; means execution proceeds only if FederationActions.shouldPerformFederationAction(room) || isUserNativeFederated(user); confirm this is intended and add a test or doc. (apps/meteor/ee/server/hooks/federation/index.ts:49–51)

Likely an incorrect or invalid review comment.

ee/packages/federation-matrix/src/FederationMatrix.ts (8)

8-16: Good move: shift to native federation type guards and enums

Using isRoomNativeFederated/isUserNativeFederated and UserStatus aligns this service with the new native federation model and removes bridged-model coupling.


198-207: Room-type gate is fine

Restricting creation to public/private channels ('c'/'p') is appropriate here.


217-218: Correctly marking rooms as native‑federated

Persisting MRID/origin via Rooms.setAsFederated is the right replacement for bridged room mapping.


402-405: DM: mark room as native‑federated

Consistent with channels, updating MRID/origin here is correct.


550-558: User MUI derivation is correct

Falling back to @username:server for non‑native users fits the native‑federation design.


771-789: Leave room flow looks correct

Native federated room check + MUI derivation + homeserver call sequence is sound.


824-849: Update message: correct MUI derivation and formatted content

Good use of toExternalMessageFormat and guarding for missing eventId.


141-158: Verified — findUserFederatedRoomIds projects externalRoomId

Model returns AggregationCursor<{ _id: IRoom['_id']; externalRoomId: string }> and projects externalRoomId from room.federation.mrid (packages/models/src/models/Subscriptions.ts:2060, 2083); no change required — fanout already filters falsy targets via .filter(Boolean).

await Message.saveSystemMessage('room_changed_topic', rid, roomTopic || '', user);
}
await callbacks.run('afterRoomTopicChange', undefined, { room, topic: roomTopic, userId: user._id });
await callbacks.run('afterRoomTopicChange', undefined, { room, topic: roomTopic, user });
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Pass userId for compatibility with existing handlers.

Current payload changed to user. Provide userId too to minimize breakage and align with callbacks type update.

Apply this diff:

-	await callbacks.run('afterRoomTopicChange', undefined, { room, topic: roomTopic, user });
+	await callbacks.run('afterRoomTopicChange', undefined, { room, topic: roomTopic, user, userId: user._id });

Additionally, consider typing the parameter as AtLeast<IUser, '_id' | 'username'> or loading the full IUser before invoking callbacks.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
await callbacks.run('afterRoomTopicChange', undefined, { room, topic: roomTopic, user });
await callbacks.run('afterRoomTopicChange', undefined, { room, topic: roomTopic, user, userId: user._id });
🤖 Prompt for AI Agents
In apps/meteor/app/channel-settings/server/functions/saveRoomTopic.ts around
line 31, the callbacks.run('afterRoomTopicChange', ...) call currently passes
user but omits userId; update the payload to include userId (user._id) alongside
user to maintain compatibility with existing handlers, and consider typing the
parameter as AtLeast<IUser, '_id' | 'username'> or load/ensure a full IUser
before invoking callbacks so the userId and username are present.

'afterDeleteUser': (user: IUser) => void;
'afterFileUpload': (params: { user: IUser; room: IRoom; message: IMessage }) => void;
'afterRoomNameChange': (params: { room: IRoom; name: string; oldName: string; userId: IUser['_id'] }) => void;
'afterRoomNameChange': (params: { room: IRoom; name: string; oldName: string; user: IUser }) => void;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid breaking existing listeners: keep userId as a backward‑compat payload field.

Many callbacks likely read params.userId. Add an optional userId while introducing user to avoid ecosystem breakage.

Apply this diff:

-	'afterRoomNameChange': (params: { room: IRoom; name: string; oldName: string; user: IUser }) => void;
+	'afterRoomNameChange': (params: { room: IRoom; name: string; oldName: string; user: IUser; userId?: IUser['_id'] }) => void;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
'afterRoomNameChange': (params: { room: IRoom; name: string; oldName: string; user: IUser }) => void;
'afterRoomNameChange': (params: { room: IRoom; name: string; oldName: string; user: IUser; userId?: IUser['_id'] }) => void;
🤖 Prompt for AI Agents
In apps/meteor/lib/callbacks.ts around line 51, the afterRoomNameChange callback
type was changed to include user but removed the legacy userId; update the
params type to include both the new user?: IUser and the backward-compatible
userId?: string (optional) so existing listeners that read params.userId
continue to work while new code can use params.user.

Comment on lines +208 to 209
'afterRoomTopicChange': (params: undefined, { room, topic, user }: { room: IRoom; topic: string; user: IUser }) => void;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Match topic-change callback payload with name-change: add optional userId.

Keeps parity and eases migration for handlers still expecting userId.

Apply this diff:

-	'afterRoomTopicChange': (params: undefined, { room, topic, user }: { room: IRoom; topic: string; user: IUser }) => void;
+	'afterRoomTopicChange': (params: undefined, { room, topic, user, userId }: { room: IRoom; topic: string; user: IUser; userId?: IUser['_id'] }) => void;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
'afterRoomTopicChange': (params: undefined, { room, topic, user }: { room: IRoom; topic: string; user: IUser }) => void;
};
'afterRoomTopicChange': (params: undefined, { room, topic, user, userId }: { room: IRoom; topic: string; user: IUser; userId?: IUser['_id'] }) => void;
};
🤖 Prompt for AI Agents
In apps/meteor/lib/callbacks.ts around lines 208-209, the afterRoomTopicChange
callback payload currently types the second parameter as { room: IRoom; topic:
string; user: IUser }; update that type to include an optional userId property
to match name-change parity — e.g. { room: IRoom; topic: string; user: IUser;
userId?: string } — so handlers that still expect userId continue to work;
adjust any related type exports or usages if needed.

Comment on lines +22 to +26
const [, serverName] = data.sender.split(':');
if (!serverName) {
throw new Error('Invalid sender format, missing server name');
}

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Bug: serverName parsing breaks when homeserver uses a port

Matrix user IDs are @localpart:serverName[:port]. split(':') drops the port. Use first-colon split or slice after the first colon.

-const [, serverName] = data.sender.split(':');
-if (!serverName) {
+const firstColon = data.sender.indexOf(':');
+const serverName = firstColon >= 0 ? data.sender.slice(firstColon + 1) : '';
+if (!serverName) {
 	throw new Error('Invalid sender format, missing server name');
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const [, serverName] = data.sender.split(':');
if (!serverName) {
throw new Error('Invalid sender format, missing server name');
}
const firstColon = data.sender.indexOf(':');
const serverName = firstColon >= 0 ? data.sender.slice(firstColon + 1) : '';
if (!serverName) {
throw new Error('Invalid sender format, missing server name');
}
🤖 Prompt for AI Agents
In ee/packages/federation-matrix/src/events/invite.ts around lines 22-26, the
current code uses data.sender.split(':') which drops a homeserver port; instead
find the first colon and slice after it so the serverName retains any additional
colons/port. Replace the split with: locate the index of the first ':' in
data.sender, throw if not found, then set serverName =
data.sender.slice(firstColon + 1) and validate it's non-empty.

Comment on lines 219 to 226
for await (const member of members) {
if (member === owner.username) {
continue;
}

try {
// TODO: Check if it is external user - split domain etc
const localUserId = await Users.findOneByUsername(member);
if (localUserId) {
await MatrixBridgedUser.createOrUpdateByLocalId(localUserId._id, member, false, this.serverName);
// continue;
}
} catch (error) {
this.logger.error('Error creating or updating bridged user:', error);
}
// We are not generating bridged users for members outside of the current workspace
// They will be created when the invite is accepted

await this.homeserverServices.invite.inviteUserToRoom(member, matrixRoomResult.room_id, matrixUserId);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Normalize invitee identifiers to valid Matrix user IDs

inviteUserToRoom likely expects Matrix user IDs. Passing raw Rocket.Chat usernames (no '@' or domain) will fail for locals and inconsistent for remotes.

Apply normalization:

-            for await (const member of members) {
+            for (const member of members) {
               if (member === owner.username) {
                 continue;
               }
-              await this.homeserverServices.invite.inviteUserToRoom(member, matrixRoomResult.room_id, matrixUserId);
+              const invitee = member.includes(':')
+                ? (member.startsWith('@') ? member : `@${member}`)
+                : `@${member}:${this.serverName}`;
+              await this.homeserverServices.invite.inviteUserToRoom(invitee, matrixRoomResult.room_id, matrixUserId);
             }

Also consider skipping local users entirely if they are auto-joined by your flow.

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +117 to 119
// Matrix's room ID. Example: !XqJXqZxXqJXq:matrix.org
mrid: string;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Typing bug: federation.origin is used elsewhere but not declared here.

Rooms.setAsFederated sets federation.origin; Statistics depends on it. Add origin to the type.

Apply this diff:

 export interface IRoomNativeFederated extends IRoomFederated {
 	federation: {
 		version: number;
-		// Matrix's room ID. Example: !XqJXqZxXqJXq:matrix.org
-		mrid: string;
+		// Matrix's room ID. Example: !XqJXqZxXqJXq:matrix.org
+		mrid: string;
+		// Origin homeserver of the room (server name)
+		origin: string;
 	};
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Matrix's room ID. Example: !XqJXqZxXqJXq:matrix.org
mrid: string;
};
export interface IRoomNativeFederated extends IRoomFederated {
federation: {
version: number;
// Matrix's room ID. Example: !XqJXqZxXqJXq:matrix.org
mrid: string;
// Origin homeserver of the room (server name)
origin: string;
};
}
🤖 Prompt for AI Agents
In packages/core-typings/src/IRoom.ts around lines 117-119, the
federation.origin field is referenced elsewhere but not declared in the type;
update the IRoom federation property to include origin: string (non-optional) so
Room.setAsFederated and Statistics consumers compile correctly, and
run/typecheck tests to ensure no other type errors.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
ee/packages/federation-matrix/src/api/_matrix/invite.ts (1)

186-203: Code duplication - extract user creation logic.

This user creation logic is duplicated from ee/packages/federation-matrix/src/events/invite.ts. Extract it to a shared utility function.

Would you like me to create a shared utility function for federated user creation to eliminate this duplication?

ee/packages/federation-matrix/src/FederationMatrix.ts (3)

107-107: Fix env flag parsing: enableThumbnails is always true

=== 'true' || true makes the value unconditionally true. Parse the env var correctly.

-				enableThumbnails: process.env.MEDIA_ENABLE_THUMBNAILS === 'true' || true,
+				enableThumbnails: (process.env.MEDIA_ENABLE_THUMBNAILS ?? 'true') === 'true',

250-256: Username normalization can produce invalid IDs (e.g., @@foo:server)

Building externalUserId from username can double-prefix @ or miss the domain. Also compute localName from the normalized value.

-				if (!username.includes(':') && !username.includes('@')) {
+				if (!username.includes(':') && !username.includes('@')) {
 					continue;
 				}
-
-				const externalUserId = username.includes(':') ? `@${username}` : `@${username}:${this.serverName}`;
+				const externalUserId = username.includes(':')
+					? (username.startsWith('@') ? username : `@${username}`)
+					: (username.startsWith('@') ? `${username}:${this.serverName}` : `@${username}:${this.serverName}`);
@@
-				const localName = username.split(':')[0]?.replace('@', '') || username;
+				const localName = externalUserId.replace(/^@/, '').split(':')[0];

Also applies to: 269-276


644-661: Normalize invitees to @user:domain in inviteUsersToRoom

Usernames without @ will likely be rejected by the homeserver.

-					.map(async (username) => {
+					.map(async (username) => {
 						const alreadyMember = await Subscriptions.findOneByRoomIdAndUsername(room._id, username, { projection: { _id: 1 } });
 						if (alreadyMember) {
 							return;
 						}
 
-						await this.homeserverServices.invite.inviteUserToRoom(username, room.federation.mrid, inviterUserId);
+						const invitee = username.startsWith('@') ? username : `@${username}`;
+						await this.homeserverServices.invite.inviteUserToRoom(invitee, room.federation.mrid, inviterUserId);
 					}),
🧹 Nitpick comments (7)
apps/meteor/ee/server/hooks/federation/index.ts (3)

60-63: Use project logger instead of console.error.

Align with Rocket.Chat logging (structured logs, levels, context).

Example:

- console.error('[sendMessage] Failed to send message to Native Federation:', error);
+ SystemLogger.error({ msg: 'Native Federation sendMessage failed', rid: room?._id, mid: message?._id, err: error });

(adapt to the repo’s logger utility in use)


75-77: External-user detection via “:”.

This heuristic is brittle. Prefer a dedicated helper to detect Matrix/remote users (handles “@user:server”, ports, IPv6, future formats).

Happy to draft a small util like isExternalFederatedUsername(username: string): boolean and reuse across reactions/delete/update.


28-41: Optional: extract a helper to parse origin once.

Avoid duplication and inconsistent parsing.

Add:

function originFromMrid(mrid: string): string {
  const i = mrid.indexOf(':');
  return i >= 0 ? mrid.slice(i + 1) : '';
}

Then:

- const fromServer = room_id.slice(room_id.indexOf(':') + 1);
+ const fromServer = originFromMrid(room_id);
...
- const fromServer = federatedRoomId.slice(federatedRoomId.indexOf(':') + 1);
+ const fromServer = originFromMrid(federatedRoomId);
ee/packages/federation-matrix/src/events/invite.ts (1)

27-43: Consider extracting user creation to a shared utility.

The user creation logic appears in multiple places (invite.ts and api/_matrix/invite.ts). Consider extracting this to a shared utility function to ensure consistency and reduce duplication.

Create a shared utility:

// In a new file: ee/packages/federation-matrix/src/utils/userCreation.ts
export async function createFederatedUser(mui: string, origin: string, displayName?: string) {
  return Users.insertOne({
    username: mui,
    type: 'user',
    status: UserStatus.ONLINE,
    active: true,
    roles: ['user'],
    name: displayName || mui,
    requirePasswordChange: false,
    createdAt: new Date(),
    _updatedAt: new Date(),
    federated: true,
    federation: {
      version: 1,
      mui,
      origin,
    },
  });
}
ee/packages/federation-matrix/src/api/_matrix/invite.ts (2)

179-183: Add projection for performance optimization.

When checking user existence, add a projection to only fetch the _id field for better performance.

-const senderUser = await Users.findOne({ 'federation.mui': inviteEvent.sender }, { projection: { _id: 1 } });
+const senderUser = await Users.findOne({ 'federation.mui': inviteEvent.sender }, { projection: { _id: 1 } });

284-287: Remove commented-out code.

This TODO comment with the commented-out code should be either addressed or removed entirely for cleaner code.

-// TODO is this needed?
-// if (isDM) {
-// 	await MatrixBridgedRoom.createOrUpdateByLocalRoomId(internalRoomId, inviteEvent.roomId, matrixRoom.origin);
-// }
ee/packages/federation-matrix/src/FederationMatrix.ts (1)

664-665: Microcopy: “a user”, not “an user”

Minor log grammar nit.

-			this.logger.error({ msg: 'Failed to invite an user to Matrix:', err: error });
+			this.logger.error({ msg: 'Failed to invite a user to Matrix:', err: error });
📜 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.

📥 Commits

Reviewing files that changed from the base of the PR and between 70ceecd and 3445d55.

📒 Files selected for processing (32)
  • apps/meteor/app/channel-settings/server/functions/saveRoomName.ts (1 hunks)
  • apps/meteor/app/channel-settings/server/functions/saveRoomTopic.ts (1 hunks)
  • apps/meteor/app/lib/server/functions/createRoom.ts (1 hunks)
  • apps/meteor/app/lib/server/functions/setUserActiveStatus.ts (1 hunks)
  • apps/meteor/ee/server/hooks/federation/index.ts (8 hunks)
  • apps/meteor/lib/callbacks.ts (2 hunks)
  • apps/meteor/server/models.ts (0 hunks)
  • apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Statistics.ts (2 hunks)
  • ee/packages/federation-matrix/src/FederationMatrix.ts (22 hunks)
  • ee/packages/federation-matrix/src/api/_matrix/invite.ts (4 hunks)
  • ee/packages/federation-matrix/src/events/edu.ts (4 hunks)
  • ee/packages/federation-matrix/src/events/invite.ts (3 hunks)
  • ee/packages/federation-matrix/src/events/member.ts (2 hunks)
  • ee/packages/federation-matrix/src/events/message.ts (2 hunks)
  • ee/packages/federation-matrix/src/events/room.ts (1 hunks)
  • ee/packages/federation-matrix/src/helpers/identifiers.ts (0 hunks)
  • packages/core-services/src/types/IFederationMatrixService.ts (2 hunks)
  • packages/core-typings/src/IRoom.ts (1 hunks)
  • packages/core-typings/src/IUser.ts (2 hunks)
  • packages/core-typings/src/federation/IMatrixBridgedRoom.ts (0 hunks)
  • packages/core-typings/src/federation/IMatrixBridgedUser.ts (0 hunks)
  • packages/core-typings/src/federation/index.ts (0 hunks)
  • packages/model-typings/src/index.ts (0 hunks)
  • packages/model-typings/src/models/IMatrixBridgedRoomModel.ts (0 hunks)
  • packages/model-typings/src/models/IMatrixBridgedUserModel.ts (0 hunks)
  • packages/model-typings/src/models/IRoomsModel.ts (2 hunks)
  • packages/models/src/index.ts (0 hunks)
  • packages/models/src/modelClasses.ts (0 hunks)
  • packages/models/src/models/MatrixBridgedRoom.ts (0 hunks)
  • packages/models/src/models/MatrixBridgedUser.ts (0 hunks)
  • packages/models/src/models/Rooms.ts (2 hunks)
  • packages/models/src/models/Subscriptions.ts (1 hunks)
💤 Files with no reviewable changes (12)
  • packages/models/src/modelClasses.ts
  • packages/models/src/index.ts
  • packages/model-typings/src/models/IMatrixBridgedUserModel.ts
  • packages/model-typings/src/index.ts
  • packages/core-typings/src/federation/IMatrixBridgedRoom.ts
  • packages/core-typings/src/federation/index.ts
  • packages/core-typings/src/federation/IMatrixBridgedUser.ts
  • ee/packages/federation-matrix/src/helpers/identifiers.ts
  • apps/meteor/server/models.ts
  • packages/models/src/models/MatrixBridgedRoom.ts
  • packages/models/src/models/MatrixBridgedUser.ts
  • packages/model-typings/src/models/IMatrixBridgedRoomModel.ts
🚧 Files skipped from review as they are similar to previous changes (13)
  • apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Statistics.ts
  • ee/packages/federation-matrix/src/events/room.ts
  • apps/meteor/app/channel-settings/server/functions/saveRoomName.ts
  • packages/core-typings/src/IRoom.ts
  • ee/packages/federation-matrix/src/events/edu.ts
  • apps/meteor/app/lib/server/functions/setUserActiveStatus.ts
  • apps/meteor/app/lib/server/functions/createRoom.ts
  • apps/meteor/lib/callbacks.ts
  • packages/model-typings/src/models/IRoomsModel.ts
  • packages/models/src/models/Subscriptions.ts
  • apps/meteor/app/channel-settings/server/functions/saveRoomTopic.ts
  • ee/packages/federation-matrix/src/events/message.ts
  • packages/core-typings/src/IUser.ts
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: rodrigok
PR: RocketChat/Rocket.Chat#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.
📚 Learning: 2025-09-19T15:15:04.642Z
Learnt from: rodrigok
PR: RocketChat/Rocket.Chat#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:

  • apps/meteor/ee/server/hooks/federation/index.ts
  • packages/core-services/src/types/IFederationMatrixService.ts
  • ee/packages/federation-matrix/src/FederationMatrix.ts
🧬 Code graph analysis (7)
ee/packages/federation-matrix/src/events/member.ts (2)
ee/packages/federation-matrix/src/events/room.ts (1)
  • room (6-59)
packages/core-services/src/index.ts (1)
  • Room (167-167)
ee/packages/federation-matrix/src/api/_matrix/invite.ts (1)
packages/core-services/src/index.ts (1)
  • Room (167-167)
packages/models/src/models/Rooms.ts (1)
packages/core-typings/src/IRoom.ts (1)
  • IRoom (21-95)
ee/packages/federation-matrix/src/events/invite.ts (2)
ee/packages/federation-matrix/src/events/room.ts (1)
  • room (6-59)
packages/core-services/src/index.ts (1)
  • Room (167-167)
apps/meteor/ee/server/hooks/federation/index.ts (2)
ee/packages/federation-matrix/src/FederationMatrix.ts (1)
  • FederationMatrix (46-938)
packages/core-typings/src/IUser.ts (1)
  • isUserNativeFederated (275-276)
packages/core-services/src/types/IFederationMatrixService.ts (3)
packages/core-typings/src/IRoom.ts (2)
  • IRoomFederated (109-112)
  • IRoomNativeFederated (114-120)
ee/packages/federation-matrix/src/events/message.ts (1)
  • message (123-293)
packages/core-typings/src/IMessage/IMessage.ts (1)
  • IMessage (138-238)
ee/packages/federation-matrix/src/FederationMatrix.ts (6)
packages/core-typings/src/IUser.ts (2)
  • isUserNativeFederated (275-276)
  • IUser (186-255)
ee/packages/federation-matrix/src/events/room.ts (1)
  • room (6-59)
packages/core-typings/src/IRoom.ts (3)
  • IRoom (21-95)
  • IRoomNativeFederated (114-120)
  • isRoomNativeFederated (124-125)
ee/packages/federation-matrix/src/events/member.ts (1)
  • member (9-51)
ee/packages/federation-matrix/src/events/reaction.ts (1)
  • reaction (10-93)
ee/packages/federation-matrix/src/helpers/message.parsers.ts (1)
  • toExternalMessageFormat (201-212)
⏰ 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 (28)
apps/meteor/ee/server/hooks/federation/index.ts (7)

2-3: Imports look good.

Type-only imports are correct; adding isUserNativeFederated and Rooms aligns with downstream usage.


49-52: Re-evaluate OR condition for send path.

As written, a native‑federated user in a non‑federated room will trigger sendMessage(room, …) with a non‑federated room, likely erroring and spamming logs.

Consider tightening:

- if (!FederationActions.shouldPerformFederationAction(room) && !isUserNativeFederated(user)) {
+ if (!FederationActions.shouldPerformFederationAction(room) || !room?.federation?.mrid) {
   return;
 }

If the OR is intentional, add a guard for room.federation?.mrid before calling sendMessage.


53-59: Good loop-avoidance guard.

Skipping when message already has a federation eventId avoids echo loops.


162-162: kickUser API usage matches new signature.

Passing room and full users aligns with FederationMatrix.kickUser.


171-174: updateRoomName call signature is correct.

rid + name + full user matches the new API.


182-185: updateRoomTopic call signature is correct.

Passing the full room, topic, and user matches the API.


209-209: addUserRoleRoomScoped usage matches new signature.

Room + fromUserId + userId + role is consistent with API.

ee/packages/federation-matrix/src/events/member.ts (4)

18-22: LGTM! Room lookup correctly migrated to federation model.

The change from MatrixBridgedRoom to directly querying Rooms with federation.mrid aligns with the broader federation refactor, eliminating the bridging layer.


25-29: LGTM! User lookup correctly uses federation identifier.

The migration to query users by federation.mui is consistent with the new federated user model.


34-35: LGTM! API calls updated to use room._id consistently.

The update to use room._id instead of room.rid properly aligns with the new room lookup structure.


38-45: LGTM! Kick logic properly handles federated users.

The kicker user lookup and subsequent removal with proper fallback to a default user when the kicker is not found is well-implemented.

packages/models/src/models/Rooms.ts (2)

670-672: LGTM! Federation metadata properly structured.

The updated setAsFederated signature correctly stores both the Matrix room ID (mrid) and origin server, supporting the federated room model.


2217-2220: Wrong return type - callers expect string array not number.

ee/packages/federation-matrix/src/events/invite.ts (2)

9-13: LGTM! Room lookup properly uses federation identifier.

The migration from MatrixBridgedRoom to direct Rooms model query with federation.mrid aligns with the federation refactor.


22-26: serverName parsing incorrectly drops port numbers.

ee/packages/federation-matrix/src/api/_matrix/invite.ts (2)

208-210: Good defensive programming with user ID validation.

The explicit check for senderUserId after user creation/lookup prevents downstream issues.


214-216: LGTM! Room lookup correctly uses federation identifier.

The migration to query rooms by federation.mrid is consistent with the new federated room model.

packages/core-services/src/types/IFederationMatrixService.ts (4)

18-18: LGTM! Return type properly reflects Matrix API response.

The updated return type Promise<{ room_id: string; event_id: string } | undefined> properly captures the Matrix homeserver response, enabling callers to track created rooms.


22-22: Verify all callers handle the new matrixRoomId parameter.


27-30: API improvements align with federation-native model.

The changes to accept IRoomNativeFederated and full IUser objects instead of simple IDs provide richer context and align with the federation-native architecture.


32-36: LGTM! Consistent use of IRoomNativeFederated.

The update to use IRoomNativeFederated for addUserRoleRoomScoped maintains consistency with other method signatures.

ee/packages/federation-matrix/src/FederationMatrix.ts (7)

689-691: LGTM: reaction sender resolution

Using native MUI when available and falling back to @username:server is correct.

Consider whether emojis outside shortname form are already normalized upstream.


829-847: LGTM: updateMessage uses federated room ID and sender MUI

Correctly parses and updates the formatted message, scoped to room’s mrid.


857-871: LGTM: updateRoomName resolves room by rid and uses sender MUI

Validation and operation look consistent with the new native federated model.


880-883: LGTM: updateRoomTopic uses setRoomTopic(roomId, userMui, topic)

Matches API expectations.


900-919: LGTM with a note: role-to-power mapping

Owner=100, Moderator=50, User=0 is reasonable. Leader is explicitly unsupported.

Confirm that upstream Matrix power-level defaults for “user” meet your moderation needs.


217-226: Normalize invitees to valid Matrix IDs and skip locals when creating rooms

Inviting raw usernames will fail for externals and create inconsistent IDs. Normalize to @user:domain and avoid inviting local users (handled by RC join flow).

-			for await (const member of members) {
+			for await (const member of members) {
 				if (member === owner.username) {
 					continue;
 				}
-
-				// We are not generating bridged users for members outside of the current workspace
-				// They will be created when the invite is accepted
-
-				await this.homeserverServices.invite.inviteUserToRoom(member, matrixRoomResult.room_id, matrixUserId);
+				// Only invite external users; local users are joined internally
+				const invitee = member.includes(':')
+					? (member.startsWith('@') ? member : `@${member}`)
+					: null;
+				if (!invitee) {
+					continue;
+				}
+				await this.homeserverServices.invite.inviteUserToRoom(invitee, matrixRoomResult.room_id, matrixUserId);
 			}

368-391: Critical: DM bootstrap stores local Mongo _id into federation.mui

The lookup uses {'federation.mui': memberId} and inserts with mui: memberId. memberId is the RC user _id, not a Matrix user ID. This corrupts federation data.

-					if (memberId) {
-						const existingMemberMatrixUserId = await Users.findOne({ 'federation.mui': memberId });
-						if (!existingMemberMatrixUserId) {
-							const newUser = {
-								username: memberId,
-								name: memberId,
+					if (memberId) {
+						const originDomain = memberMatrixUserId.split(':').pop();
+						const existingByMui = await Users.findOne(
+							{ 'federation.mui': memberMatrixUserId },
+							{ projection: { _id: 1 } },
+						);
+						if (!existingByMui) {
+							const sanitizedUsername = memberMatrixUserId;
+							const newUser = {
+								username: sanitizedUsername,
+								name: sanitizedUsername.replace(/^@/, '').split(':')[0],
 								type: 'user' as const,
 								status: UserStatus.OFFLINE,
 								active: true,
 								roles: ['user'],
 								requirePasswordChange: false,
 								federated: true,
 								federation: {
 									version: 1,
-									mui: memberId,
-									origin: memberMatrixUserId.split(':').pop(),
+									mui: memberMatrixUserId,
+									origin: originDomain,
 								},
 								createdAt: new Date(),
 								_updatedAt: new Date(),
 							};
 
 							await Users.insertOne(newUser);
 						}
 					}

@codecov
Copy link

codecov bot commented Sep 23, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 67.34%. Comparing base (d2d81d2) to head (ce2a254).
⚠️ Report is 2 commits behind head on chore/federation-backup.

Additional details and impacted files

Impacted file tree graph

@@                   Coverage Diff                    @@
##           chore/federation-backup   #37035   +/-   ##
========================================================
  Coverage                    67.33%   67.34%           
========================================================
  Files                         3342     3342           
  Lines                       113379   113374    -5     
  Branches                     20657    20652    -5     
========================================================
+ Hits                         76346    76347    +1     
- Misses                       34427    34429    +2     
+ Partials                      2606     2598    -8     
Flag Coverage Δ
e2e 56.92% <ø> (+<0.01%) ⬆️
unit 71.26% <ø> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

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

@ggazzo ggazzo added this to the 7.11.0 milestone Sep 23, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
packages/models/src/models/Rooms.ts (1)

670-672: Persisting mrid/origin is good; add supporting indexes to avoid scans.

The write looks fine. For scale, add sparse indexes on federation.origin (and likely federation.mrid) to support distinct/lookup patterns introduced by the new API.

Add to modelIndexes():

// Add near other federation-related indexes
{ key: { 'federation.origin': 1 }, sparse: true },
{ key: { 'federation.mrid': 1 }, sparse: true },
apps/meteor/ee/server/hooks/federation/index.ts (2)

57-67: Prefer server logger over console.

Route errors to the platform logger (e.g., SystemLogger) for consistency and observability.


106-107: Trim trailing space in callback id.

Trailing space makes handler names brittle.

Apply:

-	'native-federation-on-add-users-to-room ',
+	'native-federation-on-add-users-to-room',
📜 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.

📥 Commits

Reviewing files that changed from the base of the PR and between 3445d55 and 7071eb6.

📒 Files selected for processing (3)
  • apps/meteor/ee/server/hooks/federation/index.ts (8 hunks)
  • packages/model-typings/src/models/IRoomsModel.ts (2 hunks)
  • packages/models/src/models/Rooms.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/model-typings/src/models/IRoomsModel.ts
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: rodrigok
PR: RocketChat/Rocket.Chat#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.
📚 Learning: 2025-09-19T15:15:04.642Z
Learnt from: rodrigok
PR: RocketChat/Rocket.Chat#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:

  • apps/meteor/ee/server/hooks/federation/index.ts
🧬 Code graph analysis (2)
packages/models/src/models/Rooms.ts (1)
packages/core-typings/src/IRoom.ts (1)
  • IRoom (21-95)
apps/meteor/ee/server/hooks/federation/index.ts (3)
ee/packages/federation-matrix/src/FederationMatrix.ts (1)
  • FederationMatrix (46-938)
apps/meteor/server/services/room/hooks/BeforeFederationActions.ts (1)
  • FederationActions (6-30)
packages/core-typings/src/IUser.ts (1)
  • isUserNativeFederated (275-276)
⏰ 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)
packages/models/src/models/Rooms.ts (1)

2217-2220: Implement TODO: return distinct external origins; current stub breaks stats.

Callers need the list of distinct federation origins; implement via distinct with optional exclusion.

Apply this diff:

-	async countDistinctFederationRoomsExcluding(_serverNames: string[] = []): Promise<string[]> {
-		// TODO implement
-		return [];
-	}
+	async countDistinctFederationRoomsExcluding(_serverNames: string[] = []): Promise<string[]> {
+		const exclude = (_serverNames || []).filter((s) => !!s);
+		const query: Filter<IRoom> = {
+			federated: true,
+			'federation.origin': {
+				$exists: true,
+				...(exclude.length ? { $nin: exclude } : {}),
+			},
+		};
+		const origins = await this.col.distinct<string>('federation.origin', query);
+		return origins.filter((o): o is string => typeof o === 'string' && o.length > 0);
+	}
apps/meteor/ee/server/hooks/federation/index.ts (9)

79-81: LGTM: external users’ deletions are skipped.

Consistent with current policy.


166-166: LGTM: updated kickUser signature (room, removedUser, userWhoRemoved).

Matches service API.


175-178: LGTM: updateRoomName uses rid and user.

Signature aligns with service.


186-189: LGTM: updateRoomTopic uses room object.

Matches current API.


196-204: Guard missing eventId and catch errors on edit path.

Avoid throwing on non‑federated edits and don’t block local updates.

Apply:

 	async (message: IMessage, { room }) => {
 		if (FederationActions.shouldPerformFederationAction(room)) {
 			if (!isEditedMessage(message)) {
 				return;
 			}
-
-			await FederationMatrix.updateMessage(room, message);
+			if (!message.federation?.eventId) {
+				return;
+			}
+			try {
+				await FederationMatrix.updateMessage(room, message);
+			} catch (error) {
+				console.error('[updateMessage] Failed to federate edit:', error);
+			}
 		}
 	},

213-213: LGTM: addUserRoleRoomScoped call shape is correct.

(room, fromUserId, userId, role) matches service contract.


22-33: Remove redundant Rooms.setAsFederated and avoid brittle server parsing.

FederationMatrix.createRoom already persists { mrid, origin }; this second write is redundant and parses the server incorrectly with split(':')[1].

Apply:

-			const { room_id } = result;
-
-			const fromServer = room_id.split(':')[1];
-
-			await Rooms.setAsFederated(room._id, {
-				mrid: room_id,
-				origin: fromServer,
-			});
+			// FederationMatrix.createRoom already persists mrid/origin via Rooms.setAsFederated.
#!/bin/bash
# Verify duplication inside FederationMatrix
rg -nC3 'createRoom\s*\(' ee/packages/federation-matrix/src/FederationMatrix.ts
rg -nC3 'Rooms\.setAsFederated\(' ee/packages/federation-matrix/src/FederationMatrix.ts

36-41: Don’t parse Matrix server with split(':')[1]; preserve ports/IPv6.

Use slice from the first colon onward.

Apply:

-			const fromServer = federatedRoomId.split(':')[1];
+			const colonIndex = federatedRoomId.indexOf(':');
+			const fromServer = colonIndex === -1 ? federatedRoomId : federatedRoomId.slice(colonIndex + 1);

2-3: No action required — isUserNativeFederated is used (apps/meteor/ee/server/hooks/federation/index.ts:53).

Keep the import; if you remove the isUserNativeFederated guard later, drop the import to avoid an unused symbol.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
apps/meteor/ee/server/lib/engagementDashboard/messages.ts (1)

29-31: Use deletion timestamp (_deletedAt) when recording deleted messages

message.ts is the creation time; deleted records get _deletedAt (BaseRaw sets _deletedAt = new Date()). Record deletions by convertDateToInt(message._deletedAt ?? new Date()) so the event is attributed to the actual deletion day.

Location: apps/meteor/ee/server/lib/engagementDashboard/messages.ts:28-31

Suggested code fragment:
date: convertDateToInt(message._deletedAt ?? new Date()),

ee/packages/federation-matrix/src/FederationMatrix.ts (1)

107-107: Bug: enableThumbnails is always true

=== 'true' || true forces true and ignores the env flag.

-				enableThumbnails: process.env.MEDIA_ENABLE_THUMBNAILS === 'true' || true,
+				enableThumbnails: process.env.MEDIA_ENABLE_THUMBNAILS
+					? process.env.MEDIA_ENABLE_THUMBNAILS === 'true'
+					: true,
packages/core-services/src/types/IFederationMatrixService.ts (1)

18-38: Fix interface/impl mismatches (compile-time blockers)

Several method signatures don’t match the implementation (and intended model). Update to native types and correct params.

-	createRoom(room: IRoomFederated, owner: IUser, members: string[]): Promise<{ room_id: string; event_id: string }>;
+	createRoom(room: IRoom, owner: IUser, members: string[]): Promise<{ room_id: string; event_id: string }>;
@@
-	createDirectMessageRoom(room: IRoomFederated, members: IUser[], creatorId: IUser['_id']): Promise<void>;
+	createDirectMessageRoom(room: IRoom, members: (IUser | string)[], creatorId: IUser['_id']): Promise<void>;
@@
-	sendMessage(message: IMessage, room: IRoomFederated, user: IUser): Promise<void>;
+	sendMessage(message: IMessage, room: IRoomNativeFederated, user: IUser): Promise<void>;
@@
-	getEventById(eventId: string): Promise<any | null>;
+	getEventById(eventId: EventID): Promise<any | null>;
@@
-	leaveRoom(rid: IRoomFederated['_id'], user: IUser): Promise<void>;
+	leaveRoom(rid: string, user: IUser): Promise<void>;
@@
-	inviteUsersToRoom(room: IRoomFederated, usersUserName: string[], inviter: Pick<IUser, '_id' | 'username'>): Promise<void>;
+	inviteUsersToRoom(room: IRoomNativeFederated, usersUserName: string[], inviter: IUser): Promise<void>;
🧹 Nitpick comments (4)
apps/meteor/ee/server/lib/engagementDashboard/messages.ts (2)

24-26: Redundant null-check for room with non-optional type.

Since room is typed as required, !room is unnecessary. Either make it optional again or drop the check. Suggest removing the null-check for consistency.

- if (!room || !roomTypesToShow.includes(room.t)) {
+ if (!roomTypesToShow.includes(room.t)) {
     return message;
   }

8-20: Optional: unify parameter shapes between sent/deleted handlers.

handleMessagesSent accepts { room?: IRoom } while handleMessagesDeleted requires { room: IRoom }. Consider aligning both to the same contract to reduce API friction.

Also applies to: 22-34

ee/packages/federation-matrix/src/FederationMatrix.ts (2)

314-314: Use creator’s MUI when federated

Ensures correct sender when the creator is native federated.

-			const actualMatrixUserId = `@${creator.username}:${this.serverName}`;
+			const actualMatrixUserId = isUserNativeFederated(creator)
+				? creator.federation.mui
+				: `@${creator.username}:${this.serverName}`;

646-661: Use inviter’s MUI when federated

Build inviter ID with federation awareness.

-			const inviterUserId = `@${inviter.username}:${this.serverName}`;
+			const inviterUserId = isUserNativeFederated(inviter)
+				? inviter.federation.mui
+				: `@${inviter.username}:${this.serverName}`;
@@
-						await this.homeserverServices.invite.inviteUserToRoom(username, room.federation.mrid, inviterUserId);
+						await this.homeserverServices.invite.inviteUserToRoom(username, room.federation.mrid, inviterUserId);
📜 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.

📥 Commits

Reviewing files that changed from the base of the PR and between 7071eb6 and 8648eca.

📒 Files selected for processing (6)
  • apps/meteor/app/lib/server/functions/deleteMessage.ts (1 hunks)
  • apps/meteor/ee/server/hooks/federation/index.ts (7 hunks)
  • apps/meteor/ee/server/lib/engagementDashboard/messages.ts (1 hunks)
  • apps/meteor/lib/callbacks.ts (2 hunks)
  • ee/packages/federation-matrix/src/FederationMatrix.ts (22 hunks)
  • packages/core-services/src/types/IFederationMatrixService.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/meteor/lib/callbacks.ts
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: rodrigok
PR: RocketChat/Rocket.Chat#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.
📚 Learning: 2025-09-19T15:15:04.642Z
Learnt from: rodrigok
PR: RocketChat/Rocket.Chat#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:

  • packages/core-services/src/types/IFederationMatrixService.ts
  • apps/meteor/ee/server/hooks/federation/index.ts
  • ee/packages/federation-matrix/src/FederationMatrix.ts
🧬 Code graph analysis (5)
packages/core-services/src/types/IFederationMatrixService.ts (3)
packages/core-typings/src/IRoom.ts (2)
  • IRoomFederated (109-112)
  • IRoomNativeFederated (114-120)
packages/core-typings/src/IUser.ts (1)
  • IUser (186-255)
packages/core-typings/src/IMessage/IMessage.ts (1)
  • IMessage (138-238)
apps/meteor/ee/server/hooks/federation/index.ts (3)
apps/meteor/server/services/room/hooks/BeforeFederationActions.ts (1)
  • FederationActions (6-30)
packages/core-typings/src/IUser.ts (1)
  • isUserNativeFederated (275-276)
ee/packages/federation-matrix/src/FederationMatrix.ts (1)
  • FederationMatrix (46-941)
apps/meteor/app/lib/server/functions/deleteMessage.ts (1)
apps/meteor/lib/callbacks.ts (1)
  • callbacks (251-259)
apps/meteor/ee/server/lib/engagementDashboard/messages.ts (2)
packages/core-typings/src/IMessage/IMessage.ts (1)
  • IMessage (138-238)
packages/core-typings/src/IRoom.ts (1)
  • IRoom (21-95)
ee/packages/federation-matrix/src/FederationMatrix.ts (8)
packages/models/src/index.ts (2)
  • Users (205-205)
  • Rooms (196-196)
packages/core-typings/src/IUser.ts (2)
  • isUserNativeFederated (275-276)
  • IUser (186-255)
ee/packages/federation-matrix/src/events/room.ts (1)
  • room (6-59)
packages/core-typings/src/IRoom.ts (3)
  • IRoom (21-95)
  • IRoomNativeFederated (114-120)
  • isRoomNativeFederated (124-125)
ee/packages/federation-matrix/src/events/member.ts (1)
  • member (9-51)
ee/packages/federation-matrix/src/events/message.ts (1)
  • message (123-293)
ee/packages/federation-matrix/src/events/reaction.ts (1)
  • reaction (10-93)
ee/packages/federation-matrix/src/helpers/message.parsers.ts (1)
  • toExternalMessageFormat (201-212)
⏰ 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)
apps/meteor/ee/server/lib/engagementDashboard/messages.ts (1)

22-27: Signature requires { room } — verification complete.

callbacks.run('afterDeleteMessage', deletedMsg, { room, user }) (apps/meteor/app/lib/server/functions/deleteMessage.ts:96) supplies the object payload and handleMessagesDeleted is registered as the callback (apps/meteor/ee/server/lib/engagementDashboard/startup.ts:12). No direct call sites requiring migration were found.

apps/meteor/app/lib/server/functions/deleteMessage.ts (1)

96-96: Add null-safe message fallback when running afterDeleteMessage; verify listeners

Use a message fallback so callbacks never receive a null first arg.

-	await callbacks.run('afterDeleteMessage', deletedMsg, { room, user });
+	await callbacks.run('afterDeleteMessage', deletedMsg ?? message, { room, user });

Apply in: apps/meteor/app/lib/server/functions/deleteMessage.ts (around line 96)

Verify/inspect these listeners for compatibility:

  • apps/meteor/app/search/server/events/index.ts
  • apps/meteor/app/federation/server/hooks/afterDeleteMessage.js
  • apps/meteor/app/slackbridge/server/RocketAdapter.js
  • apps/meteor/app/discussion/server/hooks/propagateDiscussionMetadata.ts
  • apps/meteor/ee/server/lib/engagementDashboard/startup.ts
  • apps/meteor/ee/server/hooks/federation/index.ts
ee/packages/federation-matrix/src/FederationMatrix.ts (4)

254-286: Prevent duplicate user mappings and fix remote domain parsing

  • Only checking by username risks duplicates; also set username to MUI for consistency.
  • split(':')[1] drops ports/IPv6. Use slice after the first colon.
-				const existingUser = await Users.findOneByUsername(username);
-				if (existingUser) {
-					// TODO review: DM
-					// const existingBridge = await MatrixBridgedUser.getExternalUserIdByLocalUserId(existingUser._id); // TODO review: DM
-					// if (!existingBridge) {
-					// 	const remoteDomain = externalUserId.split(':')[1] || this.serverName;
-					// 	await MatrixBridgedUser.createOrUpdateByLocalId(existingUser._id, externalUserId, true, remoteDomain);
-					// }
-					continue;
-				}
-
-				// TODO: there is not need to check if the username includes ':' or '@', we should just use the username as is
-				const externalUserId = username.includes(':') ? `@${username}` : `@${username}:${this.serverName}`;
+				const externalUserId = username.includes(':')
+					? (username.startsWith('@') ? username : `@${username}`)
+					: `@${username}:${this.serverName}`;
+				const [existingByMui, existingByUsername] = await Promise.all([
+					Users.findOne({ 'federation.mui': externalUserId }, { projection: { _id: 1 } }),
+					Users.findOneByUsername(username, { projection: { _id: 1 } }),
+				]);
+				if (existingByMui || existingByUsername) {
+					continue;
+				}
 				this.logger.debug('Creating federated user locally', { externalUserId, username });
 
-				const remoteDomain = externalUserId.split(':')[1];
+				const remoteDomain = externalUserId.slice(externalUserId.indexOf(':') + 1);
 
 				const localName = username.split(':')[0]?.replace('@', '') || username;
 
 				const newUser = {
-					username,
+					username: externalUserId,
 					name: localName,
 					type: 'user' as const,
 					status: UserStatus.OFFLINE,
 					active: true,
 					roles: ['user'],
 					requirePasswordChange: false,
 					federated: true,
 					federation: {
 						version: 1,
-						mui: externalUserId,
-						origin: remoteDomain,
+						mui: externalUserId,
+						origin: remoteDomain,
 					},
 					createdAt: new Date(),
 					_updatedAt: new Date(),
 				};

633-636: Redaction uses actor UID — good fix

Passing the deleter’s Matrix ID resolves the prior redactor/author confusion.


217-226: Normalize/skip local invitees when creating rooms

Inviting raw usernames (no '@' or domain) will fail; skip local users or normalize to Matrix IDs.

-			for await (const member of members) {
+			for (const member of members) {
 				if (member === owner.username) {
 					continue;
 				}
-
-				// We are not generating bridged users for members outside of the current workspace
-				// They will be created when the invite is accepted
-
-				await this.homeserverServices.invite.inviteUserToRoom(member, matrixRoomResult.room_id, matrixUserId);
+				// Invite only external users; local users are handled by RC
+				const invitee = member.includes(':') ? (member.startsWith('@') ? member : `@${member}`) : null;
+				if (!invitee) {
+					continue;
+				}
+				await this.homeserverServices.invite.inviteUserToRoom(invitee, matrixRoomResult.room_id, matrixUserId);
 			}

368-391: Critical: DM bootstrap uses local _id as MUI

memberId is a local Mongo _id; checks/inserts should be keyed by the Matrix ID (memberMatrixUserId).

-					if (memberId) {
-						const existingMemberMatrixUserId = await Users.findOne({ 'federation.mui': memberId });
-						if (!existingMemberMatrixUserId) {
-							const newUser = {
-								username: memberId,
-								name: memberId,
+					if (memberId) {
+						const originDomain = memberMatrixUserId.slice(memberMatrixUserId.indexOf(':') + 1);
+						const existingByMui = await Users.findOne(
+							{ 'federation.mui': memberMatrixUserId },
+							{ projection: { _id: 1 } },
+						);
+						if (!existingByMui) {
+							const sanitizedUsername =
+								(typeof otherMember !== 'string' && otherMember.username)
+									? (otherMember.username.includes(':') ? (otherMember.username.startsWith('@') ? otherMember.username : `@${otherMember.username}`) : memberMatrixUserId)
+									: memberMatrixUserId;
+							const newUser = {
+								username: sanitizedUsername,
+								name: sanitizedUsername.replace(/^@/, '').split(':')[0],
 								type: 'user' as const,
 								status: UserStatus.OFFLINE,
 								active: true,
 								roles: ['user'],
 								requirePasswordChange: false,
 								federated: true,
 								federation: {
 									version: 1,
-									mui: memberId,
-									origin: memberMatrixUserId.split(':').pop(),
+									mui: memberMatrixUserId,
+									origin: originDomain,
 								},
 								createdAt: new Date(),
 								_updatedAt: new Date(),
 							};
 
 							await Users.insertOne(newUser);
 						}
 					}
apps/meteor/ee/server/hooks/federation/index.ts (4)

186-196: Guard missing eventId and catch errors on edit path

Prevents exceptions from breaking local edits.

-		if (FederationActions.shouldPerformFederationAction(room)) {
-			if (!isEditedMessage(message)) {
-				return;
-			}
-
-			await FederationMatrix.updateMessage(room, message);
-		}
+		if (FederationActions.shouldPerformFederationAction(room)) {
+			if (!isEditedMessage(message)) {
+				return;
+			}
+			if (!message.federation?.eventId) {
+				return;
+			}
+			try {
+				await FederationMatrix.updateMessage(room, message);
+			} catch (err) {
+				console.error('[updateMessage] Native Federation failed', { rid: room?._id, mid: message?._id, err });
+			}
+		}

24-29: Preserve ports/IPv6 when parsing the server from a Matrix ID

split(':')[1] drops “:port” and breaks IPv6. Use slice from the first colon.

-			const fromServer = federatedRoomId.split(':')[1];
+			const colonIndex = federatedRoomId.indexOf(':');
+			const fromServer = colonIndex === -1 ? '' : federatedRoomId.slice(colonIndex + 1);

41-44: Don’t block local users from federating messages

sendMessage handles non‑federated users; this guard drops valid sends.

-		if (!isUserNativeFederated(user)) {
-			return;
-		}

77-79: Don’t let federation delete failures block local deletes

Wrap in try/catch.

-			await FederationMatrix.deleteMessage(room.federation.mrid, message, user.federation.mui);
+			try {
+				await FederationMatrix.deleteMessage(room.federation.mrid, message, user.federation.mui);
+			} catch (err) {
+				console.error('[deleteMessage] Native Federation failed', { rid: room?._id, mid: message?._id, err });
+			}

@@ -1,4 +1,4 @@
import type { AtLeast, IMessage, IRoomFederated, IUser } from '@rocket.chat/core-typings';
import type { IMessage, IRoomFederated, IRoomNativeFederated, IUser } from '@rocket.chat/core-typings';
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Align imports with actual usage (add IRoom, EventID)

Required by updated signatures below.

-import type { IMessage, IRoomFederated, IRoomNativeFederated, IUser } from '@rocket.chat/core-typings';
+import type { IMessage, IRoom, IRoomFederated, IRoomNativeFederated, IUser } from '@rocket.chat/core-typings';
+import type { EventID } from '@hs/room';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import type { IMessage, IRoomFederated, IRoomNativeFederated, IUser } from '@rocket.chat/core-typings';
import type { IMessage, IRoom, IRoomFederated, IRoomNativeFederated, IUser } from '@rocket.chat/core-typings';
import type { EventID } from '@hs/room';
🤖 Prompt for AI Agents
packages/core-services/src/types/IFederationMatrixService.ts around lines 1 to
1: the current import line only brings in IMessage, IRoomFederated,
IRoomNativeFederated, and IUser but the updated signatures require IRoom and
EventID; update the named import from '@rocket.chat/core-typings' to also
include IRoom and EventID so the file references resolve correctly.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
apps/meteor/app/lib/server/methods/sendMessage.ts (1)

58-58: Avoid full user document load on hot path

Fetch only needed fields to reduce I/O and GC pressure during message send.

- const user = await Users.findOneById(uid);
+ const user = await Users.findOneById(uid, { projection: { username: 1, type: 1, language: 1 } });
apps/meteor/ee/server/hooks/federation/index.ts (1)

41-51: Prefer structured logging over console.error

Use SystemLogger for consistency and context.

- console.error('[sendMessage] Failed to send message to Native Federation:', error);
+ SystemLogger.error({ msg: '[sendMessage] Native Federation send failed', err: error });
📜 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.

📥 Commits

Reviewing files that changed from the base of the PR and between 8648eca and 2d74b20.

📒 Files selected for processing (4)
  • apps/meteor/app/lib/server/functions/createDirectRoom.ts (2 hunks)
  • apps/meteor/app/lib/server/methods/sendMessage.ts (1 hunks)
  • apps/meteor/ee/server/hooks/federation/index.ts (8 hunks)
  • apps/meteor/lib/callbacks.ts (3 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: rodrigok
PR: RocketChat/Rocket.Chat#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.
📚 Learning: 2025-09-19T15:15:04.642Z
Learnt from: rodrigok
PR: RocketChat/Rocket.Chat#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:

  • apps/meteor/ee/server/hooks/federation/index.ts
🧬 Code graph analysis (3)
apps/meteor/app/lib/server/functions/createDirectRoom.ts (1)
apps/meteor/lib/callbacks.ts (1)
  • callbacks (251-259)
apps/meteor/lib/callbacks.ts (4)
ee/packages/federation-matrix/src/events/message.ts (1)
  • message (123-293)
packages/core-typings/src/IMessage/IMessage.ts (1)
  • IMessage (138-238)
packages/core-typings/src/IRoom.ts (1)
  • IRoom (21-95)
packages/core-typings/src/IUser.ts (1)
  • IUser (186-255)
apps/meteor/ee/server/hooks/federation/index.ts (3)
apps/meteor/server/services/room/hooks/BeforeFederationActions.ts (1)
  • FederationActions (6-30)
ee/packages/federation-matrix/src/FederationMatrix.ts (1)
  • FederationMatrix (46-941)
packages/core-typings/src/IUser.ts (2)
  • isUserNativeFederated (275-276)
  • IUser (186-255)
⏰ 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 (14)
apps/meteor/app/lib/server/functions/createDirectRoom.ts (2)

49-50: API surface: addition looks good

Optional federatedRoomId on options is fine and backward‑compatible.


183-187: Propagating mrid via callback is correct. callbacks type includes mrid?: string and the EE federation hook reads params.mrid (apps/meteor/lib/callbacks.ts:67; apps/meteor/ee/server/hooks/federation/index.ts:219–221).

apps/meteor/ee/server/hooks/federation/index.ts (8)

60-75: Don’t let federation delete failures block local deletes; add try/catch

Mirror send path resilience; keep local delete successful even if remote fails.

- if (FederationActions.shouldPerformFederationAction(room)) {
-   await FederationMatrix.deleteMessage(room.federation.mrid, message, user.federation.mui);
- }
+ if (FederationActions.shouldPerformFederationAction(room)) {
+   try {
+     await FederationMatrix.deleteMessage(room.federation.mrid, message, user.federation.mui);
+   } catch (err) {
+     SystemLogger.error({ msg: '[deleteMessage] Native Federation deletion failed', rid: room?._id, mid: message?._id, err });
+   }
+ }

190-191: Guard edited-message federation and handle errors

Skip when no eventId; catch errors to avoid breaking local edits.

- await FederationMatrix.updateMessage(room, message);
+ if (message.federation?.eventId) {
+   try {
+     await FederationMatrix.updateMessage(room, message);
+   } catch (err) {
+     SystemLogger.error({ msg: '[updateMessage] Native Federation edit failed', rid: room?._id, mid: message?._id, err });
+   }
+ }

153-154: API migration to object-based kickUser looks good

Passing full room and users matches new FederationMatrix signature.


162-165: Name change flow migration LGTM

Using user object and rid matches updated API.


173-176: Topic change flow migration LGTM

Object-based params match new FederationMatrix.updateRoomTopic signature.


16-31: Incorrect — createRoom already persists mrid/origin; ignore duplicate-write suggestion.

FederationMatrix.createRoom calls Rooms.setAsFederated(room._id, { mrid: matrixRoomResult.room_id, origin: this.serverName }) inside ee/packages/federation-matrix/src/FederationMatrix.ts (around lines ~211–216 and ~397–403), so the branch that calls createRoom does not need an additional setAsFederated; the else branch remains required when options.federatedRoomId is provided.

Likely an incorrect or invalid review comment.


24-30: Bug: origin parsing drops host/IPv6 and keeps only first segment

split(':')[1] breaks IPv6 and removes :port. Preserve everything after the first colon.

- const fromServer = federatedRoomId.split(':')[1];
+ const colon = federatedRoomId.indexOf(':');
+ const fromServer = colon >= 0 ? federatedRoomId.slice(colon + 1) : '';

221-226: Bug: origin computed as just port with split(':').pop()

For mrid like "!abc:example.com:8448", .pop() yields "8448". Keep the full host[:port]/IPv6 by slicing after the first colon.

- await Rooms.setAsFederated(room._id, {
-   mrid: params.mrid,
-   origin: params.mrid.split(':').pop()!,
- });
+ const colon = params.mrid.indexOf(':');
+ const origin = colon >= 0 ? params.mrid.slice(colon + 1) : '';
+ await Rooms.setAsFederated(room._id, { mrid: params.mrid, origin });
apps/meteor/lib/callbacks.ts (4)

51-51: Keep userId as optional for ecosystem parity

Add userId?: string to avoid breaking existing listeners that still read params.userId.

- 'afterRoomNameChange': (params: { room: IRoom; name: string; oldName: string; user: IUser }) => void;
+ 'afterRoomNameChange': (params: { room: IRoom; name: string; oldName: string; user: IUser; userId?: IUser['_id'] }) => void;

208-209: Match topic-change payload parity: add optional userId

Maintain optional userId for smooth migration like name-change.

- 'afterRoomTopicChange': (params: undefined, { room, topic, user }: { room: IRoom; topic: string; user: IUser }) => void;
+ 'afterRoomTopicChange': (
+   params: undefined,
+   { room, topic, user, userId }: { room: IRoom; topic: string; user: IUser; userId?: IUser['_id'] }
+ ) => void;

67-67: afterCreateDirectRoom typing update — LGTM

mrid?: string is present in apps/meteor/lib/callbacks.ts:67 and matches producers/consumers across the PR.


44-44: Ignore type-widening — keep the current afterDeleteMessage signature

callbacks.run is invoked with callbacks.run('afterDeleteMessage', message, { room, user }) and registered handlers in the repo accept either a single message or the params object; I found registrations in apps/meteor/app/search/server/events/index.ts, apps/meteor/app/slackbridge/server/RocketAdapter.js, apps/meteor/ee/server/lib/engagementDashboard/startup.ts and the run call at apps/meteor/app/lib/server/functions/deleteMessage.ts:96. No handlers use (message, room), so widening the type is unnecessary.

Likely an incorrect or invalid review comment.

@ggazzo ggazzo force-pushed the remove-bridged-models branch 2 times, most recently from 2db3419 to 805dd20 Compare September 23, 2025 03:42
@ggazzo ggazzo force-pushed the remove-bridged-models branch from 805dd20 to ce2a254 Compare September 23, 2025 03:44
@ggazzo ggazzo merged commit 370eaaa into chore/federation-backup Sep 23, 2025
20 of 21 checks passed
@ggazzo ggazzo deleted the remove-bridged-models branch September 23, 2025 03:55
@coderabbitai coderabbitai bot mentioned this pull request Sep 23, 2025
ggazzo added a commit that referenced this pull request Sep 23, 2025
Co-authored-by: Guilherme Gazzo <guilherme@gazzo.xyz>
ggazzo added a commit that referenced this pull request Sep 25, 2025
Co-authored-by: Guilherme Gazzo <guilherme@gazzo.xyz>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants