Skip to content

Conversation

@nazabucciarelli
Copy link
Contributor

@nazabucciarelli nazabucciarelli commented Jan 22, 2026

Proposed changes (including videos or screenshots)

After some investigation, context gathering, and a discussion with Diego Sampaio, we aligned on the scope of this task.

The goal is to improve how DDP connection headers are handled in sauMonitorHooks.ts.
While the broader issue involves multiple places where the full connection object is passed downstream instead of only the required data, addressing all of those cases is outside the scope of this task.

Changes:

  • To make the change safer and more explicit, I will introduce dedicated types for the event payloads instead of passing the entire connection object.
  • SAU events where renamed adding 'sau.' as prefix in order to avoid confusion with already existent events, such as 'accounts.login' or 'accounts.logout'.
  • As I'm funneling the properties we pass downstream in the hook, the lower level functions where simplified, removing additional logic and making it even more readable.
  • getHeaders() function was added to extract headers in a safer way, regardless the connection was through HTTP or DDP.

Issue(s)

CORE-1529 - Improve DDP header handling

Steps to test or reproduce

Further comments

Doubt:
Are the new types (DeviceLoginPayload, LoginSessionPayload, LogoutSessionPayload) and the util function (getHeader) properly located in the directory tree?

Summary by CodeRabbit

Release Notes

  • Refactor
    • Enhanced session and device login event handling infrastructure to improve tracking consistency and data accuracy across the platform.

✏️ Tip: You can customize this high-level summary in your review settings.

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Jan 22, 2026

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

  • This PR is missing the 'stat: QA assured' label
  • This PR is missing the required milestone or project

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 Jan 22, 2026

⚠️ No Changeset found

Latest commit: e76d829

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

This PR includes no changesets

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

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

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 22, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This pull request refactors event payload structures across SAU monitoring and device management systems by replacing connection object passing with explicit typed fields (userId, instanceId, userAgent, loginToken, connectionId, clientAddress, host). It renames generic event names to SAU-prefixed variants and introduces a new header retrieval utility function.

Changes

Cohort / File(s) Summary
Event Definition Updates
apps/meteor/server/services/sauMonitor/events.ts, apps/meteor/server/services/device-management/events.ts
Updated event payload types to use explicit fields instead of connection objects; renamed accounts/socket events to sau-prefixed variants (accounts.loginsau.accounts.login, socket.disconnectedsau.socket.disconnected, etc.)
Event Emission Handlers
apps/meteor/server/hooks/sauMonitorHooks.ts, apps/meteor/server/services/sauMonitor/service.ts, apps/meteor/server/services/device-management/service.ts
Updated event handlers to destructure payloads, extract userId/instanceId/userAgent/loginToken/clientAddress from connection or provided data, and emit with new event names and structured payloads
Monitor Processing Logic
apps/meteor/app/statistics/server/lib/SAUMonitor.ts, apps/meteor/ee/server/lib/deviceManagement/session.ts
Updated session handlers to accept destructured arguments and payload fields instead of connection objects; replaced connection-based UA parsing with direct userAgent string handling
Utility Support
apps/meteor/server/lib/getHeader.ts
NEW: Added getHeader utility function for safe header retrieval supporting both Headers-like API and plain object maps

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

stat: ready to merge, stat: QA assured

Suggested reviewers

  • cardoso
  • sampaiodiego

Poem

🐰 Events now speak plainly, no connection needed here,
Payloads bloom with fields explicit, crystal clear!
From hooks to monitors, the data flows so free,
Typed and tidy throughout—hop, hop, merrily! 🎉

🚥 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 'chore: improve the way we send DDP connection data to hooks' accurately describes the main objective of refactoring how connection data is passed to hooks, making event payloads more specific instead of passing full connection objects.
Linked Issues check ✅ Passed The PR implements event payload restructuring and introduces dedicated types (LoginSessionPayload, LogoutSessionPayload) with new 'sau.' event namespaces, improving DDP header handling as required by CORE-1529.
Out of Scope Changes check ✅ Passed All changes are focused on improving DDP connection data handling through event payload restructuring, type introduction, and utilities. No unrelated or extraneous modifications are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/ddp-headers

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.

@nazabucciarelli
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 22, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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/statistics/server/lib/SAUMonitor.ts (1)

135-142: Update logout log messages to the new event name.

The warning strings still mention 'accounts.logout', which no longer matches the hook name and can mislead debugging.

🔧 Suggested fix
-			if (!userId) {
-				logger.warn({ msg: "Received 'accounts.logout' event without 'userId'" });
+			if (!userId) {
+				logger.warn({ msg: "Received 'sau.accounts.logout' event without 'userId'" });
 				return;
 			}
 
 			if (!sessionId) {
-				logger.warn({ msg: "Received 'accounts.logout' event without 'sessionId'" });
+				logger.warn({ msg: "Received 'sau.accounts.logout' event without 'sessionId'" });
 				return;
 			}
🤖 Fix all issues with AI agents
In `@packages/core-typings/src/sau/SocketConnectedPayload.ts`:
- Around line 1-3: Remove the inline comment inside the SocketConnectedPayload
type and replace the placeholder with an explicit empty payload type;
specifically, update export type SocketConnectedPayload to an explicit empty
shape (e.g., use Record<string, never> or an empty object type) so the intent is
encoded in the type rather than a comment and the inline comment is removed.
🧹 Nitpick comments (3)
apps/meteor/server/services/sauMonitor/service.ts (1)

35-38: Remove commented-out debug statement.

Per coding guidelines, avoid code comments in the implementation. This commented-out console.log should be removed.

Suggested fix
 		this.onEvent('socket.connected', async (data) => {
-			// console.log('socket.connected', data);
 			sauEvents.emit('sau.socket.connected', data);
 		});
apps/meteor/server/services/device-management/service.ts (1)

14-19: Address TODO: Add loginToken to payload.

The TODO indicates loginToken should be added to the device-login payload. The DeviceLoginPayload type already supports an optional loginToken field (as seen in session.ts usage at line 42).

Would you like me to help implement the loginToken extraction similar to how it's done in sauMonitorHooks.ts (using Accounts._hashLoginToken(resume))? Or should I open an issue to track this task?

apps/meteor/server/hooks/sauMonitorHooks.ts (1)

80-86: Remove inline comment and clarify SocketConnectedPayload intent.

The comment on line 82 should be removed per coding guidelines. Additionally, spreading the entire connection object into SocketConnectedPayload appears to contradict the PR's goal of avoiding passing full connection objects downstream. Consider extracting only the required fields.

Suggested fix

If only specific fields are needed, extract them explicitly:

 Meteor.onConnection((connection) => {
 	const socketConnectedEventObject: SocketConnectedPayload = {
-		// Implement SocketConnectedPayload type in case of using the sau.socket.connected hook
-		...connection,
+		connectionId: connection.id,
+		// Add other required fields as needed
 	};
 	sauEvents.emit('sau.socket.connected', socketConnectedEventObject);
 });

If the full connection is intentionally needed here, the comment should at minimum be removed.

@codecov
Copy link

codecov bot commented Jan 22, 2026

Codecov Report

❌ Patch coverage is 55.00000% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.73%. Comparing base (c107092) to head (e76d829).
⚠️ Report is 3 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #38294      +/-   ##
===========================================
- Coverage    70.73%   70.73%   -0.01%     
===========================================
  Files         3158     3160       +2     
  Lines       109359   109391      +32     
  Branches     19695    19645      -50     
===========================================
+ Hits         77358    77380      +22     
- Misses       29966    29976      +10     
  Partials      2035     2035              
Flag Coverage Δ
unit 71.89% <ø> (+0.02%) ⬆️

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.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 22, 2026

📦 Docker Image Size Report

➡️ Changes

Service Current Baseline Change Percent
sum of all images 0B 0B 0B
account-service 0B 0B 0B
authorization-service 0B 0B 0B
ddp-streamer-service 0B 0B 0B
omnichannel-transcript-service 0B 0B 0B
presence-service 0B 0B 0B
queue-worker-service 0B 0B 0B
rocketchat 0B 0B 0B

📊 Historical Trend

---
config:
  theme: "dark"
  xyChart:
    width: 900
    height: 400
---
xychart
  title "Image Size Evolution by Service (Last 30 Days + This PR)"
  x-axis ["11/18 22:53", "11/19 23:02", "11/21 16:49", "11/24 17:34", "11/27 22:32", "11/28 19:05", "12/01 23:01", "12/02 21:57", "12/03 21:00", "12/04 18:17", "12/05 21:56", "12/08 20:15", "12/09 22:17", "12/10 23:26", "12/11 21:56", "12/12 22:45", "12/13 01:34", "12/15 22:31", "12/16 22:18", "12/17 21:04", "12/18 23:12", "12/19 23:27", "12/20 21:03", "12/22 18:54", "12/23 16:16", "12/24 19:38", "12/25 17:51", "12/26 13:18", "12/29 19:01", "12/30 20:52", "01/23 22:27 (PR)"]
  y-axis "Size (GB)" 0 --> 0.5
  line "account-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "authorization-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "ddp-streamer-service" [0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.00]
  line "omnichannel-transcript-service" [0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.00]
  line "presence-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "queue-worker-service" [0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.00]
  line "rocketchat" [0.35, 0.35, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.00]
Loading

Statistics (last 30 days):

  • 📊 Average: 1.5GiB
  • ⬇️ Minimum: 1.4GiB
  • ⬆️ Maximum: 1.6GiB
  • 🎯 Current PR: 0B
ℹ️ About this report

This report compares Docker image sizes from this build against the develop baseline.

  • Tag: pr-38294
  • Baseline: develop
  • Timestamp: 2026-01-23 22:27:11 UTC
  • Historical data points: 30

Updated: Fri, 23 Jan 2026 22:27:12 GMT

@nazabucciarelli
Copy link
Contributor Author

nazabucciarelli commented Jan 22, 2026

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 22, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

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/statistics/server/lib/SAUMonitor.ts (1)

235-245: Replace the inline TODO block with an explicit UA result type.

The comment block violates the "no implementation comments" guideline. Move the type information into code as a type alias instead.

However, the proposed solution using ReturnType<typeof UAParserMobile.uaObject> won't work as expected since UAParserCustom.js is untyped JavaScript. Define the union type explicitly instead:

♻️ Suggested approach
+	type UAResult =
+		| UAParser.IResult
+		| { device?: { type: string }; app?: { name: string; version: string }; browser?: undefined; os?: undefined }
+		| { device?: { type: string }; os?: Record<string, string>; app?: { name: string; version: string }; browser?: undefined };
+
-	const result = ((): any => {
+	const result = ((): UAResult => {

The types correspond to the three code branches: standard UAParser, mobile app, and desktop app respectively.

♻️ Duplicate comments (1)
packages/core-typings/src/sau/SocketConnectedPayload.ts (1)

1-2: Remove inline comment; encode empty payload in the type.

Line 1 violates the “no implementation comments” guideline; encode the empty payload via the type instead. As per coding guidelines, avoid code comments in implementation.

♻️ Proposed change
-export type SocketConnectedPayload = {};
+export type SocketConnectedPayload = Record<string, never>;
Is `Record<string, never>` the recommended TypeScript pattern for expressing an empty object payload?

@nazabucciarelli nazabucciarelli marked this pull request as ready for review January 23, 2026 16:47
@nazabucciarelli nazabucciarelli requested review from a team as code owners January 23, 2026 16:47
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 14 files

@nazabucciarelli
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 23, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

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/statistics/server/lib/SAUMonitor.ts (1)

130-157: Potential logout miss when loginToken is absent.
LoginSessionPayload.loginToken and ISession.loginToken are optional, but this path treats a missing token as “session not found” and returns. That can leave sessions open and skew SAU. Consider enforcing a non-optional token in the payload or adding a fallback to close by sessionId when the token is missing.

🔧 Suggested fallback when `loginToken` is missing
-			const session = await Sessions.getLoggedInByUserIdAndSessionId<Pick<ISession, 'loginToken'>>(userId, sessionId, {
-				projection: { loginToken: 1 },
-			});
-			if (!session?.loginToken) {
+			const session = await Sessions.getLoggedInByUserIdAndSessionId<Pick<ISession, 'loginToken' | 'instanceId'>>(userId, sessionId, {
+				projection: { loginToken: 1, instanceId: 1 },
+			});
+			if (!session) {
 				if (!isProdEnv) {
 					throw new Error('Session not found during logout');
 				}
 				logger.error({ msg: 'Session not found during logout', userId, sessionId });
 				return;
 			}
+			if (!session.loginToken) {
+				await Sessions.closeByInstanceIdAndSessionId(session.instanceId, sessionId);
+				return;
+			}
 
 			await Sessions.logoutBySessionIdAndUserId({ loginToken: session.loginToken, userId });

@nazabucciarelli
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 23, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

🤖 Fix all issues with AI agents
In `@apps/meteor/server/services/sauMonitor/events.ts`:
- Around line 4-12: The event type for 'sau.accounts.login' is inconsistent with
ISocketConnection because connection.loginToken is optional; update the event
definition in events.ts to make loginToken optional (change loginToken: string
to loginToken?: string) so it matches ISocketConnection and avoids the type
contract violation, then recompile/typecheck; alternatively, if you prefer
forcing a string, update the caller in service.ts where connection.loginToken is
passed to provide a default (e.g., connection.loginToken ?? '')—pick one
approach and apply it consistently across sau.accounts.login, service.ts, and
references in sauMonitorHooks.ts.
🧹 Nitpick comments (3)
apps/meteor/server/services/sauMonitor/service.ts (1)

42-45: Remove commented-out debug code.

The commented console.log statement should be removed to keep the codebase clean.

♻️ Proposed fix
 		this.onEvent('socket.connected', async (data) => {
-			// console.log('socket.connected', data);
 			sauEvents.emit('sau.socket.connected', { instanceId: InstanceStatus.id(), connectionId: data.id });
 		});
apps/meteor/server/hooks/sauMonitorHooks.ts (1)

49-58: Consider consolidating the two Meteor.onConnection handlers.

Both handlers register on the same connection event. Merging them would reduce overhead and improve code organization.

♻️ Proposed consolidation
 Meteor.onConnection((connection) => {
+	// in case of implementing a listener of this event, define the parameters type in services/sauMonitor/events.ts
+	sauEvents.emit('sau.socket.connected', { instanceId: InstanceStatus.id(), connectionId: connection.id });
+
 	connection.onClose(async () => {
 		sauEvents.emit('sau.socket.disconnected', { connectionId: connection.id, instanceId: InstanceStatus.id() });
 	});
 });
-
-Meteor.onConnection((connection) => {
-	// in case of implementing a listener of this event, define the parameters type in services/sauMonitor/events.ts
-	sauEvents.emit('sau.socket.connected', { instanceId: InstanceStatus.id(), connectionId: connection.id });
-});
apps/meteor/app/statistics/server/lib/SAUMonitor.ts (1)

238-307: Return type includes undefined but function always returns a value.

The function always returns { device: info } (lines 304-306), but the return type is { device: ISessionDevice } | undefined. This could lead to unnecessary null checks by callers.

♻️ Proposed fix
-	private _getUserAgentInfo(uaString: string): { device: ISessionDevice } | undefined {
+	private _getUserAgentInfo(uaString: string): { device: ISessionDevice } {

@nazabucciarelli nazabucciarelli marked this pull request as draft January 23, 2026 21:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants