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.
  • _getConnectionInfo was removed because it was a thin wrapper with no transformation or validation logic.
    Keeping the object construction at the call site improves traceability of fields (e.g. loginToken, instanceId, httpHeaders) and reduces unnecessary indirection.
  • Improved overall code readability.

Related to #38268

Issue(s)

CORE-1529 - Improve DDP header handling

Steps to test or reproduce

Further comments

Please keep in mind that this PR touches sensitive code, such as sessions and login/logout.

Summary by CodeRabbit

  • Refactor

    • Standardized authentication and socket events to compact, strongly-typed sau.* payloads; device-login payloads simplified to userAgent and clientAddress.
  • Bug Fixes

    • Session and logout flows now use explicit sessionId; user-agent and IP consistently sourced from event payloads.
  • New Features

    • Added and exported a reusable header-extraction utility.
  • Tests

    • Added tests covering header-extraction edge cases.

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

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: 5b2120c

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

Walkthrough

Server event flow switched to strongly-typed, sau-prefixed events carrying explicit payload fields (userAgent, loginToken, clientAddress, instanceId, connectionId, host). SAUMonitor and device-management consume these payloads, parse UA strings from payloads, and a new getHeader utility exposes safe header extraction.

Changes

Cohort / File(s) Summary
SAU Event Types & Emitters
apps/meteor/server/services/sauMonitor/events.ts, apps/meteor/server/services/sauMonitor/service.ts
Introduce sau.* event names and explicit payload types (userId, instanceId, connectionId, loginToken?, clientAddress, userAgent, host); remove ISocketConnection-based payloads and update emitters.
Hooks / Event Producers
apps/meteor/server/hooks/sauMonitorHooks.ts
Login/logout/socket hooks now compute and emit typed payloads (sau.accounts.login, sau.accounts.logout, sau.socket.connected, sau.socket.disconnected) without embedding httpHeaders.
SAU Monitor Implementation
apps/meteor/app/statistics/server/lib/SAUMonitor.ts
_handleSession signature changed to accept HandleSessionArgs + params; UA parsing moved to _getUserAgentInfo(uaString); removed _getConnectionInfo and reliance on connection object; session data assembled from payload fields.
Device Management Events & Service
apps/meteor/server/services/device-management/events.ts, apps/meteor/server/services/device-management/service.ts, apps/meteor/ee/server/lib/deviceManagement/session.ts
device-login payload changed to { userId, userAgent, clientAddress }; handlers destructure these fields, parse UA from provided string, and use clientAddress directly; emission guarded by absence of loginToken.
Header Utility
packages/tools/src/getHeader.ts, packages/tools/src/getHeader.spec.ts, packages/tools/src/index.ts
Add getHeader utility and tests; export it from tools index for safe header extraction from IncomingHttpHeaders / Headers / plain objects.

Sequence Diagram(s)

sequenceDiagram
  participant Hooks as Hooks (sauMonitorHooks)
  participant SauService as Sau Service (sau)
  participant SAUMonitor as SAUMonitor
  participant DeviceMgmt as Device Management

  Hooks->>SauService: emit sau.accounts.login {userId, instanceId, connectionId, loginToken?, clientAddress, userAgent, host}
  SauService->>SAUMonitor: forward sau.accounts.login payload
  SAUMonitor->>SAUMonitor: _getUserAgentInfo(userAgent) -> device info
  SAUMonitor->>SAUMonitor: _handleSession({userId,...}, params) -> persist/update session

  Hooks->>SauService: emit sau.socket.disconnected {instanceId, connectionId}
  SauService->>SAUMonitor: forward sau.socket.disconnected
  SAUMonitor->>SAUMonitor: finish sessions for connectionId

  SauService->>DeviceMgmt: emit device-login {userId, userAgent, clientAddress}
  DeviceMgmt->>DeviceMgmt: parse UA, send notifications/emails
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

stat: ready to merge, stat: QA assured

Suggested reviewers

  • sampaiodiego
  • cardoso

Poem

🐰 I hopped through events, tidy and bright,
I pulled the UA from a single light,
Payloads now neat, connections small,
Sessions tracked steady, one and all,
A rabbit nods — the monitor's right!

🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive Linked issue CORE-1529 has no visible requirements or acceptance criteria in the provided context. Add detailed acceptance criteria to the linked issue or provide additional documentation clarifying the expected outcomes of this refactoring.
✅ Passed checks (3 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed All code changes directly support the stated objective of improving DDP connection data handling through dedicated payloads, event renaming, and utility functions.
Title check ✅ Passed The title accurately summarizes the main objective of the pull request, which is refactoring how DDP connection data is sent to hooks by introducing dedicated event payload types and renaming SAU events.
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.

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

Important

Action Needed: IP Allowlist Update

If your organization protects your Git platform with IP whitelisting, please add the new CodeRabbit IP address to your allowlist:

  • 136.113.208.247/32 (new)
  • 34.170.211.100/32
  • 35.222.179.152/32

Reviews will stop working after February 8, 2026 if the new IP is not added to your allowlist.


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 60.00000% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.39%. Comparing base (c53312f) to head (5b2120c).
⚠️ Report is 2 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #38294      +/-   ##
===========================================
+ Coverage    70.35%   70.39%   +0.03%     
===========================================
  Files         3162     3163       +1     
  Lines       110705   110719      +14     
  Branches     19923    19891      -32     
===========================================
+ Hits         77892    77945      +53     
+ Misses       30788    30746      -42     
- Partials      2025     2028       +3     
Flag Coverage Δ
e2e 60.38% <ø> (-0.03%) ⬇️
e2e-api 47.80% <45.45%> (+0.06%) ⬆️
unit 71.40% <100.00%> (+0.05%) ⬆️

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", "02/10 19:07 (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-02-10 19:07:48 UTC
  • Historical data points: 30

Updated: Tue, 10 Feb 2026 19:07:48 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.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 26, 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.

nazabucciarelli and others added 2 commits January 26, 2026 16:34
@nazabucciarelli nazabucciarelli requested a review from a team as a code owner January 26, 2026 22:53
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

🤖 Fix all issues with AI agents
In `@apps/meteor/server/hooks/sauMonitorHooks.ts`:
- Line 22: Replace the private Meteor call Accounts._hashLoginToken with the
public hashLoginToken from `@rocket.chat/account-utils`: import { hashLoginToken }
and change the expression that computes loginToken (currently using
Accounts._hashLoginToken(resume)) to use hashLoginToken(resume) (preserving the
ternary behavior with resume). Update any existing imports to add hashLoginToken
and remove reliance on Accounts._hashLoginToken so the code computes loginToken
via the public API.
- Line 38: Remove the duplicate device-login emission in sauMonitorHooks by
deleting the deviceManagementEvents.emit('device-login', { userId:
info.user._id, userAgent, loginToken, clientAddress }) call, and instead update
DeviceManagementService (the service that listens to accounts.login and emits
'device-login') to include the loginToken in its emitted payload so the single
emission covers the session handler in
apps/meteor/ee/server/lib/deviceManagement/session.ts; ensure the emitted object
from DeviceManagementService contains userId, userAgent, clientAddress and
loginToken to match the original payload.
🧹 Nitpick comments (1)
packages/tools/src/getHeader.ts (1)

3-3: Consider exporting HeaderLike type for consumers.

Consumers of getHeader might benefit from having access to the HeaderLike type alias for their own type annotations. This is optional since the function's parameter typing provides guidance.

♻️ Optional change
-type HeaderLike = IncomingHttpHeaders | Record<string, string | string[] | undefined>;
+export type HeaderLike = IncomingHttpHeaders | Record<string, string | string[] | undefined>;

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.

2 issues found across 5 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="packages/tools/src/getHeader.ts">

<violation number="1" location="packages/tools/src/getHeader.ts:5">
P1: `getHeader` now uses a generic return type with `as T` casts, but it does not guarantee the runtime value matches `T` (e.g., `T=string[]` still returns a string for `Headers`, and the default mode can now return `string[]` for Node headers). This is both a type-safety issue and a potential runtime regression for callers that expect a string.</violation>
</file>

<file name="apps/meteor/server/hooks/sauMonitorHooks.ts">

<violation number="1" location="apps/meteor/server/hooks/sauMonitorHooks.ts:24">
P2: `clientAddress` is a required `string`, so it may be `''` when unknown. Using `??` won’t fall back to `x-real-ip` in that case (behavior change from the previous `getClientAddress` helper which used `||`). Use `||` to preserve the fallback when `clientAddress` is an empty string.</violation>
</file>

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

@nazabucciarelli
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 27, 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/hooks/sauMonitorHooks.ts`:
- Line 38: The same 'device-login' event is emitted twice (once from
DeviceManagementService reacting to the DDPStreamer accounts.login broadcast and
once from sauMonitorHooks.ts via Accounts.onLogin), causing duplicate handling;
remove the redundant emission in sauMonitorHooks.ts (the
deviceManagementEvents.emit('device-login', ...) call) or add a guard there so
it only emits when DeviceManagementService/EE path is not active (e.g., detect
presence of the DDPStreamer/DeviceManagementService or an EE flag) to ensure a
single emission per login.
🧹 Nitpick comments (1)
packages/tools/src/getHeader.ts (1)

5-15: Type assertions may return unexpected types when T is string[].

The generic T defaults to string, but when a caller specifies T = string[], the function can still return an empty string '' (lines 7, 11) or a single string value (line 14) instead of an array. The test suite documents this as "by design" (line 40-42 in spec), so if this is intentional for simplicity, consider adding a brief JSDoc comment to clarify the contract for callers.

📝 Suggested documentation
+/**
+ * Retrieves a header value from various header-like objects.
+ * Note: When T is string[], the actual return type depends on the header value;
+ * callers should verify the type if expecting an array.
+ */
 export const getHeader = <T extends string | string[] = string>(headers: HeaderLike, key: string): T => {

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/hooks/sauMonitorHooks.ts`:
- Around line 56-58: Remove the inline implementation comment before the
sauEvents.emit call and instead document the expected event parameter types in
the events type definition file (services/sauMonitor/events.ts); update the type
declaration or add a comment in that file describing the parameters for the
'sau.socket.connected' event so the sauEvents.emit({ instanceId:
InstanceStatus.id(), connectionId: connection.id }) call remains clean and
implementation-only.
🧹 Nitpick comments (1)
packages/tools/src/getHeader.spec.ts (1)

7-8: Widen getHeader input type to avoid unsafe casts.

Line 8 relies on undefined as unknown as IncomingHttpHeaders, which bypasses type safety. Consider letting getHeader accept headers?: HeaderLike and call it with undefined directly to keep typings accurate.

♻️ Suggested updates
- export const getHeader = <T extends string | string[] = string>(headers: HeaderLike, key: string): T => {
+ export const getHeader = <T extends string | string[] = string>(headers?: HeaderLike, key: string): T => {
   if (!headers) {
     return '' as T;
   }
- expect(getHeader(undefined as unknown as IncomingHttpHeaders, 'origin')).toBe('');
+ expect(getHeader(undefined, 'origin')).toBe('');

As per coding guidelines, ensure accurate typing in tests.

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.

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/meteor/server/services/device-management/service.ts">

<violation number="1" location="apps/meteor/server/services/device-management/service.ts:14">
P2: This guard suppresses `device-login` emissions whenever `connection.loginToken` is set. DDP-streamer always sets `connection.loginToken` on login, so device login emails will no longer fire for those logins. Emit the event unconditionally (as before) unless you have a reliable resume-only signal.</violation>
</file>

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

@nazabucciarelli nazabucciarelli changed the title chore: improve the way we send DDP connection data to hooks #38268 refactor: improve the way we send DDP connection data to hooks #38268 Jan 28, 2026
Copy link
Member

@KevLehman KevLehman left a comment

Choose a reason for hiding this comment

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

great work! :)

@KevLehman KevLehman added this to the 8.2.0 milestone Jan 30, 2026
@dougfabris dougfabris changed the title refactor: improve the way we send DDP connection data to hooks #38268 refactor: improve the way we send DDP connection data to hooks Feb 4, 2026
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.

4 participants