Skip to content

Update for Hub v0.8.28+#268

Merged
brucetony merged 4 commits intodevelopfrom
hub-v0.28.0
Mar 3, 2026
Merged

Update for Hub v0.8.28+#268
brucetony merged 4 commits intodevelopfrom
hub-v0.28.0

Conversation

@brucetony
Copy link
Collaborator

@brucetony brucetony commented Mar 3, 2026

Refactor robot references to client

Summary by CodeRabbit

Release Notes

  • Configuration Changes

    • Authentication now uses client credentials model instead of robot credentials
    • Environment variable names updated: HUB_AUTH_ROBOT_ID → HUB_AUTH_CLIENT_ID and HUB_AUTH_ROBOT_SECRET_FILE → HUB_AUTH_CLIENT_SECRET_FILE
    • All deployment configurations, Docker Compose files, and Kubernetes manifests updated accordingly
  • Documentation

    • Updated README files and configuration guides to reflect client-based authentication terminology

@coderabbitai
Copy link

coderabbitai bot commented Mar 3, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cfddaf0 and 36a0cad.

📒 Files selected for processing (2)
  • README.MD
  • system-tests/environment/resources/hub/client-account-setup-template.json

📝 Walkthrough

Walkthrough

This pull request refactors terminology throughout the codebase, systematically replacing "robot" account references with "client" account references. Changes span configuration files, Kubernetes manifests, Java source code, tests, documentation, and deployment scripts.

Changes

Cohort / File(s) Summary
Documentation Updates
README.md, cert-showcase/README.md, k8s/README.md, system-tests/README.md
Updated documentation to reference client accounts instead of robot accounts; replaced secret file path references from robot-secret to client-secret; changed environment variable descriptions.
Configuration & Deployment Files
src/main/resources/application.yml, cert-showcase/docker-compose.yml, system-tests/environment/node/node-docker-compose.tpl.yml
Updated YAML configurations to use HUB_AUTH_CLIENT_ID and HUB_AUTH_CLIENT_SECRET_FILE environment variables; replaced secret references from robot-secret to client-secret.
Kubernetes Manifests
k8s/deploy-to-minikube.sh, k8s/manifests/broker-deployment.yml, k8s/manifests/hub-auth-secret.yml
Updated deployment scripts and manifests to reference client credentials; changed secret volume mounts, environment variables, and data keys from robot to client identifiers.
Spring Configuration
src/main/java/de/privateaim/node_message_broker/common/CommonSpringConfig.java, src/main/java/de/privateaim/node_message_broker/discovery/DiscoverySpringConfig.java, src/main/java/de/privateaim/node_message_broker/message/MessageSpringConfig.java
Renamed bean field injections, qualifiers, and method signatures from hubAuthRobotId/selfRobotId to hubAuthClientId/selfClientId; updated property bindings from app.hub.auth.robotId to app.hub.auth.clientId.
Hub Client & API Models
src/main/java/de/privateaim/node_message_broker/common/hub/HttpHubClient.java, src/main/java/de/privateaim/node_message_broker/common/hub/HubClient.java, src/main/java/de/privateaim/node_message_broker/common/hub/api/Node.java, src/main/java/de/privateaim/node_message_broker/common/hub/auth/HubOIDCAuthenticator.java
Renamed method parameter robotId to clientId in hub client interface; changed Node public field from robotId to clientId with JSON mapping update; updated OAuth2 grant type from robot_credentials to client_credentials.
Discovery Service
src/main/java/de/privateaim/node_message_broker/discovery/DiscoveryService.java, src/main/java/de/privateaim/node_message_broker/discovery/Participant.java
Renamed field selfRobotId to selfClientId; updated qualifier from DISCOVERY_SELF_ROBOT_ID to DISCOVERY_SELF_CLIENT_ID; changed discovery logic to filter by clientId instead of robotId; updated Participant record field.
Message Service & Recipients
src/main/java/de/privateaim/node_message_broker/message/MessageService.java, src/main/java/de/privateaim/node_message_broker/message/api/hub/HubMessageRecipient.java, src/main/java/de/privateaim/node_message_broker/message/api/hub/HubMessageSender.java, src/main/java/de/privateaim/node_message_broker/message/emit/EmitMessageRecipient.java
Renamed internal field selfRobotId to selfClientId in MessageService; updated public record fields from nodeRobotId to nodeClientId in HubMessageRecipient, HubMessageSender, and EmitMessageRecipient; updated related mappings and recipient construction.
Message Encryption & Decryption
src/main/java/de/privateaim/node_message_broker/message/emit/HubMessageEmitter.java, src/main/java/de/privateaim/node_message_broker/message/emit/HubMessageEncryptionMiddleware.java, src/main/java/de/privateaim/node_message_broker/message/receive/HubMessageDecryptionMiddleware.java, src/main/java/de/privateaim/node_message_broker/message/receive/HubMessageReceiver.java
Updated recipient and sender key lookups from nodeRobotId() to nodeClientId(); changed recipient type from robot to client in message construction; updated internal mapping for message routing.
Receive Message Models
src/main/java/de/privateaim/node_message_broker/message/receive/ReceiveMessageSender.java
Renamed public record field from nodeRobotId to nodeClientId with corresponding Javadoc update.
Discovery Tests
src/test/java/de/privateaim/node_message_broker/discovery/DiscoveryControllerIT.java, src/test/java/de/privateaim/node_message_broker/discovery/DiscoveryServiceIT.java, src/test/java/de/privateaim/node_message_broker/discovery/DiscoveryServiceTest.java
Updated test constants, data setup, and assertions to use client identifiers; changed instantiation parameters from robot to client IDs.
Hub Client Tests
src/test/java/de/privateaim/node_message_broker/common/hub/HttpHubClientIT.java
Updated test constant from ROBOT_ID to CLIENT_ID; modified Node construction and query parameter assertions to use client identifier.
Message Service Tests
src/test/java/de/privateaim/node_message_broker/message/MessageServiceIT.java, src/test/java/de/privateaim/node_message_broker/message/MessageServiceTest.java
Updated test setup and data to use SELF_CLIENT_ID instead of SELF_ROBOT_ID; changed Node construction to use clientId fields.
Message Emitter Tests
src/test/java/de/privateaim/node_message_broker/message/emit/HubMessageEmitterTest.java, src/test/java/de/privateaim/node_message_broker/message/emit/HubMessageEncryptionMiddlewareTest.java
Updated expected recipient types from robot to client; changed test constants and assertions to use nodeClientId().
Message Receiver Tests
src/test/java/de/privateaim/node_message_broker/message/receive/HubMessageDecryptionMiddlewareTest.java, src/test/java/de/privateaim/node_message_broker/message/receive/HubMessageReceiverTest.java
Updated test constants from SENDER_ROBOT_ID to SENDER_CLIENT_ID; changed sender construction and assertions to use client identifiers.
System Test Setup Scripts
system-tests/environment/resources/hub/setup-hub-resources.sh, system-tests/environment/resources/secrets/setup-secrets.sh, system-tests/environment/setup.sh
Renamed account setup from robots to clients; updated API endpoints from /robots to /clients; changed template references and variable names from ROBOT_* to CLIENT_*; renamed secret generation function from create_robot_secret to create_client_secret.
System Test Templates
system-tests/environment/resources/hub/node-setup-template.json, system-tests/environment/resources/hub/robot-account-setup-template.json, system-tests/environment/resources/hub/client-account-setup-template.json
Updated JSON template field from robot_id to client_id; replaced <ROBOT_SECRET> and <ROBOT_NAME> placeholders with <CLIENT_SECRET> and <CLIENT_NAME>; added new client-account-setup-template.json.

Poem

🐰 From robots to clients, the names now align,
Credentials dance through the code, by design,
OAuth flows updated, secrets renamed with care,
Configuration echoes the change everywhere! ✨

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Update for Hub v0.8.28+' accurately reflects the main objective of updating the codebase for a new Hub version, with systematic refactoring of robot references to client throughout all files.

✏️ 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 hub-v0.28.0

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

❤️ Share

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

Copy link

@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: 6

🧹 Nitpick comments (4)
cert-showcase/docker-compose.yml (1)

65-67: Parameterize HUB_AUTH_CLIENT_ID for safer environment reuse.

This is probably not a secret, but hardcoding environment-specific IDs in tracked compose files makes reuse/rotation harder.

♻️ Suggested change
-      HUB_AUTH_CLIENT_ID: "ce84b6a8-df3d-451b-8411-4fb57570c47a"
+      HUB_AUTH_CLIENT_ID: "${HUB_AUTH_CLIENT_ID:?set HUB_AUTH_CLIENT_ID}"
       HUB_AUTH_CLIENT_SECRET_FILE: /run/secrets/client-secret-node.txt
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cert-showcase/docker-compose.yml` around lines 65 - 67, Replace the hardcoded
HUB_AUTH_CLIENT_ID value with a parameterized reference (e.g., use an
environment variable interpolation like ${HUB_AUTH_CLIENT_ID}) and ensure the
compose runtime reads it from a .env or an external secret management mechanism;
update the docker-compose service definition that currently sets
HUB_AUTH_CLIENT_ID to the literal "ce84b6a8-df3d-451b-8411-4fb57570c47a" so it
instead references the external variable, and add a note to repository docs or
example .env showing the expected variable name and how to provide it (or switch
to a docker secret if preferred) so deployments can rotate/change the ID without
editing tracked files.
src/main/java/de/privateaim/node_message_broker/common/CommonSpringConfig.java (2)

197-204: Parameter name hubAuthRobotSecret should be hubAuthClientSecret for consistency.

The qualifier correctly references HUB_AUTH_CLIENT_SECRET, but the parameter name still uses "Robot" terminology.

♻️ Proposed fix
     `@Qualifier`("HUB_AUTHENTICATOR")
     `@Bean`
     OIDCAuthenticator hubAuthenticator(
             `@Qualifier`("HUB_AUTH_WEB_CLIENT") WebClient webClient,
             `@Qualifier`("HUB_EXCHANGE_RETRY_CONFIG") HttpRetryConfig retryConfig,
             `@Qualifier`("HUB_AUTH_CLIENT_ID") String hubAuthClientId,
-            `@Qualifier`("HUB_AUTH_CLIENT_SECRET") String hubAuthRobotSecret,
+            `@Qualifier`("HUB_AUTH_CLIENT_SECRET") String hubAuthClientSecret,
             `@Qualifier`("HUB_JSON_MAPPER") ObjectMapper jsonMapper
     ) {
         return HubOIDCAuthenticator.builder()
                 .usingWebClient(webClient)
                 .withRetryConfig(retryConfig)
-                .withAuthCredentials(hubAuthClientId, hubAuthRobotSecret)
+                .withAuthCredentials(hubAuthClientId, hubAuthClientSecret)
                 .withJsonDecoder(jsonMapper)
                 .build();
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/de/privateaim/node_message_broker/common/CommonSpringConfig.java`
around lines 197 - 204, Rename the method parameter currently declared as
hubAuthRobotSecret to hubAuthClientSecret to match the
`@Qualifier`("HUB_AUTH_CLIENT_SECRET") and maintain consistent naming; update all
references in the CommonSpringConfig method signature and its usage (the builder
call that passes this value to HubOIDCAuthenticator.withAuthCredentials) so the
new parameter name is used everywhere.

65-69: Inconsistent method name: hubAuthRobotSecret() should be hubAuthClientSecret().

The bean qualifier was updated to HUB_AUTH_CLIENT_SECRET, but the method name still references "Robot". For consistency with the refactoring, consider renaming the method.

♻️ Proposed fix
     `@Qualifier`("HUB_AUTH_CLIENT_SECRET")
     `@Bean`
-    public String hubAuthRobotSecret() throws IOException {
+    public String hubAuthClientSecret() throws IOException {
         return new String(ConfigurationUtil.readExternalFileContent(hubAuthClientSecretFile));
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/de/privateaim/node_message_broker/common/CommonSpringConfig.java`
around lines 65 - 69, Rename the bean factory method hubAuthRobotSecret() in
CommonSpringConfig to hubAuthClientSecret() so its name matches the
`@Qualifier`("HUB_AUTH_CLIENT_SECRET") and the intended refactor; update all
internal references/usages to the new method name and keep the signature (throws
IOException) and implementation (return new
String(ConfigurationUtil.readExternalFileContent(hubAuthClientSecretFile)))
unchanged to preserve the bean behavior.
src/main/java/de/privateaim/node_message_broker/message/MessageService.java (1)

121-122: Align error log wording with clientId terminology.

Line 121 still says “to node” while the logged identifier is a client id.

Suggested tweak
-                                .doOnError(err -> log.error("emitting message `{}` to node `{}` failed",
+                                .doOnError(err -> log.error("emitting message `{}` to client `{}` failed",
                                         msg.context().messageId(), msg.recipient().nodeClientId(), err))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/de/privateaim/node_message_broker/message/MessageService.java`
around lines 121 - 122, Update the log message in MessageService where the
reactive chain uses .doOnError(...) to emit failures: change the wording from
"emitting message `{}` to node `{}` failed" to use the clientId terminology,
e.g. "emitting message `{}` to client `{}` failed", while keeping the same
parameters msg.context().messageId() and msg.recipient().nodeClientId() so the
logged identifier aligns with clientId naming.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@README.MD`:
- Around line 34-35: Update the description for the environment variable
HUB_AUTH_CLIENT_ID in the README: replace the current text "Robot ID associated
with the node." with "Client ID associated with the node." so the variable name
and description are consistent; ensure you change only the description text for
HUB_AUTH_CLIENT_ID and keep the surrounding table formatting intact.

In
`@src/main/java/de/privateaim/node_message_broker/discovery/DiscoveryService.java`:
- Around line 80-82: The filter that builds selfParticipants in DiscoveryService
is not null-safe and can NPE when a Participant has a null clientId; update the
predicate used in participants.stream().filter(...) (the selfParticipants
construction) to a null-safe check such as using Objects.equals(selfClientId,
p.clientId()) or checking p.clientId() != null &&
p.clientId().equals(selfClientId) so comparisons never call equals on a null
value.

In `@src/main/java/de/privateaim/node_message_broker/message/MessageService.java`:
- Around line 129-132: The stream in MessageService that builds
AnalysisParticipant objects and filters by selfClientId assumes
participant.clientId is non-null; update the pipeline to defensively exclude
participants with null or blank clientId before comparing to selfClientId (i.e.,
filter out entries where AnalysisParticipant.clientId is null or empty/blank),
so the comparison participant.clientId.equals(selfClientId) cannot NPE and
invalid recipients are prevented; modify the lambda around new
AnalysisParticipant(...) and the subsequent .filter(...) to perform the
null/blank check (or normalize clientId) prior to equality comparison and
collecting.

In `@system-tests/environment/hub/hub-docker-compose.yml`:
- Line 84: The environment variable CLIENT_ADMIN_ENABLED is invalid for Authup;
replace it with the correct variable (either ROBOT_ADMIN_ENABLED to restore the
previous robot-based admin behavior or USER_ADMIN_ENABLED for user-based admin
accounts). Locate the docker-compose service env block that sets
CLIENT_ADMIN_ENABLED and change that key to the chosen valid symbol
(ROBOT_ADMIN_ENABLED or USER_ADMIN_ENABLED) while preserving the boolean value
and formatting.

In `@system-tests/environment/resources/hub/robot-account-setup-template.json`:
- Around line 1-6: Rename the JSON template file from
robot-account-setup-template.json to client-account-setup-template.json so the
setup script setup-hub-resources.sh (which expects
client-account-setup-template.json at line 34) can find it; ensure the file
content remains unchanged (it already uses <CLIENT_SECRET> and <CLIENT_NAME>)
and update any other references if present to the new filename to keep naming
consistent with the script.

In `@system-tests/environment/setup.sh`:
- Around line 48-52: The current pipeline writes the processed template into
"$BASE_DIR"/node/node-docker-compose.yml but ends the line with a redirection
followed by a pipe to the docker compose command, breaking the pipe and hiding
write errors; update the sequence so the sed pipeline writes the file first and
only then runs docker compose (use a conditional operator like &&) so that the
sed commands targeting node-docker-compose.tpl.yml and producing
node-docker-compose.yml must succeed before invoking docker compose -f
"$BASE_DIR"/node/node-docker-compose.yml up --build -d.

---

Nitpick comments:
In `@cert-showcase/docker-compose.yml`:
- Around line 65-67: Replace the hardcoded HUB_AUTH_CLIENT_ID value with a
parameterized reference (e.g., use an environment variable interpolation like
${HUB_AUTH_CLIENT_ID}) and ensure the compose runtime reads it from a .env or an
external secret management mechanism; update the docker-compose service
definition that currently sets HUB_AUTH_CLIENT_ID to the literal
"ce84b6a8-df3d-451b-8411-4fb57570c47a" so it instead references the external
variable, and add a note to repository docs or example .env showing the expected
variable name and how to provide it (or switch to a docker secret if preferred)
so deployments can rotate/change the ID without editing tracked files.

In
`@src/main/java/de/privateaim/node_message_broker/common/CommonSpringConfig.java`:
- Around line 197-204: Rename the method parameter currently declared as
hubAuthRobotSecret to hubAuthClientSecret to match the
`@Qualifier`("HUB_AUTH_CLIENT_SECRET") and maintain consistent naming; update all
references in the CommonSpringConfig method signature and its usage (the builder
call that passes this value to HubOIDCAuthenticator.withAuthCredentials) so the
new parameter name is used everywhere.
- Around line 65-69: Rename the bean factory method hubAuthRobotSecret() in
CommonSpringConfig to hubAuthClientSecret() so its name matches the
`@Qualifier`("HUB_AUTH_CLIENT_SECRET") and the intended refactor; update all
internal references/usages to the new method name and keep the signature (throws
IOException) and implementation (return new
String(ConfigurationUtil.readExternalFileContent(hubAuthClientSecretFile)))
unchanged to preserve the bean behavior.

In `@src/main/java/de/privateaim/node_message_broker/message/MessageService.java`:
- Around line 121-122: Update the log message in MessageService where the
reactive chain uses .doOnError(...) to emit failures: change the wording from
"emitting message `{}` to node `{}` failed" to use the clientId terminology,
e.g. "emitting message `{}` to client `{}` failed", while keeping the same
parameters msg.context().messageId() and msg.recipient().nodeClientId() so the
logged identifier aligns with clientId naming.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 86f159d and cfddaf0.

📒 Files selected for processing (44)
  • README.MD
  • cert-showcase/README.md
  • cert-showcase/docker-compose.yml
  • k8s/README.md
  • k8s/deploy-to-minikube.sh
  • k8s/manifests/broker-deployment.yml
  • k8s/manifests/hub-auth-secret.yml
  • src/main/java/de/privateaim/node_message_broker/common/CommonSpringConfig.java
  • src/main/java/de/privateaim/node_message_broker/common/hub/HttpHubClient.java
  • src/main/java/de/privateaim/node_message_broker/common/hub/HubClient.java
  • src/main/java/de/privateaim/node_message_broker/common/hub/api/Node.java
  • src/main/java/de/privateaim/node_message_broker/common/hub/auth/HubOIDCAuthenticator.java
  • src/main/java/de/privateaim/node_message_broker/discovery/DiscoveryService.java
  • src/main/java/de/privateaim/node_message_broker/discovery/DiscoverySpringConfig.java
  • src/main/java/de/privateaim/node_message_broker/discovery/Participant.java
  • src/main/java/de/privateaim/node_message_broker/message/MessageService.java
  • src/main/java/de/privateaim/node_message_broker/message/MessageSpringConfig.java
  • src/main/java/de/privateaim/node_message_broker/message/api/hub/HubMessageRecipient.java
  • src/main/java/de/privateaim/node_message_broker/message/api/hub/HubMessageSender.java
  • src/main/java/de/privateaim/node_message_broker/message/emit/EmitMessageRecipient.java
  • src/main/java/de/privateaim/node_message_broker/message/emit/HubMessageEmitter.java
  • src/main/java/de/privateaim/node_message_broker/message/emit/HubMessageEncryptionMiddleware.java
  • src/main/java/de/privateaim/node_message_broker/message/receive/HubMessageDecryptionMiddleware.java
  • src/main/java/de/privateaim/node_message_broker/message/receive/HubMessageReceiver.java
  • src/main/java/de/privateaim/node_message_broker/message/receive/ReceiveMessageSender.java
  • src/main/resources/application.yml
  • src/test/java/de/privateaim/node_message_broker/common/hub/HttpHubClientIT.java
  • src/test/java/de/privateaim/node_message_broker/discovery/DiscoveryControllerIT.java
  • src/test/java/de/privateaim/node_message_broker/discovery/DiscoveryServiceIT.java
  • src/test/java/de/privateaim/node_message_broker/discovery/DiscoveryServiceTest.java
  • src/test/java/de/privateaim/node_message_broker/message/MessageServiceIT.java
  • src/test/java/de/privateaim/node_message_broker/message/MessageServiceTest.java
  • src/test/java/de/privateaim/node_message_broker/message/emit/HubMessageEmitterTest.java
  • src/test/java/de/privateaim/node_message_broker/message/emit/HubMessageEncryptionMiddlewareTest.java
  • src/test/java/de/privateaim/node_message_broker/message/receive/HubMessageDecryptionMiddlewareTest.java
  • src/test/java/de/privateaim/node_message_broker/message/receive/HubMessageReceiverTest.java
  • system-tests/README.md
  • system-tests/environment/hub/hub-docker-compose.yml
  • system-tests/environment/node/node-docker-compose.tpl.yml
  • system-tests/environment/resources/hub/node-setup-template.json
  • system-tests/environment/resources/hub/robot-account-setup-template.json
  • system-tests/environment/resources/hub/setup-hub-resources.sh
  • system-tests/environment/resources/secrets/setup-secrets.sh
  • system-tests/environment/setup.sh

Comment on lines 80 to 82
var selfParticipants = participants.stream()
.filter(p -> p.robotId().equals(selfRobotId))
.filter(p -> p.clientId().equals(selfClientId))
.toList();
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Make self-discovery filter null-safe.

On Line 81, p.clientId().equals(selfClientId) can throw if hub data contains a participant with a null clientId. This turns discovery into an unexpected 500 path.

Suggested fix
-                    var selfParticipants = participants.stream()
-                            .filter(p -> p.clientId().equals(selfClientId))
-                            .toList();
+                    var selfParticipants = participants.stream()
+                            .filter(p -> p.clientId() != null)
+                            .filter(p -> selfClientId.equals(p.clientId()))
+                            .toList();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
var selfParticipants = participants.stream()
.filter(p -> p.robotId().equals(selfRobotId))
.filter(p -> p.clientId().equals(selfClientId))
.toList();
var selfParticipants = participants.stream()
.filter(p -> p.clientId() != null)
.filter(p -> selfClientId.equals(p.clientId()))
.toList();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/de/privateaim/node_message_broker/discovery/DiscoveryService.java`
around lines 80 - 82, The filter that builds selfParticipants in
DiscoveryService is not null-safe and can NPE when a Participant has a null
clientId; update the predicate used in participants.stream().filter(...) (the
selfParticipants construction) to a null-safe check such as using
Objects.equals(selfClientId, p.clientId()) or checking p.clientId() != null &&
p.clientId().equals(selfClientId) so comparisons never call equals on a null
value.

Comment on lines 129 to 132
.map(nodes -> nodes.stream()
.map(n -> new AnalysisParticipant(n.node.id, n.node.robotId))
.filter(participant -> !participant.robotId.equals(selfRobotId))
.map(n -> new AnalysisParticipant(n.node.id, n.node.clientId))
.filter(participant -> !participant.clientId.equals(selfClientId))
.collect(Collectors.toSet()));
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Defensively handle missing clientId from hub participant data.

On Line 131, dereferencing participant.clientId assumes hub data is always complete. A null/blank clientId can cause runtime failure or invalid emit recipients.

Suggested fix
         return hubClient.fetchAnalysisNodes(analysisId)
                 .map(nodes -> nodes.stream()
                         .map(n -> new AnalysisParticipant(n.node.id, n.node.clientId))
-                        .filter(participant -> !participant.clientId.equals(selfClientId))
+                        .filter(participant -> participant.clientId() != null && !participant.clientId().isBlank())
+                        .filter(participant -> !selfClientId.equals(participant.clientId()))
                         .collect(Collectors.toSet()));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/de/privateaim/node_message_broker/message/MessageService.java`
around lines 129 - 132, The stream in MessageService that builds
AnalysisParticipant objects and filters by selfClientId assumes
participant.clientId is non-null; update the pipeline to defensively exclude
participants with null or blank clientId before comparing to selfClientId (i.e.,
filter out entries where AnalysisParticipant.clientId is null or empty/blank),
so the comparison participant.clientId.equals(selfClientId) cannot NPE and
invalid recipients are prevented; modify the lambda around new
AnalysisParticipant(...) and the subsequent .filter(...) to perform the
null/blank check (or normalize clientId) prior to equality comparison and
collecting.

@brucetony brucetony merged commit 774b5a3 into develop Mar 3, 2026
4 of 5 checks passed
@brucetony brucetony deleted the hub-v0.28.0 branch March 3, 2026 11:48
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.

1 participant