Skip to content

chore: convert endpoints do openApi#39553

Open
ggazzo wants to merge 14 commits intodevelopfrom
chore/apis
Open

chore: convert endpoints do openApi#39553
ggazzo wants to merge 14 commits intodevelopfrom
chore/apis

Conversation

@ggazzo
Copy link
Copy Markdown
Member

@ggazzo ggazzo commented Mar 12, 2026

OpenAPI Endpoint Migration

Migrates API endpoints from legacy addRoute to typed .get()/.post() with AJV schema validation for request and response payloads.

Migration Progress

Area Status Endpoints
info, stats, mailer ✅ Migrated 4
push, subscriptions ✅ Migrated 6
invites, custom-user-status, emoji-custom ✅ Migrated 8
commands ✅ Migrated 5
dm/im ✅ Migrated 12
chat, autotranslate ✅ Migrated 14
misc (spotlight, shield.svg) ✅ Migrated 3
rooms ✅ Migrated (partial) 28
teams ✅ Migrated 16
users ✅ Migrated (partial) 24
integrations, moderation ✅ Migrated 6
channels ❌ Remaining 42
groups ❌ Remaining 38
rooms (remaining) ❌ Remaining 2
users (remaining) ❌ Remaining 2

~66% migrated — 84 addRoute endpoints remaining (mostly channels and groups).

What's Included

  • Ajv 2020-12 upgrade — enables unevaluatedProperties for stricter schemas
  • Core/rest typings updatesIMeApiUser, ISubscription, IRoom, IIntegration type improvements
  • API frameworkforbidden()/unauthorized()/success() signature updates, SuccessStatusCodes support
  • Response validation$ref schemas for typed responses, validateBadRequestErrorResponse/validateUnauthorizedErrorResponse/validateForbiddenErrorResponse
  • Test updates — assertions updated for new error formats and ajv coercion behavior
  • Client-side fixes — type adjustments for readStateManager, userData, mapSubscriptionFromApi, RoomsTable, EditRoomInfo

Weak Schemas

508 response schemas still use { type: 'object' } without properties or $ref. These are functional but should be strengthened incrementally.

Commits (each migration is independently revertible)

Each commit contains the endpoint migration + its tests + related type fixes:

  1. chore: upgrade Ajv to 2020-12 and update core/rest typings
  2. chore: API framework changes
  3. chore(api): migrate info, stats, mailer
  4. chore(api): migrate push, subscriptions
  5. chore(api): migrate invites, custom-user-status, emoji-custom
  6. chore(api): migrate commands
  7. chore(api): migrate dm/im
  8. chore(api): migrate chat, autotranslate
  9. chore(api): migrate misc
  10. chore(api): migrate rooms
  11. chore(api): migrate teams
  12. chore(api): migrate users
  13. chore(api): migrate integrations, moderation
  14. chore: add migration tracking scripts and docs

Task: ARCH-2063

@dionisio-bot
Copy link
Copy Markdown
Contributor

dionisio-bot bot commented Mar 12, 2026

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

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

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 12, 2026

⚠️ No Changeset found

Latest commit: 228fc59

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

This PR includes no changesets

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

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

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

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 12, 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

Migrates many endpoints from legacy addRoute patterns to explicit API.get/post handlers with AJV request/response schemas, tightens TypeScript and JSON schemas (me, integration, subscription, push, etc.), adds repository analysis CLI scripts, and applies defensive runtime fixes across client/server code and tests.

Changes

Cohort / File(s) Summary
Default / OpenAPI routes
apps/meteor/app/api/server/default/info.ts, apps/meteor/app/api/server/default/openApi.ts
Switched to API.default.get(...), added AJV-compiled response schemas, moved inline handlers to standalone action() functions, and attached response validation.
V1 API endpoints (schema & wiring)
apps/meteor/app/api/server/v1/.../commands.ts, .../custom-user-status.ts, .../emoji-custom.ts, .../invites.ts, .../mailer.ts, .../misc.ts, .../moderation.ts, .../push.ts, .../stats.ts, .../subscriptions.ts, .../channels.ts
Replaced addRoute with API.v1.get/post(...), introduced AJV request/response schemas (including standardized error schemas), tightened response shapes, and moved handlers into action() functions; includes refined input validation and some control-flow defensive fixes.
/v1/me and getUserInfo
apps/meteor/app/api/server/helpers/getUserInfo.ts, apps/meteor/app/api/server/v1/misc.ts
Changed getUserInfo return type to IMeApiUser, improved service typings, and wired /v1/me to use compiled MeApiSuccessResponse schema, removing permissive object casts.
Core typings updates
packages/core-typings/src/IMeApiUser.ts, IIntegration.ts, ISubscription.ts, IVideoConference.ts, Ajv.ts, index.ts
Added IMeApiUser and service types; made integration token/script and subscription ls/lr optional; removed Nullable helper; expanded typia schema union.
REST typings & me response
packages/rest-typings/src/v1/me.ts, .../me/meSuccessResponse.ts, packages/rest-typings/src/index.ts
Introduced MeApiSuccessResponse type and JSON schema, updated /v1/me endpoint typing to use it, and re-exported new types from package index.
Ajv runtime import change
packages/rest-typings/src/v1/Ajv.ts
Switched Ajv import to ajv/dist/2020 for this package's Ajv instance.
Integrations server changes
apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts, .../updateIncomingIntegration.ts, .../lib/triggerHandler.ts
After insert, fetch and return persisted integration (throw on missing); make $set updates conditional for optional fields; made IntegrationData.token optional in type.
Livechat & client defensive fixes
apps/meteor/app/livechat/imports/server/rest/rooms.ts, apps/meteor/client/lib/chats/readStateManager.ts, apps/meteor/client/lib/userData.ts, apps/meteor/client/lib/utils/mapSubscriptionFromApi.ts
Defensive parsing for boolean/string open, optional chaining and fallbacks for subscription timestamps, safer /v1/me consumption and merging, and conditional ls/lr mapping to Dates.
Authentication startup logging/fixes
apps/meteor/app/authentication/server/startup/index.js
Return removeEmpty(user), refine inactiveReason and username suggestion logic, and add logging around user insertion and re-fetch.
Tests updated
apps/meteor/tests/end-to-end/api/commands.ts, apps/meteor/tests/end-to-end/api/rooms.ts, apps/meteor/tests/end-to-end/apps/slash-command-test-simple.ts
Adjusted e2e assertions to reflect AJV error messages and payload changes; grouped a test with setup/teardown.
Migration tooling scripts
scripts/list-unmigrated-api-endpoints.mjs, scripts/analyze-weak-types.mjs, scripts/list-weak-response-schemas.mjs
Added three CLI scripts to locate legacy addRoute endpoints, detect weak TypeScript/schema patterns, and enumerate permissive response schemas; support JSON output and flags.
Docs
docs/api-endpoint-migration.md
Updated guidance for nullable types, documented known pitfalls for mapped utility types, and added documentation for the new analysis scripts and workflow.
Small/low-risk edits
apps/meteor/app/integrations/server/..., packages/rest-typings/src/v1/push.ts, apps/meteor/app/api/server/ApiClass.ts
Minor signature/typing tweaks (push validators, API.forbidden overloads) and small behavioural/type loosenings across integration types.

Sequence Diagram(s)

(none)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Suggested labels

type: chore

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 64.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'chore: convert endpoints do openApi' is partially related but contains a grammatical error and is vague about scope. Consider revising to 'chore: migrate API endpoints to OpenAPI-driven validation' to be more specific and grammatically correct.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR successfully implements the core objectives from ARCH-2063: replacing manual validation with ajv schemas, adding response validation schemas, and improving type consistency.
Out of Scope Changes check ✅ Passed Changes are within scope: API validation migration, type improvements (IMeApiUser), bug fixes (channels date handling, subscription date optionality), and documentation updates align with ARCH-2063 objectives.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 12, 2026

Codecov Report

❌ Patch coverage is 65.21739% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.18%. Comparing base (fc9ab29) to head (228fc59).
⚠️ Report is 3 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #39553      +/-   ##
===========================================
- Coverage    70.19%   70.18%   -0.02%     
===========================================
  Files         3280     3280              
  Lines       116852   116856       +4     
  Branches     20666    20686      +20     
===========================================
- Hits         82020    82011       -9     
- Misses       31541    31550       +9     
- Partials      3291     3295       +4     
Flag Coverage Δ
e2e 59.65% <58.82%> (-0.03%) ⬇️
e2e-api 46.53% <ø> (-0.04%) ⬇️
unit 71.02% <57.14%> (+<0.01%) ⬆️

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

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

@ggazzo ggazzo force-pushed the chore/apis branch 3 times, most recently from 901177f to 6430325 Compare March 12, 2026 05:10
@ggazzo ggazzo force-pushed the chore/apis branch 9 times, most recently from 26e0171 to 542782d Compare March 20, 2026 03:17
@rc-layne
Copy link
Copy Markdown

rc-layne bot commented Mar 20, 2026

Layne — scan passed

No security issues found on latest push.

@ggazzo ggazzo added this to the 8.3.0 milestone Mar 20, 2026
@ggazzo ggazzo marked this pull request as ready for review March 20, 2026 04:55
@ggazzo ggazzo requested review from a team as code owners March 20, 2026 04:55
@ggazzo
Copy link
Copy Markdown
Member Author

ggazzo commented Mar 20, 2026

/jira ARCH-1464

Copy link
Copy Markdown
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.

12 issues found across 40 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="scripts/analyze-weak-types.mjs">

<violation number="1" location="scripts/analyze-weak-types.mjs:46">
P2: `SCHEMA_WEAK_PATTERNS` is declared but never used, so array schemas without `items` are never detected.</violation>
</file>

<file name="apps/meteor/app/api/server/v1/subscriptions.ts">

<violation number="1" location="apps/meteor/app/api/server/v1/subscriptions.ts:26">
P2: `subscriptions.get` response schema incorrectly validates `remove` items as `ISubscription`, but runtime returns only deletion markers (`_id`, `_deletedAt`).</violation>
</file>

<file name="apps/meteor/app/api/server/v1/custom-user-status.ts">

<violation number="1" location="apps/meteor/app/api/server/v1/custom-user-status.ts:164">
P1: Omitting `statusType` on update now clears it to `''` instead of leaving it unchanged.</violation>
</file>

<file name="apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts">

<violation number="1" location="apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts:179">
P1: Truthy-gating these fields prevents clearing `avatar`, `emoji`, or `alias` to empty strings; use presence checks instead of value truthiness.</violation>
</file>

<file name="scripts/list-weak-response-schemas.mjs">

<violation number="1" location="scripts/list-weak-response-schemas.mjs:16">
P2: Using `URL.pathname` directly can break file scanning on encoded filesystem paths.</violation>

<violation number="2" location="scripts/list-weak-response-schemas.mjs:93">
P2: `bare-object` matching is too broad and flags valid multiline object schemas as weak.</violation>
</file>

<file name="apps/meteor/app/api/server/v1/misc.ts">

<violation number="1" location="apps/meteor/app/api/server/v1/misc.ts:348">
P2: `statusText` is optional on users, so requiring it in the spotlight response schema can reject valid responses.</violation>
</file>

<file name="apps/meteor/app/api/server/v1/channels.ts">

<violation number="1" location="apps/meteor/app/api/server/v1/channels.ts:643">
P1: Using `new Date(0)` counts all historical messages since 1970 as unread for new subscriptions. Fall back to `subscription.ts` to count only messages since the user joined.</violation>
</file>

<file name="apps/meteor/app/api/server/v1/moderation.ts">

<violation number="1" location="apps/meteor/app/api/server/v1/moderation.ts:159">
P2: `createdAt` is validated as `string`, but this endpoint returns `IUser.createdAt` as a `Date`, causing response-schema validation to fail.</violation>
</file>

<file name="apps/meteor/client/lib/userData.ts">

<violation number="1" location="apps/meteor/client/lib/userData.ts:130">
P2: Do not default `email2fa.changedAt` to `new Date()` when the API omits it; this writes a fabricated "changed now" timestamp into user state.

(Based on your team's feedback about avoiding unsafe type assumptions and validating values before coercion.) [FEEDBACK_USED]</violation>
</file>

<file name="apps/meteor/app/api/server/v1/invites.ts">

<violation number="1" location="apps/meteor/app/api/server/v1/invites.ts:63">
P2: `sendInvitationEmail` response schema was loosened with `additionalProperties: true`; this weakens response validation and can hide accidental extra fields.</violation>
</file>

<file name="apps/meteor/app/api/server/v1/mailer.ts">

<violation number="1" location="apps/meteor/app/api/server/v1/mailer.ts:33">
P2: Add a 403 response schema for the permission check on `mailer` so forbidden responses are documented and validated.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

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

14-21: ⚠️ Potential issue | 🟠 Major

statistics still skips the IStats contract.

Line 14 only uses IStats as a generic; the schema itself accepts any object with success: true. This endpoint does not have the fields projection problem from statistics.list, so the actual stats shape can still be enforced here instead of leaving the response effectively untyped.

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

In `@apps/meteor/app/api/server/v1/stats.ts` around lines 14 - 21, The response
schema statisticsResponseSchema currently only enforces success: true and thus
ignores the IStats shape; update the Ajv schema used in statisticsResponseSchema
(or replace it) to fully describe the IStats structure (all expected properties
and types) and set additionalProperties: false (or explicitly include any
allowed extra fields) so compile<IStats>(...) truly enforces the IStats
contract; locate statisticsResponseSchema in stats.ts and expand the properties
object to match IStats (or generate the schema from the TypeScript type) and
then recompile with ajv.compile<IStats>.
🧹 Nitpick comments (4)
apps/meteor/tests/end-to-end/api/rooms.ts (1)

2381-2382: Drop the new inline wait comment.

Please keep the intent in code instead of an implementation comment.

✂️ Suggested cleanup
-				// need to wait for the name update finish
 				await sleep(300);

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

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

In `@apps/meteor/tests/end-to-end/api/rooms.ts` around lines 2381 - 2382, Remove
the inline comment and express the intent by replacing the comment + await
sleep(300) with a clearly named helper call (e.g., await waitForNameUpdate()),
implement that helper to encapsulate the waiting strategy (for now it can call
sleep(300) or, better, poll the name update condition) and keep the existing
sleep function name (sleep) only as the underlying primitive; update any
references in the test to call waitForNameUpdate() instead of using an
implementation comment before sleep.
scripts/list-unmigrated-api-endpoints.mjs (1)

30-45: Count verbs or label this output as “registrations.”

A single addRoute() can still expose multiple handlers, but scan() emits one record per path. That makes the Total and endpoints output registration counts, not endpoint counts, so mixed-method routes understate the remaining migration work.

Also applies to: 81-89

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

In `@scripts/list-unmigrated-api-endpoints.mjs` around lines 30 - 45, The scan()
function currently emits one record per path which undercounts multi-method
handlers; modify scan() to either count verbs per registration or explicitly
label records as "registrations": for each match in scan() (using the existing
regex and extractPaths(match[2])), parse or extract the handler verbs for that
addRoute invocation and include them in the results entries (e.g., add a verbs:
[..] array or a registrations: true flag) so the output reflects handler
multiplicity; also update the downstream aggregation logic that computes totals
(the code that processes results into endpoints/Total around the later block
that iterates over results) to sum verb counts when producing endpoint totals or
to treat the output as registration counts when the records are labeled,
ensuring the final "Total" and endpoints output are accurate and consistent.
apps/meteor/app/api/server/v1/custom-user-status.ts (1)

189-209: Missing body schema for custom-user-status.delete endpoint.

The endpoint accesses this.bodyParams.customUserStatusId (line 200) but no body validator is defined in the route options. This allows arbitrary body payloads without AJV validation, relying on the manual check at lines 201-203 instead of schema enforcement.

Consider adding a body schema for consistency with the other migrated endpoints:

♻️ Proposed fix
+const isCustomUserStatusDeleteProps = ajv.compile<{ customUserStatusId: string }>({
+	type: 'object',
+	properties: {
+		customUserStatusId: { type: 'string' },
+	},
+	required: ['customUserStatusId'],
+	additionalProperties: false,
+});
+
 const customUserStatusDeleteResponseSchema = ajv.compile<void>({
 	type: 'object',
 	properties: {
 		success: { type: 'boolean', enum: [true] },
 	},
 	required: ['success'],
 	additionalProperties: false,
 });
 
 API.v1.post(
 	'custom-user-status.delete',
 	{
 		authRequired: true,
+		body: isCustomUserStatusDeleteProps,
 		response: {
 		},
 	},
 	async function action() {
 		const { customUserStatusId } = this.bodyParams;
-		if (!customUserStatusId) {
-			return API.v1.failure('The "customUserStatusId" params is required!');
-		}
 
 		await deleteCustomUserStatus(this.userId, customUserStatusId);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/app/api/server/v1/custom-user-status.ts` around lines 189 - 209,
Add a request body schema to the custom-user-status.delete route so AJV
validates this.bodyParams.customUserStatusId instead of relying on a manual
runtime check: define a request schema (e.g.,
customUserStatusDeleteRequestSchema) that requires a non-empty
customUserStatusId (string) and add it to the route options under the body key
of the API.v1.post call for 'custom-user-status.delete'; keep the existing
runtime call to deleteCustomUserStatus(this.userId, customUserStatusId)
unchanged but remove the manual presence check if you prefer strict schema
validation only.
apps/meteor/client/lib/userData.ts (1)

126-133: Inconsistent date fallback: new Date() vs new Date(0) pattern.

Lines 109-110 use new Date(0) (epoch) as a sentinel for missing dates, but line 130 uses new Date() (current time) for missing email2fa.changedAt. This inconsistency could cause confusion — a missing changedAt would appear as "just now" rather than "unknown/never set."

Consider using new Date(0) for consistency:

🔧 Suggested fix
 ...(email2fa
   ? {
       email2fa: {
         ...email2fa,
-        changedAt: email2fa.changedAt ? new Date(email2fa.changedAt) : new Date(),
+        changedAt: email2fa.changedAt ? new Date(email2fa.changedAt) : new Date(0),
       },
     }
   : {}),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/client/lib/userData.ts` around lines 126 - 133, The email2fa
object construction is using new Date() as a fallback for email2fa.changedAt
which is inconsistent with other places that use new Date(0) as a sentinel;
update the fallback in the email2fa branch so changedAt uses new Date(0) when
missing (i.e., replace new Date() with new Date(0)) to match the existing epoch
sentinel behavior and ensure uniform "unknown/never set" semantics across the
code that reads changedAt.
🤖 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/emoji-custom.ts`:
- Around line 27-38: The response schema emojiCustomAllResponseSchema currently
sets emojis: { type: 'array' } which doesn't validate array items; update the
schema passed to ajv.compile so the emojis property includes an items schema
(either items: { $ref: '<IEmojiCustom ref>' } if IEmojiCustom is registered with
AJV, or a concrete object schema matching IEmojiCustom) and keep
required/additionalProperties rules; ensure the updated shape still includes
success/count/offset/total and passes AJV compilation in the
emojiCustomAllResponseSchema declaration.

In `@apps/meteor/app/api/server/v1/integrations.ts`:
- Around line 36-38: The Typia schema generation currently only registers
IIntegration, but integrations.ts references IIncomingIntegration and
IOutgoingIntegration; open packages/core-typings/src/Ajv.ts and update the
typia.json.schemas(...) tuple to explicitly import and include
IIncomingIntegration and IOutgoingIntegration (following the pattern used for
IDirectoryChannelResult and IDirectoryUserResult) so those concrete refs are
emitted, or alternatively change the refs in integrations.ts to point to the
existing IIntegration schema name; ensure imports and the typia.json.schemas
call include the two constituent types (IIncomingIntegration,
IOutgoingIntegration) alongside IIntegration.

In `@apps/meteor/app/api/server/v1/push.ts`:
- Around line 235-306: The new GET routes 'push.get' and 'push.info' were added
but not included in the extracted route type, so update the module augmentation
that defines PushEndpoints to include these two routes with their expected
request/response shapes; locate the augmentation that declares PushEndpoints
(the same place that currently exposes 'push.token' and 'push.test') and add
entries for 'push.get' and 'push.info' matching the handlers (use the
pushGetResponseSchema shape for 'push.get' and pushInfoResponseSchema shape for
'push.info', and mark both as authRequired GET endpoints) so typed consumers see
the new routes.

In `@apps/meteor/app/api/server/v1/stats.ts`:
- Around line 98-117: The route API.v1.post handler for 'statistics.telemetry'
accepts an unvalidated body (this.bodyParams) and blindly casts/uses it in
function action; add a proper request body schema to the route options (e.g.,
statisticsTelemetryRequestSchema) that requires a params array of objects with
an eventName string and optional params object, enforce it in the route
definition alongside the existing response schemas, and update action to rely on
the validated shape (or defensively check each event contains eventName before
calling telemetryEvent) so telemetryEvent.call is never invoked with undefined
eventName.

In `@apps/meteor/app/api/server/v1/subscriptions.ts`:
- Around line 19-31: subscriptionsGetResponseSchema currently declares remove
items as full ISubscription docs but the TypeScript type expects tombstones
(Pick<ISubscription, '_id'> & {_deletedAt: Date}); update the schema for the
remove array inside subscriptionsGetResponseSchema so its items are an object
with only the tombstone shape (e.g. properties: { _id: { type: 'string' },
_deletedAt: { type: 'string', format: 'date-time' } } and required:
['_id','_deletedAt']) instead of referencing
'#/components/schemas/ISubscription', so Ajv validation matches the TypeScript
type.

In `@apps/meteor/app/authentication/server/startup/index.js`:
- Around line 214-218: Remove the raw console.log dumps that print full signup
payloads (the two console.log calls around beforeCreateUserCallback.run) and
replace them with either no logging or a redacted logger that only records safe
identifiers (e.g., user._id, user.emailHash or user.username, and a note that
callbacks ran) so sensitive fields (password hashes, OAuth tokens, emails in
plain text, approval state) are never written; update the code referencing
beforeCreateUserCallback, options, and user to use the redaction helper or
remove the logs, and apply the same change to the other occurrences mentioned
(the similar console.log uses at the other indicated locations).

In
`@apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts`:
- Around line 179-181: The current spread checks like ...(integration.avatar &&
{ avatar: integration.avatar }) use truthiness and prevent explicit clears
(e.g., avatar: ''), so change those guards to test for undefined/property
presence instead (e.g., use Object.prototype.hasOwnProperty.call(integration,
'avatar') or integration.avatar !== undefined) for avatar, emoji, alias and
script in the update logic (the spread object construction where
integration.avatar/emoji/alias/script are conditionally added); this preserves
omitted fields as no-ops but allows explicit empty-string clears to overwrite
stored values.

In `@scripts/analyze-weak-types.mjs`:
- Around line 45-58: The scan never runs the array pattern from
SCHEMA_WEAK_PATTERNS because only findWeakSchemaBlocks() is invoked; update the
schema-only scan to also execute the array check by either extending
findWeakSchemaBlocks() to apply all SCHEMA_WEAK_PATTERNS (including the array
rule) or adding and calling a dedicated matcher (e.g.,
findWeakSchemaArrayMatches or applyPatternMatches) that runs the second pattern;
ensure the main flow that handles the --schema-only flag calls the new/updated
function so the "{ type: 'array' } (no items)" case is reported.

In `@scripts/list-weak-response-schemas.mjs`:
- Around line 81-95: The 'bare-object' rule in WEAK_PATTERNS currently only
checks the current line in its test(line, context) and thus flags multi-line
schemas where "properties:" or "$ref"/combiners appear on subsequent lines;
update the test in the 'bare-object' entry to perform a lookahead using the
provided context (e.g., inspect subsequent lines/tokens from context for a small
window like the next 5-10 non-empty lines or until indentation/closing token)
and return false if any of properties, $ref, allOf, oneOf, or anyOf are found in
that lookahead; keep the original current-line checks but rely on this
multi-line scan to avoid false positives for standard multi-line object schemas.
- Around line 41-64: The chained-route regex is too broad and matches unrelated
calls like settings.get; update the third pattern in routePatterns inside
extractEndpoints to only match method calls that are part of router chains (e.g.
API.v1, variables ending with "Router"/"router", or common app/router names) by
changing the regex to require a router-like identifier before the dot (for
example using a non-capturing group like
(?:(?:API\.v1|\w*Router|\w*router|\bapp|\broutes))\.(get|post|put|delete)\(\s*['"`]([^'"`]+)['"`])
and adjust the match indexing logic in extractEndpoints accordingly so name
comes from match[2] and method from match[1].

---

Duplicate comments:
In `@apps/meteor/app/api/server/v1/stats.ts`:
- Around line 14-21: The response schema statisticsResponseSchema currently only
enforces success: true and thus ignores the IStats shape; update the Ajv schema
used in statisticsResponseSchema (or replace it) to fully describe the IStats
structure (all expected properties and types) and set additionalProperties:
false (or explicitly include any allowed extra fields) so compile<IStats>(...)
truly enforces the IStats contract; locate statisticsResponseSchema in stats.ts
and expand the properties object to match IStats (or generate the schema from
the TypeScript type) and then recompile with ajv.compile<IStats>.

---

Nitpick comments:
In `@apps/meteor/app/api/server/v1/custom-user-status.ts`:
- Around line 189-209: Add a request body schema to the
custom-user-status.delete route so AJV validates
this.bodyParams.customUserStatusId instead of relying on a manual runtime check:
define a request schema (e.g., customUserStatusDeleteRequestSchema) that
requires a non-empty customUserStatusId (string) and add it to the route options
under the body key of the API.v1.post call for 'custom-user-status.delete'; keep
the existing runtime call to deleteCustomUserStatus(this.userId,
customUserStatusId) unchanged but remove the manual presence check if you prefer
strict schema validation only.

In `@apps/meteor/client/lib/userData.ts`:
- Around line 126-133: The email2fa object construction is using new Date() as a
fallback for email2fa.changedAt which is inconsistent with other places that use
new Date(0) as a sentinel; update the fallback in the email2fa branch so
changedAt uses new Date(0) when missing (i.e., replace new Date() with new
Date(0)) to match the existing epoch sentinel behavior and ensure uniform
"unknown/never set" semantics across the code that reads changedAt.

In `@apps/meteor/tests/end-to-end/api/rooms.ts`:
- Around line 2381-2382: Remove the inline comment and express the intent by
replacing the comment + await sleep(300) with a clearly named helper call (e.g.,
await waitForNameUpdate()), implement that helper to encapsulate the waiting
strategy (for now it can call sleep(300) or, better, poll the name update
condition) and keep the existing sleep function name (sleep) only as the
underlying primitive; update any references in the test to call
waitForNameUpdate() instead of using an implementation comment before sleep.

In `@scripts/list-unmigrated-api-endpoints.mjs`:
- Around line 30-45: The scan() function currently emits one record per path
which undercounts multi-method handlers; modify scan() to either count verbs per
registration or explicitly label records as "registrations": for each match in
scan() (using the existing regex and extractPaths(match[2])), parse or extract
the handler verbs for that addRoute invocation and include them in the results
entries (e.g., add a verbs: [..] array or a registrations: true flag) so the
output reflects handler multiplicity; also update the downstream aggregation
logic that computes totals (the code that processes results into endpoints/Total
around the later block that iterates over results) to sum verb counts when
producing endpoint totals or to treat the output as registration counts when the
records are labeled, ensuring the final "Total" and endpoints output are
accurate and consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 64fd18d3-3d8b-4604-8dfd-ffb7e49aa940

📥 Commits

Reviewing files that changed from the base of the PR and between 61d3d9a and 542782d.

📒 Files selected for processing (40)
  • apps/meteor/app/api/server/default/info.ts
  • apps/meteor/app/api/server/default/openApi.ts
  • apps/meteor/app/api/server/helpers/getUserInfo.ts
  • apps/meteor/app/api/server/v1/channels.ts
  • apps/meteor/app/api/server/v1/commands.ts
  • apps/meteor/app/api/server/v1/custom-user-status.ts
  • apps/meteor/app/api/server/v1/emoji-custom.ts
  • apps/meteor/app/api/server/v1/integrations.ts
  • apps/meteor/app/api/server/v1/invites.ts
  • apps/meteor/app/api/server/v1/mailer.ts
  • apps/meteor/app/api/server/v1/misc.ts
  • apps/meteor/app/api/server/v1/moderation.ts
  • apps/meteor/app/api/server/v1/push.ts
  • apps/meteor/app/api/server/v1/stats.ts
  • apps/meteor/app/api/server/v1/subscriptions.ts
  • apps/meteor/app/authentication/server/startup/index.js
  • apps/meteor/app/integrations/server/lib/triggerHandler.ts
  • apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts
  • apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts
  • apps/meteor/app/livechat/imports/server/rest/rooms.ts
  • apps/meteor/client/lib/chats/readStateManager.ts
  • apps/meteor/client/lib/userData.ts
  • apps/meteor/client/lib/utils/mapSubscriptionFromApi.ts
  • apps/meteor/tests/end-to-end/api/commands.ts
  • apps/meteor/tests/end-to-end/api/rooms.ts
  • apps/meteor/tests/end-to-end/apps/slash-command-test-simple.ts
  • docs/api-endpoint-migration.md
  • packages/core-typings/src/Ajv.ts
  • packages/core-typings/src/IIntegration.ts
  • packages/core-typings/src/IMeApiUser.ts
  • packages/core-typings/src/ISubscription.ts
  • packages/core-typings/src/IVideoConference.ts
  • packages/core-typings/src/index.ts
  • packages/rest-typings/src/index.ts
  • packages/rest-typings/src/v1/Ajv.ts
  • packages/rest-typings/src/v1/me.ts
  • packages/rest-typings/src/v1/me/meSuccessResponse.ts
  • scripts/analyze-weak-types.mjs
  • scripts/list-unmigrated-api-endpoints.mjs
  • scripts/list-weak-response-schemas.mjs

@ggazzo ggazzo added this to the 8.4.0 milestone Mar 24, 2026
const statisticsListResponseSchema = ajv.compile<{ statistics: IStats[]; count: number; offset: number; total: number }>({
type: 'object',
properties: {
statistics: { type: 'array' },
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.

Suggested change
statistics: { type: 'array' },
statistics: { type: 'array', items: { $ref: '#/components/schemas/IStats' } },

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.

And we would need to add it in Ajv.ts typia schemas

Copy link
Copy Markdown
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.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/meteor/app/api/server/v1/autotranslate.ts">

<violation number="1" location="apps/meteor/app/api/server/v1/autotranslate.ts:94">
P1: Validate `field`/`value` compatibility before saving. The current line allows boolean values for `autoTranslateLanguage` (e.g., `true` -> `'1'`), which persists invalid language settings.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@cubic-dev-ai
Copy link
Copy Markdown
Contributor

cubic-dev-ai bot commented Apr 14, 2026

You're iterating quickly on this pull request. To help protect your rate limits, cubic has paused automatic reviews on new pushes for now—when you're ready for another review, comment @cubic-dev-ai review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants