Skip to content

chore: Add OpenAPI Support to rooms.favorite API#35995

Merged
ggazzo merged 9 commits intoRocketChat:developfrom
ahmed-n-abdeltwab:feat/openapi-rooms
Feb 23, 2026
Merged

chore: Add OpenAPI Support to rooms.favorite API#35995
ggazzo merged 9 commits intoRocketChat:developfrom
ahmed-n-abdeltwab:feat/openapi-rooms

Conversation

@ahmed-n-abdeltwab
Copy link
Contributor

@ahmed-n-abdeltwab ahmed-n-abdeltwab commented May 14, 2025

Description:
This PR integrates OpenAPI support into the Rocket.Chat API, migrate of Rocket.Chat API endpoints to the new OpenAPI pattern. The update includes improved API documentation, enhanced type safety, and response validation using AJV.

Key Changes:

  • Implemented the new pattern and added AJV-based JSON schema validation for API.
  • Uses the ExtractRoutesFromAPI utility from the TypeScript definitions to dynamically derive the routes from the endpoint specifications.
  • Enabled Swagger UI integration for this API.
  • Route Methods Chaining for the endpoints.
  • This does not introduce any breaking changes to the endpoint logic.

Issue Reference:
Relates to #34983, part of the ongoing OpenAPI integration effort.

Testing:

  • Verified that the API response schemas are correctly documented in Swagger UI.

  • All tests passed without any breaking changes

    $ yarn testapi -f '[Rooms]'     
    
    
    [Rooms]
      ✔ /rooms.get (147ms)
      ✔ /rooms.get?updatedSince (74ms)
      /rooms.saveNotification:
        ✔ /rooms.saveNotification: (154ms)
      /rooms.upload
        (node:147458) [DEP0044] DeprecationWarning: The `util.isArray` API is deprecated. Please use `Array.isArray()` instead.
        (Use `node --trace-deprecation ...` to show where the warning was created)
        ✔ don't upload a file to room with file field other than file (76ms)
        ✔ don't upload a file to room with empty file
        ✔ don't upload a file to room with more than 1 file (45ms)
        ✔ should upload a PNG file to room (1078ms)
        ✔ should upload a LST file to room (147ms)
        ✔ should upload a DRAWIO file (unknown media type) to room (125ms)
        ✔ should not allow uploading a blocked media type to a room (161ms)
        ✔ should not allow uploading an unknown media type to a room if the default one is blocked (189ms)
        ✔ should be able to get the file (72ms)
        ✔ should be able to get the file when no access to the room if setting allows it (340ms)
        ✔ should not be able to get the file when no access to the room if setting blocks (155ms)
        ✔ should be able to get the file if member and setting blocks outside access (204ms)
        ✔ should be able to get the file if not member but can access room if setting allows (366ms)
        ✔ should not be able to get the file if not member and cannot access room (275ms)
        ✔ should respect the setting with less permissions when both are true (429ms)
        ✔ should not be able to get the file without credentials
        ✔ should be able to get the file without credentials if setting allows (218ms)
        ✔ should generate thumbnail for SVG files correctly (356ms)
        ✔ should generate thumbnail for JPEG files correctly (420ms)
        ✔ should correctly save file description and properties with type e2e (352ms)
      /rooms.media
        ✔ don't upload a file to room with file field other than file (46ms)
        ✔ don't upload a file to room with empty file
        ✔ don't upload a file to room with more than 1 file (39ms)
        ✔ should upload a PNG file to room (218ms)
        ✔ should upload a LST file to room (128ms)
        ✔ should not allow uploading a blocked media type to a room (176ms)
        ✔ should be able to get the file (60ms)
        ✔ should be able to get the file when no access to the room if setting allows it (237ms)
        ✔ should not be able to get the file when no access to the room if setting blocks (184ms)
        ✔ should be able to get the file if member and setting blocks outside access (254ms)
        ✔ should not be able to get the file without credentials (47ms)
        ✔ should be able to get the file without credentials if setting allows (242ms)
        ✔ should generate thumbnail for SVG files correctly (208ms)
        ✔ should generate thumbnail for JPEG files correctly (206ms)
        ✔ should correctly save file description and properties with type e2e (208ms)
        ✔ should correctly save encrypted file (143ms)
        ✔ should correctly save encrypted file with the default media type even if another type is provided (117ms)
        ✔ should fail encrypted file upload when files encryption is disabled (187ms)
        ✔ should fail encrypted file upload on blacklisted application/octet-stream media type (162ms)
        /rooms.media - Max allowed size
          ✔ should allow uploading a file with description under the max character limit (306ms)
          ✔ should not allow uploading a file with description over the max character limit (71ms)
      /rooms.favorite
        ✔ should favorite the room when send favorite: true by roomName
        ✔ should unfavorite the room when send favorite: false by roomName
        ✔ should favorite the room when send favorite: true by roomId
        ✔ should unfavorite room when send favorite: false by roomId
        ✔ should return an error when send an invalid room
      /rooms.nameExists
        ✔ should return 401 unauthorized when user is not logged in
        ✔ should return true if this room name exists
        ✔ should return false if this room name does not exist
        ✔ should return an error when the require parameter (roomName) is not provided
      [/rooms.cleanHistory]
        ✔ should return success when send a valid public channel (53ms)
        ✔ should not count hidden or deleted messages when limit param is not sent (801ms)
        ✔ should not count hidden or deleted messages when limit param is sent (117ms)
        ✔ should successfully delete an image and thumbnail from public channel
        ✔ should remove only files and file attachments when filesOnly is set to true (337ms)
        ✔ should not remove quote attachments when filesOnly is set to true (323ms)
        ✔ should return success when send a valid private channel
        ✔ should return success when send a valid Direct Message channel
        ✔ should return not allowed error when try deleting messages with user without permission (40ms)
        test user is not part of room
          ✔ should return an error when the user with right privileges is not part of the room
      [/rooms.info]
        ✔ should return the info about the created channel correctly searching by roomId
        ✔ should return the info about the created channel correctly searching by roomName
        ✔ should return the info about the created group correctly searching by roomId (43ms)
        ✔ should return the info about the created group correctly searching by roomName
        ✔ should return the info about the created DM correctly searching by roomId
        ✔ should not return parent & team for room thats not on a team nor is a discussion
        with team and parent data
          ✔ should return the channel info, team and parent info
          ✔ should return the dicsussion room info and parent info
          ✔ should not return parent info for the main room of the team
          ✔ should not return team for room outside team
          ✔ should return the parent for discussion outside team
          ✔ should return the parent for a discussion created from team main room
      [/rooms.leave]
        ✔ should return an Error when trying leave a DM room
        ✔ should return an Error when trying to leave a public channel and you are the last owner (53ms)
        ✔ should return an Error when trying to leave a private group and you are the last owner
        ✔ should return an Error when trying to leave a public channel and not have the necessary permission(leave-c) (198ms)
        ✔ should return an Error when trying to leave a private group and not have the necessary permission(leave-p) (207ms)
        ✔ should leave the public channel when the room has at least another owner and the user has the necessary permission(leave-c) (359ms)
        ✔ should leave the private group when the room has at least another owner and the user has the necessary permission(leave-p) (343ms)
      /rooms.createDiscussion
        ✔ should throw an error when the user tries to create a discussion and the feature is disabled (283ms)
        ✔ should throw an error when the user tries to create a discussion and does not have at least one of the required permissions (972ms)
        ✔ should throw an error when the user tries to create a discussion without the required parameter "prid"
        ✔ should throw an error when the user tries to create a discussion without the required parameter "t_name"
        ✔ should throw an error when the user tries to create a discussion with the required parameter invalid "users"(different from an array)
        ✔ should throw an error when the user tries to create a discussion with the channel's id invalid
        ✔ should throw an error when the user tries to create a discussion with the message's id invalid
        ✔ should create a discussion successfully when send only the required parameters (68ms)
        ✔ should create a discussion successfully when send the required parameters plus the optional parameter "reply" (120ms)
        ✔ should create a discussion successfully when send the required parameters plus the optional parameter "users" (127ms)
        ✔ should create a discussion successfully when send the required parameters plus the optional parameter "pmid" (132ms)
        it should create a *private* discussion if the parent channel is public and inside a private team
          ✔ should create a team (60ms)
          ✔ should add the public channel to the team
          ✔ should create a private discussion inside the public channel (65ms)
      /rooms.getDiscussions
        ✔ should throw an error when the user tries to gets a list of discussion without a required parameter "roomId"
        ✔ should throw an error when the user tries to gets a list of discussion and he cannot access the room (358ms)
        ✔ should return a list of discussions with ONE discussion
      [/rooms.autocomplete.channelAndPrivate]
        ✔ should return an error when the required parameter "selector" is not provided
        ✔ should return the rooms to fill auto complete
      [/rooms.autocomplete.channelAndPrivate.withPagination]
        ✔ should return an error when the required parameter "selector" is not provided
        ✔ should return the rooms to fill auto complete (63ms)
        ✔ should return the rooms to fill auto complete even requested with count and offset params
      [/rooms.autocomplete.availableForTeams]
        ✔ should return the rooms to fill auto complete
        ✔ should return the filtered rooms to fill auto complete
      [/rooms.autocomplete.adminRooms]
        - should return an error when the required parameter "selector" is not provided
        ✔ should return the rooms to fill auto complete (44ms)
        ✔ should return the rooms to fill auto complete
      /rooms.adminRooms
        ✔ should throw an error when the user tries to gets a list of discussion and he cannot access the room (362ms)
        ✔ should return a list of admin rooms (41ms)
        ✔ should return a list of admin rooms even requested with count and offset params
        ✔ should search the list of admin rooms using non-latin characters when UI_Allow_room_names_with_special_chars setting is toggled (164ms)
        ✔ should search the list of admin rooms using latin characters only when UI_Allow_room_names_with_special_chars setting is disabled (151ms)
        ✔ should filter by only rooms types (44ms)
        ✔ should filter by only name
        ✔ should filter by type and name at the same query
        ✔ should return an empty array when filter by wrong type and correct room name
        ✔ should return an array sorted by "ts" property
      update group dms name
        ✔ should update group name if user changes username (525ms)
        ✔ should update group name if user changes name (527ms)
      /rooms.delete
        ✔ should throw an error when roomId is not provided
        ✔ should delete a room when the request is correct (55ms)
        ✔ should throw an error when the room id doesn exist
      rooms.saveRoomSettings
        ✔ should update the room settings (742ms)
        ✔ should have reflected on rooms.info
        ✔ should be able to update the discussion name with spaces (60ms)
        ✔ should mark a room as favorite (42ms)
        ✔ should not mark a room as favorite when room is not a default room (58ms)
        ✔ should update the team sidepanel items to channels and discussions (45ms)
        ✔ should throw error when updating team sidepanel with incorrect items
        ✔ should throw error when updating team sidepanel with more than 2 items
        ✔ should throw error when updating team sidepanel with duplicated items (42ms)
      rooms.images
        ✔ should return an error when user is not logged in
        ✔ should return an error when the required parameter "roomId" is not provided
        ✔ should return an error when the required parameter "roomId" is not a valid room
        ✔ should return an error when room is valid but user is not part of it (125ms)
        ✔ should return an empty array when room is valid and user is part of it but there are no images (108ms)
        ✔ should return an array of images when room is valid and user is part of it and there are images (339ms)
        ✔ should return multiple images when room is valid and user is part of it and there are multiple images (521ms)
        ✔ should allow to filter images passing the startingFromId parameter (657ms)
      /rooms.muteUser
        ✔ should invite rocket.cat user to room (43ms)
        ✔ should mute the rocket.cat user
        ✔ should contain rocket.cat user in mute list
      /rooms.unmuteUser
        ✔ should unmute the rocket.cat user in read-only room
        ✔ should contain rocket.cat user in unmute list
      /rooms.export
        ✔ should fail exporting room as file if dates are incorrectly provided
        ✔ should fail exporting room as file if no roomId is provided
        ✔ should fail exporting room as file if no type is provided
        ✔ should fail exporting room as file if fromDate is after toDate (incorrect date interval)
        ✔ should fail exporting room as file if invalid roomId is provided
        ✔ should fail exporting room as file if no format is provided
        ✔ should fail exporting room as file if an invalid format is provided
        ✔ should fail exporting room as file if an invalid type is provided
        ✔ should succesfully export room as file
        ✔ should succesfully export room as file even if no dates are provided (66ms)
        ✔ should fail exporting room via email if target users AND target emails are NOT provided (48ms)
        ✔ should fail exporting room via email if no target e-mails are provided
        ✔ should fail exporting room via email if no target users or e-mails params are provided
        ✔ should fail exporting room via email if no messages are provided
        ✔ should succesfully export room via email (51ms)
      /rooms.isMember
        ✔ should return error if room not found
        ✔ should return error if user not found with the given userId
        ✔ should return error if user not found with the given username
        ✔ should return success with isMember=true if given userId is a member of the channel (46ms)
        ✔ should return success with isMember=true if given username is a member of the channel
        ✔ should return success with isMember=false if user is not a member of the channel
        ✔ should return success with isMember=true if given userId is a member of the group
        ✔ should return success with isMember=true if given username is a member of the group
        ✔ should return success with isMember=false if user is not a member of the group
        ✔ should return unauthorized if caller cannot access the group
        ✔ should return success with isMember=true if given userId is a member of the DM
        ✔ should return success with isMember=true if given username is a member of the DM
        ✔ should return success with isMember=false if user is not a member of the DM
        ✔ should return unauthorized if caller cannot access the DM
      /rooms.open
        ✔ should open the room
        ✔ should fail if roomId is not provided
      [/rooms.membersOrderedByRole]
        ✔ should return a list of members ordered by owner, leader, moderator, then members by default (46ms)
        ✔ should support sorting by role in descending priority
        ✔ should support pagination
        ✔ should return matched members when using filter param (288ms)
        ✔ should return empty list if no matches (e.g., filter by status that no one has)
        ✔ should support custom sorting by username descending
        ✔ should not be affected by custom roles when sorting
        Sort by user status
          ✔ should sort by user status after user role
        Additional Visibility Tests
          ✔ should not fetch private room members by user not part of room
          ✔ should fetch private room members by user who is part of the room
          ✔ should fetch public room members by user who is part of the room
          ✔ should fetch public room members by user not part of room - because public (203ms)
          ✔ should fetch a private channel members inside a public team by someone part of the room 
          ✔ should not fetch a private channel members inside a public team by someone not part of the room, but part of team
          ✔ should not fetch a private channel members inside a public team by someone not part of the team 
          ✔ should fetch a public channel members inside a public team by someone part of the room 
          ✔ should fetch a public channel members inside a public team by someone not part of the room, but part of team
          ✔ should fetch a public channel members inside a public team by someone not part of the team 
          ✔ should fetch a public channel members inside a private team by someone part of the room
          ✔ should fetch a public channel members inside a private team by someone not part of the room, but part of team
          ✔ should not fetch a public channel members inside a private team by someone not part of team
          ✔ should fetch a private channel members inside a private team by someone part of the room (47ms)
          ✔ should not fetch a private channel members inside a private team by someone not part of the room, but part of team
          ✔ should not fetch a private channel members inside a private team by someone not part of team
      /rooms.hide
        ✔ should hide the room
        ✔ should be already hidden
        ✔ should fail if roomId is not provided
        ✔ should return 401 if user is not logged in
        ✔ should return forbidden if user does not have access to the room
      /rooms.roles
        ✔ should get room roles
    
    
    206 passing (59s)
    1 pending
        

Endpoints:

Looking forward to your feedback! 🚀

Summary by CodeRabbit

  • New Features

    • Added a rooms.favorite API to toggle room favorites with stricter validation and clearer responses.
  • Bug Fixes

    • Improved rooms.invite handling with enhanced error handling and reporting.
  • Documentation

    • Updated API documentation and response validation for room-related endpoints.
  • Chores

    • Bumped related packages.

Task: ARCH-1985

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented May 14, 2025

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

  • This PR is targeting the wrong base branch. It should target 8.3.0, but it targets 8.2.0

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 May 14, 2025

🦋 Changeset detected

Latest commit: 2186c0b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 41 packages
Name Type
@rocket.chat/meteor Patch
@rocket.chat/rest-typings Patch
@rocket.chat/api-client Patch
@rocket.chat/core-services Patch
@rocket.chat/ddp-client Patch
@rocket.chat/http-router Patch
@rocket.chat/models Patch
@rocket.chat/ui-contexts Patch
@rocket.chat/web-ui-registration Patch
@rocket.chat/account-service Patch
@rocket.chat/authorization-service Patch
@rocket.chat/ddp-streamer Patch
@rocket.chat/federation-matrix Patch
@rocket.chat/omnichannel-services Patch
@rocket.chat/presence Patch
rocketchat-services Patch
@rocket.chat/omnichannel-transcript Patch
@rocket.chat/presence-service Patch
@rocket.chat/queue-worker Patch
@rocket.chat/abac Patch
@rocket.chat/network-broker Patch
@rocket.chat/omni-core-ee Patch
@rocket.chat/livechat Patch
@rocket.chat/mock-providers Patch
@rocket.chat/cron Patch
@rocket.chat/instance-status Patch
@rocket.chat/omni-core Patch
@rocket.chat/server-fetch Patch
@rocket.chat/ui-client Patch
@rocket.chat/media-calls Patch
@rocket.chat/uikit-playground Patch
@rocket.chat/fuselage-ui-kit Patch
@rocket.chat/gazzodown Patch
@rocket.chat/ui-avatar Patch
@rocket.chat/ui-video-conf Patch
@rocket.chat/ui-voip Patch
@rocket.chat/core-typings Patch
@rocket.chat/apps Patch
@rocket.chat/model-typings Patch
@rocket.chat/license Patch
@rocket.chat/pdf-worker Patch

Not sure what this means? Click here to learn what changesets are.

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

@kody-ai
Copy link

kody-ai bot commented May 14, 2025

Code Review Completed! 🔥

The code review was successfully completed based on your current configurations.

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the @kody start-review command at the root of your PR.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Security
Code Style
Kody Rules
Refactoring
Error Handling
Maintainability
Potential Issues
Documentation And Comments
Performance And Optimization
Breaking Changes

Access your configuration settings here.

@CLAassistant
Copy link

CLAassistant commented May 14, 2025

CLA assistant check
All committers have signed the CLA.

@kody-ai
Copy link

kody-ai bot commented May 14, 2025

Kody Review Complete

Great news! 🎉
No issues were found that match your current review configurations.

Keep up the excellent work! 🚀

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the @kody start-review command at the root of your PR.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Security
Code Style
Kody Rules
Refactoring
Error Handling
Maintainability
Potential Issues
Documentation And Comments
Performance And Optimization
Breaking Changes

Access your configuration settings here.

1 similar comment
@kody-ai
Copy link

kody-ai bot commented May 14, 2025

Kody Review Complete

Great news! 🎉
No issues were found that match your current review configurations.

Keep up the excellent work! 🚀

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the @kody start-review command at the root of your PR.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Security
Code Style
Kody Rules
Refactoring
Error Handling
Maintainability
Potential Issues
Documentation And Comments
Performance And Optimization
Breaking Changes

Access your configuration settings here.

@kody-ai
Copy link

kody-ai bot commented May 15, 2025

Code Review Completed! 🔥

The code review was successfully completed based on your current configurations.

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the @kody start-review command at the root of your PR.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Security
Code Style
Kody Rules
Refactoring
Error Handling
Maintainability
Potential Issues
Documentation And Comments
Performance And Optimization
Breaking Changes

Access your configuration settings here.

@ahmed-n-abdeltwab ahmed-n-abdeltwab requested a review from a team as a code owner August 6, 2025 10:54
@ahmed-n-abdeltwab ahmed-n-abdeltwab marked this pull request as draft August 6, 2025 10:54
@ahmed-n-abdeltwab ahmed-n-abdeltwab marked this pull request as ready for review August 7, 2025 16:27
@ahmed-n-abdeltwab ahmed-n-abdeltwab requested a review from a team as a code owner August 7, 2025 16:27
@ahmed-n-abdeltwab
Copy link
Contributor Author

@cardoso, @ggazzo this API is Ready for review whenever you have time

cardoso
cardoso previously approved these changes Aug 8, 2025
Copy link
Member

@cardoso cardoso left a comment

Choose a reason for hiding this comment

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

@ggazzo 👍

@ahmed-n-abdeltwab
Copy link
Contributor Author

Looks fine

… by migrating to a modern chained route definition syntax and utilizing shared AJV schemas for validation to enhance API documentation and ensure type safety through response validation.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 21, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Moves rooms.favorite into chained OpenAPI-style route definitions with AJV validation, adds RoomsFavorite type and validator, inlines rooms.invite into consolidated roomEndpoints with enhanced error handling, and removes the legacy POST /v1/rooms.favorite declaration from rest-typings.

Changes

Cohort / File(s) Summary
Changeset
\.changeset/tricky-boxes-type.md
Adds changelog entries: patch bumps for @rocket.chat/meteor and @rocket.chat/rest-typings.
API Implementation
apps/meteor/app/api/server/v1/rooms.ts
Adds RoomsFavorite union type, RoomsFavoriteSchema, and isRoomsFavoriteProps AJV validator; adds POST rooms.favorite under consolidated roomEndpoints with validation and response schema; inlines rooms.invite handling into roomEndpoints with enhanced try/catch calling FederationMatrix.handleInvite; updates RoomEndpoints derivation to use ExtractRoutesFromAPI<typeof roomEndpoints>.
Rest Typings Cleanup
packages/rest-typings/src/v1/rooms.ts
Removes the legacy POST /v1/rooms.favorite signature from RoomsEndpoints (previous `{ roomId

Sequence Diagram(s)

sequenceDiagram
  participant Client as Client
  participant API as Rooms API
  participant Validator as AJV Validator
  participant Finder as Room Finder
  participant Service as toggleFavoriteMethod
  participant DB as Database

  Client->>API: POST /rooms.favorite {roomId|roomName, favorite}
  API->>Validator: validate(body)
  Validator-->>API: valid / invalid
  alt valid
    API->>Finder: locate room by id or name
    Finder-->>API: room
    API->>Service: toggleFavoriteMethod(user, room, favorite)
    Service->>DB: update favorite flag
    DB-->>Service: success
    Service-->>API: result
    API-->>Client: 200 {success:true, roomId/roomName, favorite}
  else invalid
    API-->>Client: 400 Bad Request
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I hopped through routes with careful paws,

I stitched the schemas and tightened the laws.
Invites tucked in, favorites now neat,
The API hums with tidy beat.
🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Out of Scope Changes check ❓ Inconclusive The PR introduces changes beyond rooms.favorite scope: rooms.invite endpoint migration and consolidation into roomEndpoints, which are tangential improvements related to the OpenAPI migration pattern but not strictly required by the linked issue objectives. Clarify whether rooms.invite consolidation is part of the OpenAPI integration scope or should be addressed in a separate PR to maintain focused changesets.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR successfully implements all linked issue objectives: migrates rooms.favorite to OpenAPI pattern with AJV validation, uses ExtractRoutesFromAPI for dynamic route derivation, enables Swagger UI integration, implements route chaining, and maintains backward compatibility.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title accurately describes the main change: adding OpenAPI support to the rooms.favorite API endpoint with AJV schema validation and refactored route definitions.

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


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

❤️ Share

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

Copy link
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 (1)
apps/meteor/app/api/server/v1/rooms.ts (1)

1085-1115: 🛠️ Refactor suggestion | 🟠 Major

Inconsistent indentation in the rooms.invite handler.

The rooms.invite block has mismatched indentation compared to the other chained routes (e.g., rooms.favorite and rooms.roles). Specifically:

  • Line 1087: route name 'rooms.invite' is not indented to match the .post( on Line 1086.
  • Line 1107: try { has 3 levels of indentation while the rest of the handler body uses 1 level.
  • Lines 1113–1114: closing braces use inconsistent tab depth.

This appears to be a leftover from converting the standalone route into the chained pattern. Please re-indent this block to match the style used in the rooms.favorite handler below.

♻️ Proposed indentation fix
 	)
 	.post(
-	'rooms.invite',
-	{
-		authRequired: true,
-		body: isRoomsInviteProps,
-		response: {
-			400: validateBadRequestErrorResponse,
-			401: validateUnauthorizedErrorResponse,
-			200: ajv.compile<void>({
-				type: 'object',
-				properties: {
-					success: { type: 'boolean', enum: [true] },
-				},
-				required: ['success'],
-				additionalProperties: false,
-			}),
+		'rooms.invite',
+		{
+			authRequired: true,
+			body: isRoomsInviteProps,
+			response: {
+				400: validateBadRequestErrorResponse,
+				401: validateUnauthorizedErrorResponse,
+				200: ajv.compile<void>({
+					type: 'object',
+					properties: {
+						success: { type: 'boolean', enum: [true] },
+					},
+					required: ['success'],
+					additionalProperties: false,
+				}),
+			},
 		},
-	},
-	async function action() {
-		const { roomId, action } = this.bodyParams;
-
-			try {
-		await FederationMatrix.handleInvite(roomId, this.userId, action);
-		return API.v1.success();
-	} catch (error) {
-		return API.v1.failure({ error: `Failed to handle invite: ${error instanceof Error ? error.message : String(error)}` });
-	}
-	
+		async function action() {
+			const { roomId, action } = this.bodyParams;
+
+			try {
+				await FederationMatrix.handleInvite(roomId, this.userId, action);
+				return API.v1.success();
+			} catch (error) {
+				return API.v1.failure({ error: `Failed to handle invite: ${error instanceof Error ? error.message : String(error)}` });
+			}
 		},
 	)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/app/api/server/v1/rooms.ts` around lines 1085 - 1115, The
`rooms.invite` route block has inconsistent indentation; reformat the chained
.post call so its opening '.post(' and route name 'rooms.invite' align with
other chained routes (e.g., rooms.favorite), and normalize the handler body
indentation (including the try/catch and the closing braces) to use the same
indentation level as other handlers; locate the `.post('rooms.invite', {
authRequired: true, body: isRoomsInviteProps, ... }, async function action() {
... FederationMatrix.handleInvite(roomId, this.userId, action); return
API.v1.success(); } )` and adjust whitespace so the function, try/catch, and
return/API.v1.failure lines match the surrounding style.
🧹 Nitpick comments (1)
apps/meteor/app/api/server/v1/rooms.ts (1)

1137-1149: Redundant favorite existence check — AJV already enforces this.

Line 1140 checks this.bodyParams.hasOwnProperty('favorite'), but the isRoomsFavoriteProps validator (Line 1120) already requires favorite in both schema variants. If favorite is missing, the request is rejected before the handler executes. This check is dead code.

♻️ Proposed simplification
 	async function action() {
 		const { favorite } = this.bodyParams;
 
-		if (!this.bodyParams.hasOwnProperty('favorite')) {
-			return API.v1.failure("The 'favorite' param is required");
-		}
-
 		const room = await findRoomByIdOrName({ params: this.bodyParams });
 
 		await toggleFavoriteMethod(this.userId, room._id, favorite);
 
 		return API.v1.success();
 	},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/app/api/server/v1/rooms.ts` around lines 1137 - 1149, The
handler's explicit existence check for the favorite param is redundant because
the isRoomsFavoriteProps validator already enforces that favorite is present;
remove the dead branch in the action() function (the
this.bodyParams.hasOwnProperty('favorite') check and its API.v1.failure return)
and let the validator reject invalid requests, keeping the existing extraction
const { favorite } = this.bodyParams and subsequent calls to findRoomByIdOrName
and toggleFavoriteMethod unchanged.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3145c41 and 0d4b946.

📒 Files selected for processing (3)
  • .changeset/tricky-boxes-type.md
  • apps/meteor/app/api/server/v1/rooms.ts
  • packages/rest-typings/src/v1/rooms.ts
💤 Files with no reviewable changes (1)
  • packages/rest-typings/src/v1/rooms.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/app/api/server/v1/rooms.ts
🧠 Learnings (6)
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.

Applied to files:

  • .changeset/tricky-boxes-type.md
  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-11-27T17:56:26.050Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37557
File: apps/meteor/client/views/admin/ABAC/AdminABACRooms.tsx:115-116
Timestamp: 2025-11-27T17:56:26.050Z
Learning: In Rocket.Chat, the GET /v1/abac/rooms endpoint (implemented in ee/packages/abac/src/index.ts) only returns rooms where abacAttributes exists and is not an empty array (query: { abacAttributes: { $exists: true, $ne: [] } }). Therefore, in components consuming this endpoint (like AdminABACRooms.tsx), room.abacAttributes is guaranteed to be defined for all returned rooms, and optional chaining before calling array methods like .join() is sufficient without additional null coalescing.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2026-01-17T01:51:47.764Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38219
File: packages/core-typings/src/cloud/Announcement.ts:5-6
Timestamp: 2026-01-17T01:51:47.764Z
Learning: In packages/core-typings/src/cloud/Announcement.ts, the AnnouncementSchema.createdBy field intentionally overrides IBannerSchema.createdBy (object with _id and optional username) with a string enum ['cloud', 'system'] to match existing runtime behavior. This is documented as technical debt with a FIXME comment at apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts:53 and should not be flagged as an error until the runtime behavior is corrected.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: UserBridge.doGetUserRoomIds in packages/apps-engine/src/server/bridges/UserBridge.ts has a bug where it implicitly returns undefined when the app lacks read permission (missing return statement in the else case of the permission check).

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-12-09T20:01:07.355Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:07.355Z
Learning: In Rocket.Chat's federation invite handling (ee/packages/federation-matrix/src/FederationMatrix.ts), when a user rejects an invite via federationSDK.rejectInvite(), the subscription cleanup happens automatically through an event-driven flow: Matrix emits a leave event back, which is processed by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, and that function calls Room.performUserRemoval() to clean up the subscription. No explicit cleanup is needed in the reject branch of handleInvite() because the leave event handler takes care of it.
<!-- </add_learning>

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
🧬 Code graph analysis (1)
apps/meteor/app/api/server/v1/rooms.ts (3)
packages/rest-typings/src/v1/Ajv.ts (3)
  • ajv (24-24)
  • validateBadRequestErrorResponse (47-47)
  • validateUnauthorizedErrorResponse (70-70)
apps/meteor/app/channel-settings/server/methods/saveRoomSettings.ts (1)
  • favorite (348-350)
apps/meteor/app/api/server/ApiClass.ts (1)
  • ExtractRoutesFromAPI (74-78)
⏰ 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). (2)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
🔇 Additional comments (4)
.changeset/tricky-boxes-type.md (1)

1-6: LGTM!

Changeset correctly marks both packages as patch for the non-breaking OpenAPI migration, and the description is clear.

apps/meteor/app/api/server/v1/rooms.ts (3)

928-936: LGTM!

The RoomsFavorite union type correctly models the two mutually exclusive request body shapes, consistent with the anyOf JSON schema below.


947-970: LGTM!

Schema correctly uses anyOf with additionalProperties: false on each variant, ensuring exactly one of roomId or roomName is accepted alongside favorite.


1152-1157: LGTM!

The RoomEndpoints type extraction from the chained builder and the module augmentation correctly propagate the new route types into @rocket.chat/rest-typings.

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/meteor/app/api/server/v1/rooms.ts`:
- Around line 1122-1132: The 200 response schema compiled with ajv.compile in
the rooms.favorite response block allows any boolean for the success property;
update the schema used by ajv.compile (the object with properties.success) to
constrain success to only true by adding enum: [true] to the success property so
it matches the rooms.invite pattern and prevents { success: false } from
validating.

---

Outside diff comments:
In `@apps/meteor/app/api/server/v1/rooms.ts`:
- Around line 1085-1115: The `rooms.invite` route block has inconsistent
indentation; reformat the chained .post call so its opening '.post(' and route
name 'rooms.invite' align with other chained routes (e.g., rooms.favorite), and
normalize the handler body indentation (including the try/catch and the closing
braces) to use the same indentation level as other handlers; locate the
`.post('rooms.invite', { authRequired: true, body: isRoomsInviteProps, ... },
async function action() { ... FederationMatrix.handleInvite(roomId, this.userId,
action); return API.v1.success(); } )` and adjust whitespace so the function,
try/catch, and return/API.v1.failure lines match the surrounding style.

---

Nitpick comments:
In `@apps/meteor/app/api/server/v1/rooms.ts`:
- Around line 1137-1149: The handler's explicit existence check for the favorite
param is redundant because the isRoomsFavoriteProps validator already enforces
that favorite is present; remove the dead branch in the action() function (the
this.bodyParams.hasOwnProperty('favorite') check and its API.v1.failure return)
and let the validator reject invalid requests, keeping the existing extraction
const { favorite } = this.bodyParams and subsequent calls to findRoomByIdOrName
and toggleFavoriteMethod unchanged.

@codecov
Copy link

codecov bot commented Feb 21, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 70.56%. Comparing base (b08592e) to head (b8d9007).
⚠️ Report is 52 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #35995      +/-   ##
===========================================
- Coverage    70.58%   70.56%   -0.03%     
===========================================
  Files         3178     3189      +11     
  Lines       111796   112703     +907     
  Branches     20213    20417     +204     
===========================================
+ Hits         78914    79530     +616     
- Misses       30831    31113     +282     
- Partials      2051     2060       +9     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

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

Choose a reason for hiding this comment

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

No issues found across 3 files

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

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0d4b946 and 6acc3d6.

📒 Files selected for processing (1)
  • apps/meteor/app/api/server/v1/rooms.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/app/api/server/v1/rooms.ts
🧠 Learnings (6)
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-11-27T17:56:26.050Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37557
File: apps/meteor/client/views/admin/ABAC/AdminABACRooms.tsx:115-116
Timestamp: 2025-11-27T17:56:26.050Z
Learning: In Rocket.Chat, the GET /v1/abac/rooms endpoint (implemented in ee/packages/abac/src/index.ts) only returns rooms where abacAttributes exists and is not an empty array (query: { abacAttributes: { $exists: true, $ne: [] } }). Therefore, in components consuming this endpoint (like AdminABACRooms.tsx), room.abacAttributes is guaranteed to be defined for all returned rooms, and optional chaining before calling array methods like .join() is sufficient without additional null coalescing.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2026-01-17T01:51:47.764Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38219
File: packages/core-typings/src/cloud/Announcement.ts:5-6
Timestamp: 2026-01-17T01:51:47.764Z
Learning: In packages/core-typings/src/cloud/Announcement.ts, the AnnouncementSchema.createdBy field intentionally overrides IBannerSchema.createdBy (object with _id and optional username) with a string enum ['cloud', 'system'] to match existing runtime behavior. This is documented as technical debt with a FIXME comment at apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts:53 and should not be flagged as an error until the runtime behavior is corrected.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: UserBridge.doGetUserRoomIds in packages/apps-engine/src/server/bridges/UserBridge.ts has a bug where it implicitly returns undefined when the app lacks read permission (missing return statement in the else case of the permission check).

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-12-09T20:01:07.355Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:07.355Z
Learning: In Rocket.Chat's federation invite handling (ee/packages/federation-matrix/src/FederationMatrix.ts), when a user rejects an invite via federationSDK.rejectInvite(), the subscription cleanup happens automatically through an event-driven flow: Matrix emits a leave event back, which is processed by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, and that function calls Room.performUserRemoval() to clean up the subscription. No explicit cleanup is needed in the reject branch of handleInvite() because the leave event handler takes care of it.
<!-- </add_learning>

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
🧬 Code graph analysis (1)
apps/meteor/app/api/server/v1/rooms.ts (2)
apps/meteor/app/channel-settings/server/methods/saveRoomSettings.ts (1)
  • favorite (348-350)
apps/meteor/app/api/server/ApiClass.ts (1)
  • ExtractRoutesFromAPI (74-78)
🔇 Additional comments (3)
apps/meteor/app/api/server/v1/rooms.ts (3)

1152-1156: LGTM — type extraction and module augmentation are consistent with the consolidated roomEndpoints chain.


947-970: No action required for RoomsFavoriteSchema — the anyOf pattern is safe in this codebase.

The shared ajv instance in packages/rest-typings/src/v1/Ajv.ts does not configure the removeAdditional option. It uses: coerceTypes: true, allowUnionTypes: true, code: { source: true }, and discriminator: true. Therefore, the anyOf with additionalProperties: false inside each subschema will validate correctly without risk of silent data mutation. Valid requests like { roomId, favorite } will pass the second branch of the anyOf as expected.

Likely an incorrect or invalid review comment.


1104-1113: ⚠️ Potential issue | 🟡 Minor

Fix the API response schema violation in the error handler.

The catch block returns API.v1.failure({ error: ... }), which produces {success: false, error: "..."}. This response violates the declared 200 schema that requires {success: true} with additionalProperties: false. Either return an appropriate error status code (4xx) or adjust the response schema to allow failure responses with error details.

The endpoint is federation-specific by design (accept/reject invite TO a room); no breaking change concern applies.

⛔ Skipped due to learnings
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:07.355Z
Learning: In Rocket.Chat's federation invite handling (ee/packages/federation-matrix/src/FederationMatrix.ts), when a user rejects an invite via federationSDK.rejectInvite(), the subscription cleanup happens automatically through an event-driven flow: Matrix emits a leave event back, which is processed by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, and that function calls Room.performUserRemoval() to clean up the subscription. No explicit cleanup is needed in the reject branch of handleInvite() because the leave event handler takes care of it.
<!-- </add_learning>
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38219
File: packages/core-typings/src/cloud/Announcement.ts:5-6
Timestamp: 2026-01-17T01:51:47.764Z
Learning: In packages/core-typings/src/cloud/Announcement.ts, the AnnouncementSchema.createdBy field intentionally overrides IBannerSchema.createdBy (object with _id and optional username) with a string enum ['cloud', 'system'] to match existing runtime behavior. This is documented as technical debt with a FIXME comment at apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts:53 and should not be flagged as an error until the runtime behavior is corrected.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/meteor/app/api/server/v1/rooms.ts`:
- Around line 1107-1112: The catch block is returning API.v1.failure(...) which
violates the declared 200 response schema (success must be true); replace this
with throwing a proper Meteor.Error (or MeteorError) so the framework converts
it to a 4xx response consistent with other endpoints—specifically, in the
handler that calls FederationMatrix.handleInvite(roomId, this.userId, action)
remove the API.v1.failure(...) return and instead throw new Meteor.Error(...)
(including a short error code and the caught error message) so the route yields
a validated error response; alternatively, if you prefer to keep API.v1.failure,
update the route’s response schema to declare a matching 4xx error response, but
prefer throwing Meteor.Error for consistency.
- Around line 1138-1142: Remove the redundant runtime guard that checks
this.bodyParams.hasOwnProperty('favorite') in the Rooms favorite handler: AJV
already enforces required via isRoomsFavoriteProps / RoomsFavoriteSchema before
the action runs, and destructuring const { favorite } = this.bodyParams happens
before the check anyway, so delete the if
(!this.bodyParams.hasOwnProperty('favorite')) { return API.v1.failure(...) }
block and leave the destructuring and subsequent logic intact.

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 (1)
apps/meteor/app/api/server/v1/rooms.ts (1)

1094-1101: ajv.compile<void> loses the validated type — use the actual response shape.

Both 200-response validators use void as the generic parameter, but the schema describes { success: boolean }. This means ValidateFunction<void> is returned, stripping type information from any downstream consumer that inspects .data.

♻️ Proposed fix (apply to both occurrences)
-			200: ajv.compile<void>({
+			200: ajv.compile<{ success: boolean }>({

Also applies to: 1121-1132

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/app/api/server/v1/rooms.ts` around lines 1094 - 1101, The AJV
validators are compiled with ajv.compile<void>, which loses the response type;
change those generics to the actual response shape (e.g., ajv.compile<{ success:
boolean }>) so the returned ValidateFunction has the correct typed `.data`;
update both 200-response validators (the ajv.compile calls shown and the other
occurrence at the later 1121-1132 block) to use the concrete type instead of
void.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/meteor/app/api/server/v1/rooms.ts`:
- Around line 1138-1142: findRoomByIdOrName is being called with the default
checkedArchived = true, which causes archived rooms to throw error-room-archived
and prevents toggleFavoriteMethod from removing favorites; update the call that
currently uses findRoomByIdOrName({ params: this.bodyParams }) to pass
checkedArchived: false (e.g. findRoomByIdOrName({ params: this.bodyParams,
checkedArchived: false })) so the endpoint can unfavorite archived rooms before
calling toggleFavoriteMethod(this.userId, room._id, favorite).
- Around line 1107-1112: The catch block around FederationMatrix.handleInvite
currently constructs new Meteor.Error with the full interpolated message as the
first (code) argument; change it to pass a stable error code as the first arg
and the human-readable message as the second, preserving any existing structured
code/message from the caught error (e.g. use (error && error.code) ||
'federation-handle-invite-failed' for the first argument and (error &&
error.message) || String(error) for the second) when throwing new Meteor.Error
in the catch.

---

Nitpick comments:
In `@apps/meteor/app/api/server/v1/rooms.ts`:
- Around line 1094-1101: The AJV validators are compiled with ajv.compile<void>,
which loses the response type; change those generics to the actual response
shape (e.g., ajv.compile<{ success: boolean }>) so the returned ValidateFunction
has the correct typed `.data`; update both 200-response validators (the
ajv.compile calls shown and the other occurrence at the later 1121-1132 block)
to use the concrete type instead of void.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6acc3d6 and 051932b.

📒 Files selected for processing (1)
  • apps/meteor/app/api/server/v1/rooms.ts
📜 Review details
⏰ 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: cubic · AI code reviewer
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/app/api/server/v1/rooms.ts
🧠 Learnings (10)
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-11-27T17:56:26.050Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37557
File: apps/meteor/client/views/admin/ABAC/AdminABACRooms.tsx:115-116
Timestamp: 2025-11-27T17:56:26.050Z
Learning: In Rocket.Chat, the GET /v1/abac/rooms endpoint (implemented in ee/packages/abac/src/index.ts) only returns rooms where abacAttributes exists and is not an empty array (query: { abacAttributes: { $exists: true, $ne: [] } }). Therefore, in components consuming this endpoint (like AdminABACRooms.tsx), room.abacAttributes is guaranteed to be defined for all returned rooms, and optional chaining before calling array methods like .join() is sufficient without additional null coalescing.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-09-19T15:15:04.642Z
Learnt from: rodrigok
Repo: RocketChat/Rocket.Chat PR: 36991
File: apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts:219-221
Timestamp: 2025-09-19T15:15:04.642Z
Learning: The Federation_Matrix_homeserver_domain setting in apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts is part of the old federation system and is being deprecated/removed, so configuration issues with this setting should not be flagged for improvement.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings (mapping subscription documents to room IDs), never undefined, even when user has no room subscriptions.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2026-01-17T01:51:47.764Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38219
File: packages/core-typings/src/cloud/Announcement.ts:5-6
Timestamp: 2026-01-17T01:51:47.764Z
Learning: In packages/core-typings/src/cloud/Announcement.ts, the AnnouncementSchema.createdBy field intentionally overrides IBannerSchema.createdBy (object with _id and optional username) with a string enum ['cloud', 'system'] to match existing runtime behavior. This is documented as technical debt with a FIXME comment at apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts:53 and should not be flagged as an error until the runtime behavior is corrected.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: UserBridge.doGetUserRoomIds in packages/apps-engine/src/server/bridges/UserBridge.ts has a bug where it implicitly returns undefined when the app lacks read permission (missing return statement in the else case of the permission check).

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-12-09T20:01:07.355Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:07.355Z
Learning: In Rocket.Chat's federation invite handling (ee/packages/federation-matrix/src/FederationMatrix.ts), when a user rejects an invite via federationSDK.rejectInvite(), the subscription cleanup happens automatically through an event-driven flow: Matrix emits a leave event back, which is processed by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, and that function calls Room.performUserRemoval() to clean up the subscription. No explicit cleanup is needed in the reject branch of handleInvite() because the leave event handler takes care of it.
<!-- </add_learning>

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2026-01-26T18:26:01.279Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 38227
File: apps/meteor/app/api/server/router.ts:44-49
Timestamp: 2026-01-26T18:26:01.279Z
Learning: In apps/meteor/app/api/server/router.ts, when retrieving bodyParams and queryParams from the Hono context via c.get(), do not add defensive defaults (e.g., ?? {}). The code should fail fast if these parameters are missing, as endpoint handlers expect them to be present and breaking here helps surface parsing problems rather than hiding them.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
🧬 Code graph analysis (1)
apps/meteor/app/api/server/v1/rooms.ts (3)
packages/rest-typings/src/v1/rooms.ts (1)
  • isRoomsInviteProps (712-712)
apps/meteor/app/channel-settings/server/methods/saveRoomSettings.ts (1)
  • favorite (348-350)
apps/meteor/app/api/server/ApiClass.ts (1)
  • ExtractRoutesFromAPI (74-78)
🔇 Additional comments (2)
apps/meteor/app/api/server/v1/rooms.ts (2)

928-970: LGTM — schema and type are well-formed.

The anyOf + additionalProperties: false pattern correctly models the RoomsFavorite union: AJV evaluates each branch independently, so { roomId, favorite } passes only the second branch and { roomId, roomName, favorite } fails both. The compile-time generic matches the runtime schema.


1148-1152: LGTM — type consolidation is clean.

RoomEndpoints now derives solely from ExtractRoutesFromAPI<typeof roomEndpoints>, correctly reflecting both rooms.invite and rooms.favorite being consolidated into the chained route definition.

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.

♻️ Duplicate comments (1)
apps/meteor/app/api/server/v1/rooms.ts (1)

1140-1140: ⚠️ Potential issue | 🟡 Minor

checkedArchived: true (default) prevents unfavoriting archived rooms.

Users who favorited a room before it was archived will be unable to unfavorite it, as findRoomByIdOrName throws error-room-archived before reaching toggleFavoriteMethod. Pass checkedArchived: false since archival status should not gate favorite toggling.

Proposed fix
-		const room = await findRoomByIdOrName({ params: this.bodyParams });
+		const room = await findRoomByIdOrName({ params: this.bodyParams, checkedArchived: false });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/app/api/server/v1/rooms.ts` at line 1140, findRoomByIdOrName
currently uses its default checkedArchived:true which causes it to throw
error-room-archived and prevents toggleFavoriteMethod from running; update the
call at the start of the favorite toggle flow to call findRoomByIdOrName({
params: this.bodyParams, checkedArchived: false }) so archived status does not
block unfavoriting, preserving existing behavior elsewhere that relies on the
default.
🧹 Nitpick comments (1)
apps/meteor/app/api/server/v1/rooms.ts (1)

1121-1132: ajv.compile<void> doesn't reflect the actual response shape.

The schema describes { success: boolean }, but the generic parameter is void. Other endpoints in this file (e.g., rooms.adminRooms.privateRooms at Line 1040) pass accurate generics. Since ExtractRoutesFromAPI derives route types from these validators, the inferred 200 response type will be void instead of { success: true }.

Suggested fix
-			200: ajv.compile<void>({
+			200: ajv.compile<{ success: true }>({
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/app/api/server/v1/rooms.ts` around lines 1121 - 1132, The
200-response Ajv validator currently uses ajv.compile<void> which causes the
inferred route type to be void; update the generic to match the schema shape
(e.g., ajv.compile<{ success: true }> or ajv.compile<{ success: boolean }> to
match your intent) for the validator so ExtractRoutesFromAPI derives the correct
response type; locate the validator call (ajv.compile) in this handler and
replace the void generic with the accurate response interface, mirroring the
pattern used by rooms.adminRooms.privateRooms.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@apps/meteor/app/api/server/v1/rooms.ts`:
- Line 1140: findRoomByIdOrName currently uses its default checkedArchived:true
which causes it to throw error-room-archived and prevents toggleFavoriteMethod
from running; update the call at the start of the favorite toggle flow to call
findRoomByIdOrName({ params: this.bodyParams, checkedArchived: false }) so
archived status does not block unfavoriting, preserving existing behavior
elsewhere that relies on the default.

---

Nitpick comments:
In `@apps/meteor/app/api/server/v1/rooms.ts`:
- Around line 1121-1132: The 200-response Ajv validator currently uses
ajv.compile<void> which causes the inferred route type to be void; update the
generic to match the schema shape (e.g., ajv.compile<{ success: true }> or
ajv.compile<{ success: boolean }> to match your intent) for the validator so
ExtractRoutesFromAPI derives the correct response type; locate the validator
call (ajv.compile) in this handler and replace the void generic with the
accurate response interface, mirroring the pattern used by
rooms.adminRooms.privateRooms.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 051932b and b8d9007.

📒 Files selected for processing (1)
  • apps/meteor/app/api/server/v1/rooms.ts
📜 Review details
⏰ 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: ⚙️ Variables Setup
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: CodeQL-Build
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/app/api/server/v1/rooms.ts
🧠 Learnings (13)
📓 Common learnings
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 35995
File: apps/meteor/app/api/server/v1/rooms.ts:1107-1112
Timestamp: 2026-02-23T17:53:06.802Z
Learning: In Rocket.Chat PR reviews, maintain strict scope boundaries—when a PR is focused on a specific endpoint (e.g., rooms.favorite), avoid reviewing or suggesting changes to other endpoints that were incidentally refactored (e.g., rooms.invite) unless explicitly requested by maintainers.
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2026-02-23T17:53:06.802Z
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 35995
File: apps/meteor/app/api/server/v1/rooms.ts:1107-1112
Timestamp: 2026-02-23T17:53:06.802Z
Learning: During PR reviews that touch endpoint files under apps/meteor/app/api/server/v1, enforce strict scope: if a PR targets a specific endpoint (e.g., rooms.favorite), do not propose changes to unrelated endpoints (e.g., rooms.invite) unless maintainers explicitly request them. Focus feedback on the touched endpoint's behavior, API surface, and related tests; avoid broad cross-endpoint changes in the same PR unless requested.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-11-27T17:56:26.050Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37557
File: apps/meteor/client/views/admin/ABAC/AdminABACRooms.tsx:115-116
Timestamp: 2025-11-27T17:56:26.050Z
Learning: In Rocket.Chat, the GET /v1/abac/rooms endpoint (implemented in ee/packages/abac/src/index.ts) only returns rooms where abacAttributes exists and is not an empty array (query: { abacAttributes: { $exists: true, $ne: [] } }). Therefore, in components consuming this endpoint (like AdminABACRooms.tsx), room.abacAttributes is guaranteed to be defined for all returned rooms, and optional chaining before calling array methods like .join() is sufficient without additional null coalescing.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2026-01-17T01:51:47.764Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38219
File: packages/core-typings/src/cloud/Announcement.ts:5-6
Timestamp: 2026-01-17T01:51:47.764Z
Learning: In packages/core-typings/src/cloud/Announcement.ts, the AnnouncementSchema.createdBy field intentionally overrides IBannerSchema.createdBy (object with _id and optional username) with a string enum ['cloud', 'system'] to match existing runtime behavior. This is documented as technical debt with a FIXME comment at apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts:53 and should not be flagged as an error until the runtime behavior is corrected.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: UserBridge.doGetUserRoomIds in packages/apps-engine/src/server/bridges/UserBridge.ts has a bug where it implicitly returns undefined when the app lacks read permission (missing return statement in the else case of the permission check).

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2026-01-26T18:26:01.279Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 38227
File: apps/meteor/app/api/server/router.ts:44-49
Timestamp: 2026-01-26T18:26:01.279Z
Learning: In apps/meteor/app/api/server/router.ts, when retrieving bodyParams and queryParams from the Hono context via c.get(), do not add defensive defaults (e.g., ?? {}). The code should fail fast if these parameters are missing, as endpoint handlers expect them to be present and breaking here helps surface parsing problems rather than hiding them.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-12-09T20:01:07.355Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:07.355Z
Learning: In Rocket.Chat's federation invite handling (ee/packages/federation-matrix/src/FederationMatrix.ts), when a user rejects an invite via federationSDK.rejectInvite(), the subscription cleanup happens automatically through an event-driven flow: Matrix emits a leave event back, which is processed by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, and that function calls Room.performUserRemoval() to clean up the subscription. No explicit cleanup is needed in the reject branch of handleInvite() because the leave event handler takes care of it.
<!-- </add_learning>

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-11-19T18:20:37.116Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: apps/meteor/server/services/media-call/service.ts:141-141
Timestamp: 2025-11-19T18:20:37.116Z
Learning: In apps/meteor/server/services/media-call/service.ts, the sendHistoryMessage method should use call.caller.id or call.createdBy?.id as the message author, not call.transferredBy?.id. Even for transferred calls, the message should appear in the DM between the two users who are calling each other, not sent by the person who transferred the call.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-09-19T15:15:04.642Z
Learnt from: rodrigok
Repo: RocketChat/Rocket.Chat PR: 36991
File: apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts:219-221
Timestamp: 2025-09-19T15:15:04.642Z
Learning: The Federation_Matrix_homeserver_domain setting in apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts is part of the old federation system and is being deprecated/removed, so configuration issues with this setting should not be flagged for improvement.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-11-19T12:32:29.696Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37547
File: packages/i18n/src/locales/en.i18n.json:634-634
Timestamp: 2025-11-19T12:32:29.696Z
Learning: Repo: RocketChat/Rocket.Chat
Context: i18n workflow
Learning: In this repository, new translation keys should be added to packages/i18n/src/locales/en.i18n.json only; other locale files are populated via the external translation pipeline and/or fall back to English. Do not request adding the same key to all locale files in future reviews.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-11-10T19:06:20.146Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37408
File: apps/meteor/client/views/admin/ABAC/useRoomAttributeOptions.tsx:53-69
Timestamp: 2025-11-10T19:06:20.146Z
Learning: In the Rocket.Chat repository, do not provide suggestions or recommendations about code sections marked with TODO comments. The maintainers have already identified these as future work and external reviewers lack the full context about implementation plans and timing.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
🧬 Code graph analysis (1)
apps/meteor/app/api/server/v1/rooms.ts (3)
packages/rest-typings/src/v1/rooms.ts (1)
  • isRoomsInviteProps (712-712)
apps/meteor/app/channel-settings/server/methods/saveRoomSettings.ts (1)
  • favorite (348-350)
apps/meteor/app/api/server/ApiClass.ts (1)
  • ExtractRoutesFromAPI (74-78)
🔇 Additional comments (3)
apps/meteor/app/api/server/v1/rooms.ts (3)

928-970: Well-structured discriminated union schema for rooms.favorite body validation.

The RoomsFavorite type and RoomsFavoriteSchema cleanly model the two mutually exclusive input shapes (roomId vs roomName), and additionalProperties: false on each branch correctly prevents mixing them.


1137-1145: Clean action handler — dead-code guard correctly removed.

The previous hasOwnProperty('favorite') guard is gone, and AJV now handles validation before the action runs. The handler is concise and correct.


1148-1153: Type extraction and module augmentation look correct.

RoomEndpoints is cleanly derived from roomEndpoints and properly extends the Endpoints interface.

@ggazzo ggazzo added this to the 8.3.0 milestone Feb 23, 2026
@ggazzo
Copy link
Member

ggazzo commented Feb 23, 2026

/jira ARCH-1935

ggazzo
ggazzo previously approved these changes Feb 23, 2026
@ggazzo ggazzo added the stat: QA assured Means it has been tested and approved by a company insider label Feb 23, 2026
@dionisio-bot dionisio-bot bot added the stat: ready to merge PR tested and approved waiting for merge label Feb 23, 2026
ggazzo
ggazzo previously approved these changes Feb 23, 2026
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.

♻️ Duplicate comments (1)
apps/meteor/app/api/server/v1/rooms.ts (1)

1144-1144: ⚠️ Potential issue | 🟡 Minor

checkedArchived: true (default) prevents unfavoriting archived rooms.

findRoomByIdOrName throws error-room-archived before toggleFavoriteMethod is reached, making it impossible to remove a favorite from an archived room. This issue was raised in a previous review and remains unaddressed.

🐛 Proposed fix
-		const room = await findRoomByIdOrName({ params: this.bodyParams });
+		const room = await findRoomByIdOrName({ params: this.bodyParams, checkedArchived: false });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/app/api/server/v1/rooms.ts` at line 1144, The call to
findRoomByIdOrName in the toggle favorite flow is using the default
checkedArchived:true which causes an error-room-archived to be thrown before
toggleFavoriteMethod can run; change the invocation in the toggle favorite
endpoint so it passes checkedArchived:false (e.g., findRoomByIdOrName({ params:
this.bodyParams, checkedArchived: false })) so archived rooms are returned and
toggleFavoriteMethod can proceed to remove favorites from archived rooms.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@apps/meteor/app/api/server/v1/rooms.ts`:
- Line 1144: The call to findRoomByIdOrName in the toggle favorite flow is using
the default checkedArchived:true which causes an error-room-archived to be
thrown before toggleFavoriteMethod can run; change the invocation in the toggle
favorite endpoint so it passes checkedArchived:false (e.g., findRoomByIdOrName({
params: this.bodyParams, checkedArchived: false })) so archived rooms are
returned and toggleFavoriteMethod can proceed to remove favorites from archived
rooms.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b8d9007 and 7751ff8.

📒 Files selected for processing (1)
  • apps/meteor/app/api/server/v1/rooms.ts
📜 Review details
⏰ 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). (2)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/app/api/server/v1/rooms.ts
🧠 Learnings (15)
📓 Common learnings
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 35995
File: apps/meteor/app/api/server/v1/rooms.ts:1107-1112
Timestamp: 2026-02-23T17:53:06.802Z
Learning: In Rocket.Chat PR reviews, maintain strict scope boundaries—when a PR is focused on a specific endpoint (e.g., rooms.favorite), avoid reviewing or suggesting changes to other endpoints that were incidentally refactored (e.g., rooms.invite) unless explicitly requested by maintainers.
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-11-27T17:56:26.050Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37557
File: apps/meteor/client/views/admin/ABAC/AdminABACRooms.tsx:115-116
Timestamp: 2025-11-27T17:56:26.050Z
Learning: In Rocket.Chat, the GET /v1/abac/rooms endpoint (implemented in ee/packages/abac/src/index.ts) only returns rooms where abacAttributes exists and is not an empty array (query: { abacAttributes: { $exists: true, $ne: [] } }). Therefore, in components consuming this endpoint (like AdminABACRooms.tsx), room.abacAttributes is guaranteed to be defined for all returned rooms, and optional chaining before calling array methods like .join() is sufficient without additional null coalescing.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2026-01-17T01:51:47.764Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38219
File: packages/core-typings/src/cloud/Announcement.ts:5-6
Timestamp: 2026-01-17T01:51:47.764Z
Learning: In packages/core-typings/src/cloud/Announcement.ts, the AnnouncementSchema.createdBy field intentionally overrides IBannerSchema.createdBy (object with _id and optional username) with a string enum ['cloud', 'system'] to match existing runtime behavior. This is documented as technical debt with a FIXME comment at apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts:53 and should not be flagged as an error until the runtime behavior is corrected.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-09-19T15:15:04.642Z
Learnt from: rodrigok
Repo: RocketChat/Rocket.Chat PR: 36991
File: apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts:219-221
Timestamp: 2025-09-19T15:15:04.642Z
Learning: The Federation_Matrix_homeserver_domain setting in apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts is part of the old federation system and is being deprecated/removed, so configuration issues with this setting should not be flagged for improvement.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2026-02-23T17:53:06.802Z
Learnt from: ggazzo
Repo: RocketChat/Rocket.Chat PR: 35995
File: apps/meteor/app/api/server/v1/rooms.ts:1107-1112
Timestamp: 2026-02-23T17:53:06.802Z
Learning: During PR reviews that touch endpoint files under apps/meteor/app/api/server/v1, enforce strict scope: if a PR targets a specific endpoint (e.g., rooms.favorite), do not propose changes to unrelated endpoints (e.g., rooms.invite) unless maintainers explicitly request them. Focus feedback on the touched endpoint's behavior, API surface, and related tests; avoid broad cross-endpoint changes in the same PR unless requested.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings (mapping subscription documents to room IDs), never undefined, even when user has no room subscriptions.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: UserBridge.doGetUserRoomIds in packages/apps-engine/src/server/bridges/UserBridge.ts has a bug where it implicitly returns undefined when the app lacks read permission (missing return statement in the else case of the permission check).

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2026-01-26T18:26:01.279Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 38227
File: apps/meteor/app/api/server/router.ts:44-49
Timestamp: 2026-01-26T18:26:01.279Z
Learning: In apps/meteor/app/api/server/router.ts, when retrieving bodyParams and queryParams from the Hono context via c.get(), do not add defensive defaults (e.g., ?? {}). The code should fail fast if these parameters are missing, as endpoint handlers expect them to be present and breaking here helps surface parsing problems rather than hiding them.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-12-09T20:01:07.355Z
Learnt from: sampaiodiego
Repo: RocketChat/Rocket.Chat PR: 37532
File: ee/packages/federation-matrix/src/FederationMatrix.ts:920-927
Timestamp: 2025-12-09T20:01:07.355Z
Learning: In Rocket.Chat's federation invite handling (ee/packages/federation-matrix/src/FederationMatrix.ts), when a user rejects an invite via federationSDK.rejectInvite(), the subscription cleanup happens automatically through an event-driven flow: Matrix emits a leave event back, which is processed by handleLeave() in ee/packages/federation-matrix/src/events/member.ts, and that function calls Room.performUserRemoval() to clean up the subscription. No explicit cleanup is needed in the reject branch of handleInvite() because the leave event handler takes care of it.
<!-- </add_learning>

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-11-19T18:20:37.116Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: apps/meteor/server/services/media-call/service.ts:141-141
Timestamp: 2025-11-19T18:20:37.116Z
Learning: In apps/meteor/server/services/media-call/service.ts, the sendHistoryMessage method should use call.caller.id or call.createdBy?.id as the message author, not call.transferredBy?.id. Even for transferred calls, the message should appear in the DM between the two users who are calling each other, not sent by the person who transferred the call.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-11-19T12:32:29.696Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37547
File: packages/i18n/src/locales/en.i18n.json:634-634
Timestamp: 2025-11-19T12:32:29.696Z
Learning: Repo: RocketChat/Rocket.Chat
Context: i18n workflow
Learning: In this repository, new translation keys should be added to packages/i18n/src/locales/en.i18n.json only; other locale files are populated via the external translation pipeline and/or fall back to English. Do not request adding the same key to all locale files in future reviews.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
📚 Learning: 2025-11-10T19:06:20.146Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37408
File: apps/meteor/client/views/admin/ABAC/useRoomAttributeOptions.tsx:53-69
Timestamp: 2025-11-10T19:06:20.146Z
Learning: In the Rocket.Chat repository, do not provide suggestions or recommendations about code sections marked with TODO comments. The maintainers have already identified these as future work and external reviewers lack the full context about implementation plans and timing.

Applied to files:

  • apps/meteor/app/api/server/v1/rooms.ts
🔇 Additional comments (2)
apps/meteor/app/api/server/v1/rooms.ts (2)

928-970: LGTM — schema, type, and validator are consistent.

The anyOf with additionalProperties: false on both branches correctly ensures mutual exclusivity of roomId and roomName while requiring favorite on both, and the generic type parameter matches the union type.


1152-1152: LGTM — type derivation is correct.

RoomEndpoints now cleanly derives from the consolidated roomEndpoints chain, which includes all migrated routes.

@ggazzo ggazzo changed the title feat: Add OpenAPI Support to rooms.favorite API chore: Add OpenAPI Support to rooms.favorite API Feb 23, 2026
@ggazzo ggazzo merged commit 98a6c58 into RocketChat:develop Feb 23, 2026
8 checks passed
@ahmed-n-abdeltwab
Copy link
Contributor Author

thanks , im going to update this repo RocketChat/Rocket.Chat-Open-API#150 and remove the rooms.favorite from it

@ahmed-n-abdeltwab ahmed-n-abdeltwab deleted the feat/openapi-rooms branch February 23, 2026 19:04
ahmed-n-abdeltwab added a commit to ahmed-n-abdeltwab/Rocket.Chat that referenced this pull request Feb 24, 2026
Co-authored-by: Guilherme Gazzo <guilhermegazzo@gmail.com>
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

gsoc-project stat: QA assured Means it has been tested and approved by a company insider stat: ready to merge PR tested and approved waiting for merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants