Skip to content

chore(api): migrate groups.ts to typed HTTP methods - #41422

Merged
ggazzo merged 6 commits into
developfrom
chore/api-migrate-groups
Jul 29, 2026
Merged

chore(api): migrate groups.ts to typed HTTP methods#41422
ggazzo merged 6 commits into
developfrom
chore/api-migrate-groups

Conversation

@ggazzo

@ggazzo ggazzo commented Jul 16, 2026

Copy link
Copy Markdown
Member

Proposed changes

Continues the API endpoint migration (docs/api-endpoint-migration.md): migrates apps/meteor/server/api/v1/groups.ts (mirror of channels.ts, see #41415) from legacy API.v1.addRoute() to the typed API.v1.get/post pattern with AJV request/response validation.

WIP / incremental. groups.* endpoints are already declared in GroupsEndpoints (rest-typings), so this follows the moderation pattern: convert the registration and add response schemas, keeping the manual Endpoints entry (no augmentation).

Migrated so far

  • groups.addAll, groups.addModerator, groups.addOwner, groups.addLeader, groups.archive, groups.close

Notes

  • Shared groupResponseSchema ($ref IRoom) + successResponseSchema.
  • These endpoints had no validateParams, so inline ajv body validators are used (roomTargetBody / roomUserBody), matching the inline-validator style in rooms.ts/users.ts.
  • getRoomFromParams / findPrivateGroupByIdOrName and the room methods throw Meteor.Error; the typed router does not convert throws to 400, so each handler catches and returns API.v1.failure(message, errorType). Errors from core-services are not instanceof Meteor.Error, so message/errorType are extracted by shape.
  • No behavior change intended — pure refactor/typing; no changeset needed.
  • Remaining groups.* endpoints follow in subsequent batches; messages/history/files return IMessage (attachment oneOf validation limitation).

Testing

  • tsc --noEmit, eslint and prettier clean for the migrated file.
  • Response schemas validate only under TEST_MODE; the e2e groups suite exercises them.

Review in cubic

Task: ARCH-2316

Summary by CodeRabbit

  • API Improvements
    • Standardized request validation and consistent response shapes across private-group management endpoints.
    • Improved access checks for actions performed on private groups.
    • Updated validation messaging for invalid group settings (including requiring encrypted to be a boolean).
  • Tests
    • Adjusted the /groups.setEncrypted end-to-end test to match the new validation error message.

@dionisio-bot

dionisio-bot Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

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

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

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot

changeset-bot Bot commented Jul 16, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 492b87c

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

This PR includes no changesets

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

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

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

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3a0609dc-17f6-40c2-8391-5cead1448053

📥 Commits

Reviewing files that changed from the base of the PR and between 1ce9295 and b486517.

📒 Files selected for processing (1)
  • apps/meteor/server/api/v1/groups.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/meteor/server/api/v1/groups.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout. (5)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: CodeQL-Build
  • GitHub Check: Hacktron Security Check
  • GitHub Check: CodeQL-Build

Walkthrough

Private-group management endpoints were migrated from legacy route handlers to schema-driven API.v1.post actions. Shared AJV schemas validate request bodies and responses, user lookup projection was corrected, and encrypted-group validation tests were updated.

Changes

Private group API

Layer / File(s) Summary
Shared schemas and core group routes
apps/meteor/server/api/v1/groups.ts
Adds shared AJV request/response schemas, updates acting-user projection fields, and migrates core group-management routes to typed API.v1.post actions.
Membership mutation routes
apps/meteor/server/api/v1/groups.ts
Migrates groups.kick and groups.leave to shared schema validation while preserving membership operations.
Remaining mutations and encrypted validation
apps/meteor/server/api/v1/groups.ts, apps/meteor/tests/end-to-end/api/groups.ts
Migrates additional group mutation routes, replaces manual encrypted-field validation, and updates the invalid-payload test expectation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested labels: type: chore

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: migrating groups.ts to typed HTTP methods.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • ARCH-2316: Request failed with status code 401

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.

@ggazzo ggazzo added this to the 8.7.0 milestone Jul 16, 2026
@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.95238% with 28 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.73%. Comparing base (b3eee9b) to head (492b87c).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff            @@
##           develop   #41422   +/-   ##
========================================
  Coverage    68.73%   68.73%           
========================================
  Files         4151     4151           
  Lines       159516   159513    -3     
  Branches     27957    27978   +21     
========================================
+ Hits        109646   109648    +2     
  Misses       44687    44687           
+ Partials      5183     5178    -5     
Flag Coverage Δ
e2e 58.82% <ø> (-0.07%) ⬇️
e2e-api 45.66% <80.95%> (-0.28%) ⬇️
unit 70.73% <ø> (+0.04%) ⬆️

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

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

@ggazzo

ggazzo commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

🤝 Handoff — continuing in a fresh session

State: groups.ts is 22/38 migrated (last commit cac191eddd). tsc/eslint/prettier clean. Worktree .claude/worktrees/api-groups, branch chore/api-migrate-groups (off develop).

groups.ts is the mirror of channels.ts (#41415) — follow the detailed handoff on #41415 for all conventions/pitfalls (throw→500 + try/catch + errorToFailureArgs, no new rest-typings exports → inline ajv.compile validators, ajvQuery for GET, type≠DB reality, remember to change the API.v1.addRoute( line, IMessage attachment oneOf relax).

Groups specifics: responses use group (not channel) via groupResponseSchema ($ref IRoom); the find helper is findPrivateGroupByIdOrName / getRoomFromParams (both throw Meteor.Error); helpers already in file: groupResponseSchema, successResponseSchema, errorToFailureArgs, roomTargetBody<T>(extra, required), roomUserBody<T>(), stringFieldResponseSchema<T>, field response schemas.

Remaining (16)

GET: info, list, listAll, members, moderators, online, counters, roles, getIntegrations, files · IMessage (relax): messages, history · POST: create, delete, invite, convertToTeam ({team}/ITeam).

All mechanical POST actions + setters + role-ops are done; remaining is GET return-schema authoring + IMessage relax + create/convertToTeam.

@ggazzo ggazzo modified the milestones: 8.7.0, 8.8.0 Jul 22, 2026
@ggazzo
ggazzo marked this pull request as ready for review July 29, 2026 18:51
@ggazzo
ggazzo requested a review from a team as a code owner July 29, 2026 18:51
@ggazzo

ggazzo commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

/jira ARCH-1464

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
apps/meteor/server/api/v1/groups.ts (2)

151-158: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Nit: ajv.compile<void> and the inline comment.

The 200 payload is { success: true }, not void; consider ajv.compile<{ success: boolean }> for accurate typing. Also drop the explanatory comment on Line 158 — the helper name already conveys it.

As per coding guidelines: "Avoid code comments in the implementation".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/meteor/server/api/v1/groups.ts` around lines 151 - 158, Update
successResponseSchema to compile against { success: boolean } instead of void,
matching the actual { success: true } response payload, and remove the
explanatory inline body-validator comment beneath it.

Source: Coding guidelines


228-228: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the repeated body type literal.

The same { roomId?: string; roomName?: string; userId?: string; username?: string; user?: string } literal is repeated at Lines 228, 253, 278, 727, 1026, 1051, 1076. A single type RoomUserBody = ... (or making roomUserBody return that type by default) removes the duplication.

Also applies to: 253-253, 278-278

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/meteor/server/api/v1/groups.ts` at line 228, Extract the repeated
optional room/user fields into a shared RoomUserBody type near the existing body
definitions, then reuse it at the body declarations currently using the inline
literal, including the occurrences around lines 228, 253, 278, 727, 1026, 1051,
and 1076. Preserve the existing optional fields and roomUserBody behavior while
removing the duplicated type literals.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/meteor/server/api/v1/groups.ts`:
- Around line 194-210: Update the activeUsersOnly coercion in the action using
findPrivateGroupByIdOrName and addAllUserToRoomFn to recognize boolean true,
string "true" or "1", and numeric 1 as enabled. Preserve false behavior for
other accepted values so only active users are selected when any supported
truthy representation is provided.

---

Nitpick comments:
In `@apps/meteor/server/api/v1/groups.ts`:
- Around line 151-158: Update successResponseSchema to compile against {
success: boolean } instead of void, matching the actual { success: true }
response payload, and remove the explanatory inline body-validator comment
beneath it.
- Line 228: Extract the repeated optional room/user fields into a shared
RoomUserBody type near the existing body definitions, then reuse it at the body
declarations currently using the inline literal, including the occurrences
around lines 228, 253, 278, 727, 1026, 1051, and 1076. Preserve the existing
optional fields and roomUserBody behavior while removing the duplicated type
literals.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6098601c-a0aa-4597-a70b-73eb0e7fd76f

📥 Commits

Reviewing files that changed from the base of the PR and between 2ec4d29 and 1ce9295.

📒 Files selected for processing (2)
  • apps/meteor/server/api/v1/groups.ts
  • apps/meteor/tests/end-to-end/api/groups.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: Hacktron Security Check
🧰 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/tests/end-to-end/api/groups.ts
  • apps/meteor/server/api/v1/groups.ts
🧠 Learnings (3)
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • apps/meteor/tests/end-to-end/api/groups.ts
  • apps/meteor/server/api/v1/groups.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • apps/meteor/tests/end-to-end/api/groups.ts
  • apps/meteor/server/api/v1/groups.ts
📚 Learning: 2026-05-06T12:21:44.083Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 40256
File: apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx:121-149
Timestamp: 2026-05-06T12:21:44.083Z
Learning: Field wrappers in rocket.chat/fuselage-forms (Field, FieldLabel, FieldRow, FieldError, FieldHint) auto-create htmlFor/id associations, aria-describedby, and role="alert" for errors. Do not manually set htmlFor, id, aria-describedby, or role attributes when using these wrappers. This automatic wiring does not apply to plain rocket.chat/fuselage components, which require explicit ID wiring per the accessibility docs. In code reviews, prefer using fuselage-forms wrappers for form fields and verify there is no unnecessary manual ID/aria wiring in files that use these wrappers. If a component uses plain fuselage components, ensure proper id wiring as per docs.

Applied to files:

  • apps/meteor/tests/end-to-end/api/groups.ts
  • apps/meteor/server/api/v1/groups.ts
🔇 Additional comments (8)
apps/meteor/server/api/v1/groups.ts (7)

11-18: LGTM!

Also applies to: 116-116


299-346: LGTM!


723-772: LGTM!


994-1095: LGTM!


1097-1362: LGTM!


1408-1437: LGTM!


159-170: 🗄️ Data Integrity & Integration

No action needed.

apps/meteor/tests/end-to-end/api/groups.ts (1)

2574-2574: LGTM!

Comment thread apps/meteor/server/api/v1/groups.ts Outdated

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 2 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread apps/meteor/server/api/v1/groups.ts
Comment thread apps/meteor/server/api/v1/groups.ts Outdated
ggazzo added 6 commits July 29, 2026 16:46
WIP migrating groups.ts (mirror of channels.ts) from addRoute to typed API.v1
(moderation pattern — keep manual GroupsEndpoints entry, no augment). Batch 1:
addAll, addModerator, addOwner, addLeader, archive, close.

- Shared groupResponseSchema ($ref IRoom) + successResponseSchema.
- Inline ajv body validators (roomTargetBody / roomUserBody) since these
  endpoints had no validateParams.
- getRoomFromParams/findPrivateGroupByIdOrName throw Meteor.Error; the typed
  router does not map throws to 400, so handlers catch and return
  API.v1.failure (errorToFailureArgs extracts message/errorType by shape for
  core-services errors).
…rypted + role-removes (batch 2)

Migrate open, kick, leave, unarchive, rename, setEncrypted and remove{Moderator,
Owner,Leader}. Same pattern as channels: inline ajv body validators, group
response via $ref IRoom, findPrivateGroupByIdOrName throws caught -> failure.
Migrate setCustomFields, setReadOnly, setType (->group) and setDescription,
setPurpose, setTopic, setAnnouncement (->{field}). Inline ajv body validators.
…boolean param

The dead 'bodyParam encrypted is required' branch was removed (schema already
marks encrypted required+boolean); a non-boolean value now fails AJV body
validation with 'must be boolean'. Update the assertion accordingly.
…et in groups

- addAll: accept boolean true for activeUsersOnly (schema allows boolean|string|number)
- roomTargetBody: anyOf -> oneOf so exactly one of roomId/roomName is required
@ggazzo
ggazzo force-pushed the chore/api-migrate-groups branch from b486517 to 492b87c Compare July 29, 2026 19:47
@ggazzo
ggazzo merged commit cff1ac2 into develop Jul 29, 2026
96 of 100 checks passed
@ggazzo
ggazzo deleted the chore/api-migrate-groups branch July 29, 2026 20:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Development

Successfully merging this pull request may close these issues.

2 participants