Cleanup/nats internal events #2642

Merged
mfreeman451 merged 2 commits from refs/pull/2642/head into testing 2026-01-10 02:36:15 +00:00
mfreeman451 commented 2026-01-10 01:52:08 +00:00 (Migrated from github.com)
Owner

Imported from GitHub pull request.

Original GitHub pull request: #2238
Original author: @mfreeman451
Original URL: https://github.com/carverauto/serviceradar/pull/2238
Original created: 2026-01-10T01:52:08Z
Original updated: 2026-01-10T02:36:17Z
Original head: carverauto/serviceradar:cleanup/nats-internal-events
Original base: testing
Original merged: 2026-01-10T02:36:15Z by @mfreeman451

User description

IMPORTANT: Please sign the Developer Certificate of Origin

Thank you for your contribution to ServiceRadar. Please note, when contributing, the developer must include
a DCO sign-off statement indicating the DCO acceptance in one commit message. Here
is an example DCO Signed-off-by line in a commit message:

Signed-off-by: J. Doe <j.doe@domain.com>

Describe your changes

Code checklist before requesting a review

  • I have signed the DCO?
  • The build completes without errors?
  • All tests are passing when running make test?

PR Type

Enhancement, Documentation


Description

  • Major architectural refactoring: Migrated from poller-based to gateway-based architecture across the entire codebase

  • Protobuf definitions updated: Renamed PollerId to GatewayId, replaced PollerStatusRequest/Response with GatewayStatusRequest/Response, and added new agent-gateway communication messages

  • Push-first sync service: Refactored pkg/sync/service.go to implement push-based gateway architecture with multi-tenant support, replacing pull-based KV and gRPC clients

  • Gateway monitoring implementation: Added comprehensive gateway health checks, offline/recovery detection, and NATS event publishing in pkg/core/gateways.go

  • NATS bootstrap CLI: Implemented new CLI command for NATS operator, system account, and platform account generation with multi-tenant routing support

  • Multi-tenant support: Added TenantId and TenantSlug fields throughout gateway-related messages and services

  • Extensive cleanup: Removed deprecated poller infrastructure including pkg/poller/ package, poller-specific Docker/Helm configurations, and related build scripts

  • Configuration updates: Added production and development Elixir configurations for agent gateway

  • API documentation: Updated terminology from "service pollers" to "service gateways"


Diagram Walkthrough

flowchart LR
  A["Poller Architecture<br/>Pull-based KV/gRPC"] -->|"Refactor"| B["Gateway Architecture<br/>Push-based"]
  B --> C["Agent-Gateway<br/>Communication"]
  B --> D["Multi-tenant<br/>Support"]
  B --> E["NATS Bootstrap<br/>CLI"]
  C --> F["Gateway Status<br/>Management"]
  D --> G["Per-tenant<br/>Configs"]
  E --> H["Account<br/>Generation"]

File Walkthrough

Relevant files
Enhancement
5 files
monitoring.pb.go
Refactor protobuf definitions from poller to gateway architecture

proto/monitoring.pb.go

  • Renamed PollerId field to GatewayId across multiple message types
    (StatusRequest, ResultsRequest, StatusResponse, ResultsResponse)
  • Removed deprecated PollerStatusRequest, PollerStatusResponse, and
    ServiceStatus message types
  • Replaced PollerStatusChunk with new GatewayStatusRequest,
    GatewayStatusResponse, GatewayStatusChunk, and GatewayServiceStatus
    types
  • Added new agent-gateway communication messages: AgentHelloRequest,
    AgentHelloResponse, AgentConfigRequest, AgentConfigResponse,
    AgentCheckConfig
  • Updated service definitions from PollerService to AgentGatewayService
    with new RPC methods
  • Added multi-tenant support fields (TenantId, TenantSlug) to
    gateway-related messages
+1039/-404
nats_bootstrap.go
Add NATS bootstrap CLI command implementation                       

pkg/cli/nats_bootstrap.go

  • New file implementing NATS bootstrap functionality for the CLI
  • Provides handlers for nats-bootstrap and admin nats subcommands
  • Supports both remote bootstrap via Core API and local bootstrap modes
  • Implements NATS operator, system account, and platform account
    generation
  • Includes configuration file generation, verification, and credential
    management
  • Supports multi-tenant routing with tenant ID and slug fields
+961/-0 
service.go
Migrate sync service to push-first gateway architecture with
multi-tenant support

pkg/sync/service.go

  • Removed KV client and gRPC client dependencies; replaced with gateway
    client for push-first architecture
  • Added multi-tenant support with per-tenant source configs,
    integrations, and results tracking
  • Implemented gateway enrollment, config polling, and heartbeat loops
    for dynamic configuration
  • Refactored discovery to support per-source scheduling with
    interval-based filtering
  • Added chunked results streaming to gateway with configurable chunk
    sizes
  • Deprecated pull-based GetResults and StreamResults methods in favor of
    push-based gateway integration
+1290/-317
gateways.go
Gateway monitoring and status management implementation   

pkg/core/gateways.go

  • New comprehensive gateway monitoring and status management
    implementation with 1549 lines of core functionality
  • Implements gateway health checks, offline/recovery detection, and
    event publishing to NATS
  • Handles streaming status reports with chunk reassembly and service
    message processing
  • Provides device registration for gateways, agents, and checkers with
    auto-registration capabilities
+1549/-0
edge_onboarding.go
Poller to gateway terminology refactoring and sync support

pkg/core/edge_onboarding.go

  • Comprehensive refactoring renaming all poller references to gateway
    throughout the file
  • Updates type names, function names, variable names, and comments to
    reflect gateway terminology
  • Adds support for EdgeOnboardingComponentTypeSync component type in
    package creation and validation
  • Updates KV store paths from config/pollers/ to config/gateways/ and
    related configuration handling
+208/-206
Documentation
1 files
main.go
Update API documentation terminology                                         

cmd/core/main.go

  • Updated API description from "service pollers" to "service gateways"
+1/-1     
Configuration changes
2 files
prod.exs
Add production configuration for Elixir agent gateway       

elixir/serviceradar_agent_gateway/config/prod.exs

  • New file with production-specific Elixir configuration
  • Sets logger level to info for production environment
+4/-0     
dev.exs
Add Elixir development configuration                                         

elixir/serviceradar_agent_gateway/config/dev.exs

  • New development configuration file for Elixir agent gateway
  • Sets logger level to debug for development environment
+4/-0     
Dependencies
2 files
nats_account.pb.go
Add NATS account management protobuf definitions                 

proto/nats_account.pb.go

  • Generated protobuf code for NATS account management service
  • Defines message types for account limits, subject mappings, and user
    credentials
  • Includes RPC service definitions for operator bootstrap, tenant
    account creation, and user credential generation
  • Supports account JWT signing and pushing to NATS resolver
+1266/-0
nats_account_grpc.pb.go
NATS account service gRPC definitions                                       

proto/nats_account_grpc.pb.go

  • Auto-generated gRPC service definitions for NATSAccountService with 6
    RPC methods
  • Implements NATS JWT signing operations including operator bootstrap,
    account creation, and credential generation
  • Provides both client and server interfaces with proper error handling
    and method descriptors
+376/-0 
Formatting
1 files
ubnt_poller_test.go
Test parameter terminology update                                               

pkg/mapper/ubnt_poller_test.go

  • Updates test parameter from PollerID: "poller1" to GatewayID:
    "gateway1" for consistency
+1/-1     
Additional files
101 files
.bazelignore +4/-0     
.bazelrc +5/-0     
.env-sample +33/-0   
.env.example +38/-0   
main.yml +18/-0   
AGENTS.md +177/-11
INSTALL.md +11/-11 
MODULE.bazel +5/-0     
Makefile +55/-14 
README-Docker.md +17/-2   
README.md +3/-3     
ROADMAP.md +1/-1     
BUILD.bazel +11/-6   
BUILD.bazel +12/-0   
mix_release.bzl +124/-49
BUILD.bazel +1/-0     
README.md +4/-4     
config.json +5/-6     
main.go +174/-74
build.rs +0/-1     
monitoring.proto +3/-26   
server.rs +2/-0     
main.go +1/-1     
README.md +2/-2     
monitoring.proto +2/-26   
server.rs +6/-6     
main.go +16/-2   
config.rs +26/-0   
grpc_server.rs +2/-2     
message_processor.rs +1/-0     
nats.rs +4/-0     
zen-consumer-with-otel.json +1/-0     
zen-consumer.json +1/-0     
app.go +1/-1     
config.json +4/-4     
config.json +4/-4     
BUILD.bazel +1/-0     
main.go +68/-0   
README.md +3/-3     
README.md +9/-12   
flowgger.toml +1/-0     
nats_output.rs +14/-0   
otel.toml +1/-0     
config.rs +13/-0   
nats_output.rs +7/-0     
setup.rs +1/-0     
BUILD.bazel +0/-25   
config.json +0/-111 
main.go +0/-138 
BUILD.bazel +0/-25   
config.json +0/-77   
main.go +0/-123 
main.go +1/-1     
config.rs +21/-0   
main.rs +23/-3   
docker-compose.elx.yml +117/-0 
docker-compose.spiffe.yml +8/-158 
docker-compose.yml +326/-269
Dockerfile.agent-gateway +94/-0   
Dockerfile.core-elx +108/-0 
Dockerfile.poller +0/-70   
Dockerfile.sync +0/-95   
Dockerfile.tools +1/-2     
Dockerfile.web-ng +6/-0     
agent-minimal.docker.json +6/-6     
agent.docker.json +5/-20   
agent.mtls.json +7/-10   
bootstrap-nested-spire.sh +0/-80   
.gitkeep +1/-0     
datasvc.docker.json +3/-2     
datasvc.mtls.json +14/-1   
db-event-writer.docker.json +2/-2     
db-event-writer.mtls.json +3/-2     
FRICTION_POINTS.md +0/-355 
README.md +0/-207 
SETUP_GUIDE.md +0/-307 
docker-compose.edge-e2e.yml +0/-27   
manage-packages.sh +0/-211 
setup-edge-e2e.sh +0/-198 
edge-poller-restart.sh +0/-178 
downstream-agent.conf +0/-32   
env +0/-4     
server.conf +0/-51   
upstream-agent.conf +0/-32   
entrypoint-certs.sh +13/-9   
entrypoint-poller.sh +0/-274 
entrypoint-sync.sh +0/-96   
fix-cert-permissions.sh +2/-2     
flowgger.docker.toml +2/-1     
generate-certs.sh +214/-12
nats.docker.conf +16/-160
netflow-consumer.mtls.json +1/-0     
otel.docker.toml +2/-0     
pg_hba.conf +9/-0     
pg_ident.conf +17/-0   
poller-stack.compose.yml +0/-121 
poller.docker.json +0/-128 
poller.mtls.json +0/-135 
poller.spiffe.json +0/-55   
refresh-upstream-credentials.sh +0/-248 
Additional files not shown

Imported from GitHub pull request. Original GitHub pull request: #2238 Original author: @mfreeman451 Original URL: https://github.com/carverauto/serviceradar/pull/2238 Original created: 2026-01-10T01:52:08Z Original updated: 2026-01-10T02:36:17Z Original head: carverauto/serviceradar:cleanup/nats-internal-events Original base: testing Original merged: 2026-01-10T02:36:15Z by @mfreeman451 --- ### **User description** ## IMPORTANT: Please sign the Developer Certificate of Origin Thank you for your contribution to ServiceRadar. Please note, when contributing, the developer must include a [DCO sign-off statement]( https://developercertificate.org/) indicating the DCO acceptance in one commit message. Here is an example DCO Signed-off-by line in a commit message: ``` Signed-off-by: J. Doe <j.doe@domain.com> ``` ## Describe your changes ## Issue ticket number and link ## Code checklist before requesting a review - [ ] I have signed the DCO? - [ ] The build completes without errors? - [ ] All tests are passing when running make test? ___ ### **PR Type** Enhancement, Documentation ___ ### **Description** - **Major architectural refactoring**: Migrated from poller-based to gateway-based architecture across the entire codebase - **Protobuf definitions updated**: Renamed `PollerId` to `GatewayId`, replaced `PollerStatusRequest/Response` with `GatewayStatusRequest/Response`, and added new agent-gateway communication messages - **Push-first sync service**: Refactored `pkg/sync/service.go` to implement push-based gateway architecture with multi-tenant support, replacing pull-based KV and gRPC clients - **Gateway monitoring implementation**: Added comprehensive gateway health checks, offline/recovery detection, and NATS event publishing in `pkg/core/gateways.go` - **NATS bootstrap CLI**: Implemented new CLI command for NATS operator, system account, and platform account generation with multi-tenant routing support - **Multi-tenant support**: Added `TenantId` and `TenantSlug` fields throughout gateway-related messages and services - **Extensive cleanup**: Removed deprecated poller infrastructure including `pkg/poller/` package, poller-specific Docker/Helm configurations, and related build scripts - **Configuration updates**: Added production and development Elixir configurations for agent gateway - **API documentation**: Updated terminology from "service pollers" to "service gateways" ___ ### Diagram Walkthrough ```mermaid flowchart LR A["Poller Architecture<br/>Pull-based KV/gRPC"] -->|"Refactor"| B["Gateway Architecture<br/>Push-based"] B --> C["Agent-Gateway<br/>Communication"] B --> D["Multi-tenant<br/>Support"] B --> E["NATS Bootstrap<br/>CLI"] C --> F["Gateway Status<br/>Management"] D --> G["Per-tenant<br/>Configs"] E --> H["Account<br/>Generation"] ``` <details><summary><h3>File Walkthrough</h3></summary> <table><thead><tr><th></th><th align="left">Relevant files</th></tr></thead><tbody><tr><td><strong>Enhancement</strong></td><td><details><summary>5 files</summary><table> <tr> <td> <details> <summary><strong>monitoring.pb.go</strong><dd><code>Refactor protobuf definitions from poller to gateway architecture</code></dd></summary> <hr> proto/monitoring.pb.go <ul><li>Renamed <code>PollerId</code> field to <code>GatewayId</code> across multiple message types <br>(<code>StatusRequest</code>, <code>ResultsRequest</code>, <code>StatusResponse</code>, <code>ResultsResponse</code>)<br> <li> Removed deprecated <code>PollerStatusRequest</code>, <code>PollerStatusResponse</code>, and <br><code>ServiceStatus</code> message types<br> <li> Replaced <code>PollerStatusChunk</code> with new <code>GatewayStatusRequest</code>, <br><code>GatewayStatusResponse</code>, <code>GatewayStatusChunk</code>, and <code>GatewayServiceStatus</code> <br>types<br> <li> Added new agent-gateway communication messages: <code>AgentHelloRequest</code>, <br><code>AgentHelloResponse</code>, <code>AgentConfigRequest</code>, <code>AgentConfigResponse</code>, <br><code>AgentCheckConfig</code><br> <li> Updated service definitions from <code>PollerService</code> to <code>AgentGatewayService</code> <br>with new RPC methods<br> <li> Added multi-tenant support fields (<code>TenantId</code>, <code>TenantSlug</code>) to <br>gateway-related messages</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-4f7e955b42854cc9cf3fb063b95e58a04f36271e6a0c1cb42ea6d7953dd96cc4">+1039/-404</a></td> </tr> <tr> <td> <details> <summary><strong>nats_bootstrap.go</strong><dd><code>Add NATS bootstrap CLI command implementation</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary> <hr> pkg/cli/nats_bootstrap.go <ul><li>New file implementing NATS bootstrap functionality for the CLI<br> <li> Provides handlers for <code>nats-bootstrap</code> and <code>admin nats</code> subcommands<br> <li> Supports both remote bootstrap via Core API and local bootstrap modes<br> <li> Implements NATS operator, system account, and platform account <br>generation<br> <li> Includes configuration file generation, verification, and credential <br>management<br> <li> Supports multi-tenant routing with tenant ID and slug fields</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-2176d03ba6ab4ccc1b0587a4727171546eecf6123e4df815ead583aaab062457">+961/-0</a>&nbsp; </td> </tr> <tr> <td> <details> <summary><strong>service.go</strong><dd><code>Migrate sync service to push-first gateway architecture with </code><br><code>multi-tenant support</code></dd></summary> <hr> pkg/sync/service.go <ul><li>Removed KV client and gRPC client dependencies; replaced with gateway <br>client for push-first architecture<br> <li> Added multi-tenant support with per-tenant source configs, <br>integrations, and results tracking<br> <li> Implemented gateway enrollment, config polling, and heartbeat loops <br>for dynamic configuration<br> <li> Refactored discovery to support per-source scheduling with <br>interval-based filtering<br> <li> Added chunked results streaming to gateway with configurable chunk <br>sizes<br> <li> Deprecated pull-based <code>GetResults</code> and <code>StreamResults</code> methods in favor of <br>push-based gateway integration</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-b4ea5a5b3d811fa94c6a84c71c0ddb920ce177a376d13cb776f05dd6017c4c7e">+1290/-317</a></td> </tr> <tr> <td> <details> <summary><strong>gateways.go</strong><dd><code>Gateway monitoring and status management implementation</code>&nbsp; &nbsp; </dd></summary> <hr> pkg/core/gateways.go <ul><li>New comprehensive gateway monitoring and status management <br>implementation with 1549 lines of core functionality<br> <li> Implements gateway health checks, offline/recovery detection, and <br>event publishing to NATS<br> <li> Handles streaming status reports with chunk reassembly and service <br>message processing<br> <li> Provides device registration for gateways, agents, and checkers with <br>auto-registration capabilities</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-260332914ad2238e720f4637a71b0f9f01e899102bc6b37f7827782e56b0b5c0">+1549/-0</a></td> </tr> <tr> <td> <details> <summary><strong>edge_onboarding.go</strong><dd><code>Poller to gateway terminology refactoring and sync support</code></dd></summary> <hr> pkg/core/edge_onboarding.go <ul><li>Comprehensive refactoring renaming all <code>poller</code> references to <code>gateway</code> <br>throughout the file<br> <li> Updates type names, function names, variable names, and comments to <br>reflect gateway terminology<br> <li> Adds support for <code>EdgeOnboardingComponentTypeSync</code> component type in <br>package creation and validation<br> <li> Updates KV store paths from <code>config/pollers/</code> to <code>config/gateways/</code> and <br>related configuration handling</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-85874e3c4bdcc9110db09909f10648d44cdee554b26c987f910502321eb20b5c">+208/-206</a></td> </tr> </table></details></td></tr><tr><td><strong>Documentation</strong></td><td><details><summary>1 files</summary><table> <tr> <td> <details> <summary><strong>main.go</strong><dd><code>Update API documentation terminology</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary> <hr> cmd/core/main.go <ul><li>Updated API description from "service pollers" to "service gateways"</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-4ab3fd1d4debc53dd2499d94a0f60c648fdae4235dd1e3678095a975f5bb434a">+1/-1</a>&nbsp; &nbsp; &nbsp; </td> </tr> </table></details></td></tr><tr><td><strong>Configuration changes</strong></td><td><details><summary>2 files</summary><table> <tr> <td> <details> <summary><strong>prod.exs</strong><dd><code>Add production configuration for Elixir agent gateway</code>&nbsp; &nbsp; &nbsp; &nbsp; </dd></summary> <hr> elixir/serviceradar_agent_gateway/config/prod.exs <ul><li>New file with production-specific Elixir configuration<br> <li> Sets logger level to <code>info</code> for production environment</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-5fdc859dfda96a02326392f61218325913f22f9f0c75a1276ee940d5db9fc62b">+4/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td> <details> <summary><strong>dev.exs</strong><dd><code>Add Elixir development configuration</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary> <hr> elixir/serviceradar_agent_gateway/config/dev.exs <ul><li>New development configuration file for Elixir agent gateway<br> <li> Sets logger level to debug for development environment</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-378e53cb66373073730a5d7ceba4973777eb84ae419c8a38472e3f69c3056fe9">+4/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> </table></details></td></tr><tr><td><strong>Dependencies</strong></td><td><details><summary>2 files</summary><table> <tr> <td> <details> <summary><strong>nats_account.pb.go</strong><dd><code>Add NATS account management protobuf definitions</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary> <hr> proto/nats_account.pb.go <ul><li>Generated protobuf code for NATS account management service<br> <li> Defines message types for account limits, subject mappings, and user <br>credentials<br> <li> Includes RPC service definitions for operator bootstrap, tenant <br>account creation, and user credential generation<br> <li> Supports account JWT signing and pushing to NATS resolver</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-49eb93c28e2d86d8dcf4ee78fd24bed498cf3fcfaa8e49849a36e70980420087">+1266/-0</a></td> </tr> <tr> <td> <details> <summary><strong>nats_account_grpc.pb.go</strong><dd><code>NATS account service gRPC definitions</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary> <hr> proto/nats_account_grpc.pb.go <ul><li>Auto-generated gRPC service definitions for <code>NATSAccountService</code> with 6 <br>RPC methods<br> <li> Implements NATS JWT signing operations including operator bootstrap, <br>account creation, and credential generation<br> <li> Provides both client and server interfaces with proper error handling <br>and method descriptors</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-af98ae5f073d25a2ea0a044c996542fc65d215f6a70f14a9fba0447d87b34e11">+376/-0</a>&nbsp; </td> </tr> </table></details></td></tr><tr><td><strong>Formatting</strong></td><td><details><summary>1 files</summary><table> <tr> <td> <details> <summary><strong>ubnt_poller_test.go</strong><dd><code>Test parameter terminology update</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></summary> <hr> pkg/mapper/ubnt_poller_test.go <ul><li>Updates test parameter from <code>PollerID: "poller1"</code> to <code>GatewayID: </code><br><code>"gateway1"</code> for consistency</ul> </details> </td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-3a012fc444d26a40b833529837d1c8b96198ddc6d99e33eac0c000eafc0d35e0">+1/-1</a>&nbsp; &nbsp; &nbsp; </td> </tr> </table></details></td></tr><tr><td><strong>Additional files</strong></td><td><details><summary>101 files</summary><table> <tr> <td><strong>.bazelignore</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-a5641cd37d6ad98b32cdfce1980836cc68312277bc6a7052f55da02ada5bc6cf">+4/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>.bazelrc</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-544556920c45b42cbfe40159b082ce8af6bd929e492d076769226265f215832f">+5/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>.env-sample</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-c4368a972a7fa60d9c4e333cebf68cdb9a67acb810451125c02e3b7eb2594e3d">+33/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>.env.example</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-a3046da0d15a27e89f2afe639b25748a7ad4d9290af3e7b1b6c1a5533c8f0a8c">+38/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>main.yml</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-7829468e86c1cc5d5133195b5cb48e1ff6c75e3e9203777f6b2e379d9e4882b3">+18/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>AGENTS.md</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-a54ff182c7e8acf56acfd6e4b9c3ff41e2c41a31c9b211b2deb9df75d9a478f9">+177/-11</a></td> </tr> <tr> <td><strong>INSTALL.md</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-09b140a43ebfdd8dbec31ce72cafffd15164d2860fd390692a030bcb932b54a0">+11/-11</a>&nbsp; </td> </tr> <tr> <td><strong>MODULE.bazel</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-6136fc12446089c3db7360e923203dd114b6a1466252e71667c6791c20fe6bdc">+5/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>Makefile</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-76ed074a9305c04054cdebb9e9aad2d818052b07091de1f20cad0bbac34ffb52">+55/-14</a>&nbsp; </td> </tr> <tr> <td><strong>README-Docker.md</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-9fd61d24482efe68c22d8d41e2a1dcc440f39195aa56e7a050f2abe598179efd">+17/-2</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>README.md</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5">+3/-3</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>ROADMAP.md</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-683343bdf93f55ed3cada86151abb8051282e1936e58d4e0a04beca95dff6e51">+1/-1</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>BUILD.bazel</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-884fa9353a5226345e44fbabea3300efc7a87dfbcde0b6a42521ca51823f1b68">+11/-6</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>BUILD.bazel</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-0e80ea46aeb61a873324685edb96eae864c7a2004fbb7ee404b4ec951190ba10">+12/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>mix_release.bzl</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-86ec281f99363b6b6eb1f49e21d83b7eeca93a35b552b9f305fffc6855e38ccd">+124/-49</a></td> </tr> <tr> <td><strong>BUILD.bazel</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-143f8d1549d52f28906f19ce28e5568a5be474470ff103c2c1e63c3e6b08d670">+1/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>README.md</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-bfd308915d0cf522e7fc76600dee687617dc69165ab22502a1d219850c0c0860">+4/-4</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>config.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-5b1bc8fe77422534739bdd3a38dc20d2634a86c171265c34e1b5d0c5a61b6bab">+5/-6</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>main.go</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-61358711e980ccf505246fd3915f97cbd3a380e9b66f6fa5aad46749968c5ca3">+174/-74</a></td> </tr> <tr> <td><strong>build.rs</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-251e7a923f45f8f903e510d10f183366bda06d281c8ecc3669e1858256e2186d">+0/-1</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>monitoring.proto</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-b56f709f4a0a3db694f2124353908318631f23e20b7846bc4b8ee869e2e0632a">+3/-26</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>server.rs</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-bce0f4ca6548712f224b73816825d28e831acbbff7dbed3c98671ed50f65d028">+2/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>main.go</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-f25402eade63525184cb5e7437accff93c7b9338eebe81add6dc5f2a9eb12550">+1/-1</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>README.md</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-2e9751b437fa61442aac074c7a4a912d0ac50ac3ea156ac8aedd8478d21c6bdb">+2/-2</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>monitoring.proto</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-9faf6025eb0d3d38383f5b7ad2b733abeb38454d5e4de3e83994e94b12d87a50">+2/-26</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>server.rs</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-2c4395fee16396339c3eea518ad9bec739174c67c9cedf62e6848c17136dd33e">+6/-6</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>main.go</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-ed4d81d29a7267f93fd77e17993fd3491b9ef6ded18490b4514d10ed1d803bc2">+16/-2</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>config.rs</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-05038f3867985e757de9027609950e682bad6d1992dac6acd7c28962a3c65dc4">+26/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>grpc_server.rs</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-e4564a93f6cf84ff91cd3d8141fc9272ec9b4ec19defd107afa42be01fcfed5b">+2/-2</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>message_processor.rs</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-9fcbc5358a9009e60a8cd22d21e5a9ea652787c727732d0b869e0865495114c3">+1/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>nats.rs</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-97f7335def0ad5d644b594a1076ae2d7080b11259cbb8de22c7946cc8e4b39f8">+4/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>zen-consumer-with-otel.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-68375f1f7847e1fbdf75664f6be65b1ad94ae6ce86ed73fc5964d65054668acb">+1/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>zen-consumer.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-4d308af9802a93a0f656e8c02a3b5fcd8991407bb18360f087470db74e1f9524">+1/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>app.go</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-4ad8a289575edf3b163088617b7a40ae1305c29ced0c7d59b3751c57d6938072">+1/-1</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>config.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-2423ef78d36e905ae993b69ff59f5df6b2e1b9492fb0fa8c6d0aad7c76d2d229">+4/-4</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>config.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-ef778d85ac6f9652c25cb0d631f0fe8dfb3edac4dde5d719a4fc2926fb5c3216">+4/-4</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>BUILD.bazel</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-c62c0139ebdb337369f4067567cd2c52b8e7decb3ddfabc77f9f67b2f6e5789c">+1/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>main.go</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-5e7731adfb877918cd65d9d5531621312496450fd550fea2682efca4ca8fe816">+68/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>README.md</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-0b0725713b87dca1de57200214a4fe04633f0d856c39aa8032280227bf8e8141">+3/-3</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>README.md</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-f425b4378f84e0ba0c6f532facff17ff5d55b4dc6033d8bf35130a159cd2ba32">+9/-12</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>flowgger.toml</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-af9f49f931e282dca53d1f0521b036d222fe671f77e61a876a84cf4c6d7cca4d">+1/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>nats_output.rs</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-a82e2e4d413539bf0b414b5629665b19648447523994cba639c4d1238aa5a0c1">+14/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>otel.toml</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-c64b9ace832b8ea57a2be62f84166e03bb1904882635d444ec76a880cdf14cc0">+1/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>config.rs</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-abbaec651da3d6af96b482e0f77bb909b65dbe0cabd78b5803769cc9dab0a1b0">+13/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>nats_output.rs</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-6b585ea3564a481174e04da1270e2e13edd4e2b980d02a2652d6d21e6d82a498">+7/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>setup.rs</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-3891f667deb20fd26e296d3e2742c57378d3764fe1743118e612465ae360391f">+1/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>BUILD.bazel</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-e1f7c698e0e3a4e6afa971c1140e71cbf22593fbb19c81cb26b02c15c5dc46ec">+0/-25</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>config.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-9edc2486fff55fc399e0ac96dba5137948a7ea7285f5ef7846835355684b7ab5">+0/-111</a>&nbsp; </td> </tr> <tr> <td><strong>main.go</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-4b8ec845da50cd58d011e69f9d1c30530ee1968df26616b8768bb1fc03433bbe">+0/-138</a>&nbsp; </td> </tr> <tr> <td><strong>BUILD.bazel</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-4f5d2ea4260d490a0d6f28adde0b35eca8af77d22f3ee366a783946c53687619">+0/-25</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>config.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-bcac20d6b3cb81f0059e766839ba1ee59a885009249501b0ba1182ebb1daea25">+0/-77</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>main.go</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-78dc6bc53f1c760c66f43ff5f486bfe78a65bee8b2e0d4862293ec0892da2b29">+0/-123</a>&nbsp; </td> </tr> <tr> <td><strong>main.go</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-bc6eeb1b05bcb9179525e32fac1de9926b5823ec3504be546ab10c5c9740f544">+1/-1</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>config.rs</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-c89b88ba4d2bf0a054d0ba69a672a92c30140b8d19503d67b980a218ffe3106d">+21/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>main.rs</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-33b655d8730ae3e9c844ee280787d11f1b0d5343119188273f89558805f814ba">+23/-3</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>docker-compose.elx.yml</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-9562070d7ad4a3e9b2d06567008cf35de1d96448d914b3b45bf6c36d97cdd914">+117/-0</a>&nbsp; </td> </tr> <tr> <td><strong>docker-compose.spiffe.yml</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-603fd9e7d40841d174f26b95d0cb0c9537430bf3f7a5da3ccbba4ea3d8ac66c9">+8/-158</a>&nbsp; </td> </tr> <tr> <td><strong>docker-compose.yml</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-e45e45baeda1c1e73482975a664062aa56f20c03dd9d64a827aba57775bed0d3">+326/-269</a></td> </tr> <tr> <td><strong>Dockerfile.agent-gateway</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-332bc81a932ae08efa711a71b60fe0954d99bf17ebdab00a3baaa177a44de8b0">+94/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>Dockerfile.core-elx</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-5ec7a971285669999af442a0c7f141c34f7fd9180257307f5c4ed12f789a2182">+108/-0</a>&nbsp; </td> </tr> <tr> <td><strong>Dockerfile.poller</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-d3ba129830fb366bfe23b00db4ef6218b10fc981d3c04842b1b3b3b367a8982f">+0/-70</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>Dockerfile.sync</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-0227933b9961fd553af1d229e89d71a0271fdc475081bbcef49b587941af1eda">+0/-95</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>Dockerfile.tools</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-0258db71e4070e342198965f1d046f3097640850b037df8a2287a7e239630add">+1/-2</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>Dockerfile.web-ng</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-92d43af1965575d56c3380ecc8a81024aac2ff36f039ec2d3839e9fc7852bc10">+6/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>agent-minimal.docker.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-1f09fad94636c90373af8e270f6ba0332ae4f4d1df50a4909729280a3a9691e6">+6/-6</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>agent.docker.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-5d33fe703515d03076d31261ecf946e9c6fc668cf5bf65099d49b670739e455e">+5/-20</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>agent.mtls.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-008f2216f159a9bd5db9cc90baaf6f1e64487df7af05b56ab3b9d6c4946aa95f">+7/-10</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>bootstrap-nested-spire.sh</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-ab4746a08fb1e0b307a1e47660cd22182e283a087cba87dcbff0fdfe750f44f1">+0/-80</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>.gitkeep</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-d72c41aab2d6f2c230a4340dfefe7917cdd12bed942c825aa0d4c9875a637bac">+1/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>datasvc.docker.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-3f2719d3dbfe042e8383739e3c78e74e5f851a44e5e46bea8e79c4b79fdcc34f">+3/-2</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>datasvc.mtls.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-3a45619e57f1e6e9a31486ec7fffb33ef246e271f82bac272ee0a946b88da70a">+14/-1</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>db-event-writer.docker.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-9fc51271f7ef5bb460160013e24e44e829b730656891d26fc49d5fe72fbb3147">+2/-2</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>db-event-writer.mtls.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-7a33f95f7545499abf0ed9fc91b58499ab209639e4885019579c959583fc7496">+3/-2</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>FRICTION_POINTS.md</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-b0653c58880f810ba832c0500733d63de309db98b43009fe73a1862494cf41bd">+0/-355</a>&nbsp; </td> </tr> <tr> <td><strong>README.md</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-31849f033cfc932acee35f549c069abb1f36101c352e553dd6bff8713b29f98c">+0/-207</a>&nbsp; </td> </tr> <tr> <td><strong>SETUP_GUIDE.md</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-b4914f8640a78038e45f51235a624535672680dc902de5f107fc051f4f281913">+0/-307</a>&nbsp; </td> </tr> <tr> <td><strong>docker-compose.edge-e2e.yml</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-575d19ea771bdf8102cb9729db43a1bfd6afc2527160e54105beeac2e314f362">+0/-27</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>manage-packages.sh</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-3c2ff6febbddb956c71557894adaf7d0a39a1f20dda120fe126364946bc47280">+0/-211</a>&nbsp; </td> </tr> <tr> <td><strong>setup-edge-e2e.sh</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-2714e2c7e111f69ea9e9f5ddd7f6a70fa5ea96e3a53b851cb13b8b8b7cd12917">+0/-198</a>&nbsp; </td> </tr> <tr> <td><strong>edge-poller-restart.sh</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-96a8fe52c38fd0d7c14895127df34a27be311cac89c53d28ee178661b629bd22">+0/-178</a>&nbsp; </td> </tr> <tr> <td><strong>downstream-agent.conf</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-747de0375ced42af978ca7dac239862bdabb7f6bd0bd634f134b485517a7b4ee">+0/-32</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>env</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-686f1a954c542f2ec9bf14c3170648b65190ad242c7f3a95a0f872ae41b8b1c6">+0/-4</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>server.conf</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-025f5b5ab79526cf549ca1fdb90dd659ba76b438f05a7f77d916d18728c4b572">+0/-51</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>upstream-agent.conf</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-e8a869ddf4affa31536a8d4e4e6f09c40072a7026da2c609d93c6ecf04138902">+0/-32</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>entrypoint-certs.sh</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-83d6800b184a5233c66c69766286b0a60fece1bc64addb112d9f8dc019437f05">+13/-9</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>entrypoint-poller.sh</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-e202d27e3331088745eb55cdd2b3e40ac3f5df109d9ff5c76c0faed60772807a">+0/-274</a>&nbsp; </td> </tr> <tr> <td><strong>entrypoint-sync.sh</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-9d5620b8e6833309dbafb8ee6b6b75c3b942d163c3fe7f1a9827958b2d640265">+0/-96</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>fix-cert-permissions.sh</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-17ea40a11edcaa7c85bb4215fda46b5a32505246fef0ab5f3ed47b28470c5ec8">+2/-2</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>flowgger.docker.toml</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-824f8797b418d4b9f5ea41e4a3741a0ed64b881f343072464489a76b7ea01008">+2/-1</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>generate-certs.sh</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-8298241543b4744a6ac7780c760ac5b5a0a87ba62de19c8612ebe1aba0996ebd">+214/-12</a></td> </tr> <tr> <td><strong>nats.docker.conf</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-06f2012494f428fe1bfb304972061c2094e0d99da88ba9af6914f7776872e6eb">+16/-160</a></td> </tr> <tr> <td><strong>netflow-consumer.mtls.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-f15920e8498a24f71ce3eec4f48fe8fefbb1765a90362998af779a660fcef9e1">+1/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>otel.docker.toml</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-d4af38790e3657b7589cd37a7539d5308b032f11caba7aa740ddc86bf99f4415">+2/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>pg_hba.conf</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-7bd5f7292054916c7e5997f4c84ac9ec07d4c945621a48936c2aed0575fb96eb">+9/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>pg_ident.conf</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-e7b8ce062e32c61fdc3bcc9e525c1f1df1c8008fbc02b11409e58c67baa17cc5">+17/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>poller-stack.compose.yml</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-f3b5c991c2c1f7646db0ca4ed9bcb5df0f313ce6a05d8f3c890f80c873f776f5">+0/-121</a>&nbsp; </td> </tr> <tr> <td><strong>poller.docker.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-d64ebb69ec31e831efd187c47a5bfff2573960306b177f6464e91cb44a3c709d">+0/-128</a>&nbsp; </td> </tr> <tr> <td><strong>poller.mtls.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-ef5d74bb3607431245c2bf06169d7fee89cae817e114035075b59a671229ab46">+0/-135</a>&nbsp; </td> </tr> <tr> <td><strong>poller.spiffe.json</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-4e04bd23a0216287d5c0bb3831e0f95e7922ed03e8386a10ae7f4873e4fdb538">+0/-55</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>refresh-upstream-credentials.sh</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-d3b3a8fcdea1b49c9e1c0ecc12d61fb6d416313520e8ad52edbee9094dbdc271">+0/-248</a>&nbsp; </td> </tr> <tr> <td><strong>Additional files not shown</strong></td> <td><a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-2f328e4cd8dbe3ad193e49d92bcf045f47a6b72b1e9487d366f6b8288589b4ca"></a></td> </tr> </table></details></td></tr></tbody></table> </details> ___
qodo-code-review[bot] commented 2026-01-10 01:53:39 +00:00 (Migrated from github.com)
Author
Owner

Imported GitHub PR comment.

Original author: @qodo-code-review[bot]
Original URL: https://github.com/carverauto/serviceradar/pull/2238#issuecomment-3731448946
Original created: 2026-01-10T01:53:39Z

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
Audit logs unverified: The PR description indicates new gateway health/offline detection and NATS event
publishing, but those code paths are in files not included in the provided diff so it
cannot be verified that critical actions are logged with actor identity, timestamp,
action, and outcome.

Referred Code
/*

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Error handling unverified: The PR description claims a major refactor to a push-first gateway sync service, but the
relevant implementation files are not included in the provided diff so potential failure
points and edge-case handling cannot be verified.

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status:
CLI errors unverified: The PR introduces NATS bootstrap/account generation functionality, but the new CLI code is
not present in the provided diff so it cannot be verified that user-facing errors avoid
leaking sensitive internal details or secrets.

Referred Code
/*

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Sensitive logs unverified: The PR adds multi-tenant NATS account and key management, but the implementation is not
included in the provided diff so it cannot be verified that logs are structured and do not
emit secrets (keys, tokens, credentials) or tenant-identifying data inappropriately.

Referred Code
/*

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Input validation unverified: New external-facing fields such as tenant_id, tenant_slug, gateway_id, and config_json
were added to protobuf messages, but the server-side handlers/validators consuming these
inputs are not included in the provided diff so validation, authorization, and secure
handling cannot be confirmed.

Referred Code
// GatewayStatusRequest is sent by agents to push their status to the gateway.
type GatewayStatusRequest struct {
	state         protoimpl.MessageState  `protogen:"open.v1"`
	Services      []*GatewayServiceStatus `protobuf:"bytes,1,rep,name=services,proto3" json:"services,omitempty"`
	GatewayId     string                  `protobuf:"bytes,2,opt,name=gateway_id,json=gatewayId,proto3" json:"gateway_id,omitempty"` // Gateway receiving this status
	AgentId       string                  `protobuf:"bytes,3,opt,name=agent_id,json=agentId,proto3" json:"agent_id,omitempty"`       // Agent sending this status
	Timestamp     int64                   `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
	Partition     string                  `protobuf:"bytes,5,opt,name=partition,proto3" json:"partition,omitempty"`                     // Partition identifier
	SourceIp      string                  `protobuf:"bytes,6,opt,name=source_ip,json=sourceIp,proto3" json:"source_ip,omitempty"`       // Host IP where agent is running
	KvStoreId     string                  `protobuf:"bytes,7,opt,name=kv_store_id,json=kvStoreId,proto3" json:"kv_store_id,omitempty"`  // KV store identifier this agent is using
	TenantId      string                  `protobuf:"bytes,8,opt,name=tenant_id,json=tenantId,proto3" json:"tenant_id,omitempty"`       // Tenant UUID for multi-tenant routing
	TenantSlug    string                  `protobuf:"bytes,9,opt,name=tenant_slug,json=tenantSlug,proto3" json:"tenant_slug,omitempty"` // Tenant slug for NATS subject prefixing
	unknownFields protoimpl.UnknownFields
	sizeCache     protoimpl.SizeCache
}

func (x *GatewayStatusRequest) Reset() {
	*x = GatewayStatusRequest{}
	mi := &file_monitoring_proto_msgTypes[9]
	ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
	ms.StoreMessageInfo(mi)



 ... (clipped 686 lines)

Learn more about managing compliance generic rules or creating your own custom rules

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
- Requires Further Human Verification
🏷️ - Compliance label
Imported GitHub PR comment. Original author: @qodo-code-review[bot] Original URL: https://github.com/carverauto/serviceradar/pull/2238#issuecomment-3731448946 Original created: 2026-01-10T01:53:39Z --- ## PR Compliance Guide 🔍 <!-- https://github.com/carverauto/serviceradar/commit/92d6ba6ddf765969afd273e5f2b6cc7f0b6fe1af --> Below is a summary of compliance checks for this PR:<br> <table><tbody><tr><td colspan='2'><strong>Security Compliance</strong></td></tr> <tr><td>🟢</td><td><details><summary><strong>No security concerns identified</strong></summary> No security vulnerabilities detected by AI analysis. Human verification advised for critical code. </details></td></tr> <tr><td colspan='2'><strong>Ticket Compliance</strong></td></tr> <tr><td>⚪</td><td><details><summary>🎫 <strong>No ticket provided </strong></summary> - [ ] Create ticket/issue <!-- /create_ticket --create_ticket=true --> </details></td></tr> <tr><td colspan='2'><strong>Codebase Duplication Compliance</strong></td></tr> <tr><td>⚪</td><td><details><summary><strong>Codebase context is not defined </strong></summary> Follow the <a href='https://qodo-merge-docs.qodo.ai/core-abilities/rag_context_enrichment/'>guide</a> to enable codebase context checks. </details></td></tr> <tr><td colspan='2'><strong>Custom Compliance</strong></td></tr> <tr><td rowspan=1>🟢</td><td> <details><summary><strong>Generic: Meaningful Naming and Self-Documenting Code</strong></summary><br> **Objective:** Ensure all identifiers clearly express their purpose and intent, making code <br>self-documenting<br> **Status:** Passed<br> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td rowspan=5>⚪</td> <td><details> <summary><strong>Generic: Comprehensive Audit Trails</strong></summary><br> **Objective:** To create a detailed and reliable record of critical system actions for security analysis <br>and compliance.<br> **Status:** <br><a href='https://github.com/carverauto/serviceradar/pull/2238/files#diff-260332914ad2238e720f4637a71b0f9f01e899102bc6b37f7827782e56b0b5c0R1-R1'><strong>Audit logs unverified</strong></a>: The PR description indicates new gateway health/offline detection and NATS event <br>publishing, but those code paths are in files not included in the provided diff so it <br>cannot be verified that critical actions are logged with actor identity, timestamp, <br>action, and outcome.<br> <details open><summary>Referred Code</summary> ```go /* ``` </details> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td><details> <summary><strong>Generic: Robust Error Handling and Edge Case Management</strong></summary><br> **Objective:** Ensure comprehensive error handling that provides meaningful context and graceful <br>degradation<br> **Status:** <br><a href='https://github.com/carverauto/serviceradar/pull/2238/files#diff-b4ea5a5b3d811fa94c6a84c71c0ddb920ce177a376d13cb776f05dd6017c4c7eR1-R1'><strong>Error handling unverified</strong></a>: The PR description claims a major refactor to a push-first gateway sync service, but the <br>relevant implementation files are not included in the provided diff so potential failure <br>points and edge-case handling cannot be verified.<br> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td><details> <summary><strong>Generic: Secure Error Handling</strong></summary><br> **Objective:** To prevent the leakage of sensitive system information through error messages while <br>providing sufficient detail for internal debugging.<br> **Status:** <br><a href='https://github.com/carverauto/serviceradar/pull/2238/files#diff-2176d03ba6ab4ccc1b0587a4727171546eecf6123e4df815ead583aaab062457R1-R1'><strong>CLI errors unverified</strong></a>: The PR introduces NATS bootstrap/account generation functionality, but the new CLI code is <br>not present in the provided diff so it cannot be verified that user-facing errors avoid <br>leaking sensitive internal details or secrets.<br> <details open><summary>Referred Code</summary> ```go /* ``` </details> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td><details> <summary><strong>Generic: Secure Logging Practices</strong></summary><br> **Objective:** To ensure logs are useful for debugging and auditing without exposing sensitive <br>information like PII, PHI, or cardholder data.<br> **Status:** <br><a href='https://github.com/carverauto/serviceradar/pull/2238/files#diff-3e814328b5d5bddca9cd4b0ca021a975cf416afdc059e454452580a4ce751320R1-R1'><strong>Sensitive logs unverified</strong></a>: The PR adds multi-tenant NATS account and key management, but the implementation is not <br>included in the provided diff so it cannot be verified that logs are structured and do not <br>emit secrets (keys, tokens, credentials) or tenant-identifying data inappropriately.<br> <details open><summary>Referred Code</summary> ```go /* ``` </details> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td><details> <summary><strong>Generic: Security-First Input Validation and Data Handling</strong></summary><br> **Objective:** Ensure all data inputs are validated, sanitized, and handled securely to prevent <br>vulnerabilities<br> **Status:** <br><a href='https://github.com/carverauto/serviceradar/pull/2238/files#diff-4f7e955b42854cc9cf3fb063b95e58a04f36271e6a0c1cb42ea6d7953dd96cc4R826-R1532'><strong>Input validation unverified</strong></a>: New external-facing fields such as <code>tenant_id</code>, <code>tenant_slug</code>, <code>gateway_id</code>, and <code>config_json</code> <br>were added to protobuf messages, but the server-side handlers/validators consuming these <br>inputs are not included in the provided diff so validation, authorization, and secure <br>handling cannot be confirmed.<br> <details open><summary>Referred Code</summary> ```go // GatewayStatusRequest is sent by agents to push their status to the gateway. type GatewayStatusRequest struct { state protoimpl.MessageState `protogen:"open.v1"` Services []*GatewayServiceStatus `protobuf:"bytes,1,rep,name=services,proto3" json:"services,omitempty"` GatewayId string `protobuf:"bytes,2,opt,name=gateway_id,json=gatewayId,proto3" json:"gateway_id,omitempty"` // Gateway receiving this status AgentId string `protobuf:"bytes,3,opt,name=agent_id,json=agentId,proto3" json:"agent_id,omitempty"` // Agent sending this status Timestamp int64 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` Partition string `protobuf:"bytes,5,opt,name=partition,proto3" json:"partition,omitempty"` // Partition identifier SourceIp string `protobuf:"bytes,6,opt,name=source_ip,json=sourceIp,proto3" json:"source_ip,omitempty"` // Host IP where agent is running KvStoreId string `protobuf:"bytes,7,opt,name=kv_store_id,json=kvStoreId,proto3" json:"kv_store_id,omitempty"` // KV store identifier this agent is using TenantId string `protobuf:"bytes,8,opt,name=tenant_id,json=tenantId,proto3" json:"tenant_id,omitempty"` // Tenant UUID for multi-tenant routing TenantSlug string `protobuf:"bytes,9,opt,name=tenant_slug,json=tenantSlug,proto3" json:"tenant_slug,omitempty"` // Tenant slug for NATS subject prefixing unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *GatewayStatusRequest) Reset() { *x = GatewayStatusRequest{} mi := &file_monitoring_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) ... (clipped 686 lines) ``` </details> > Learn more about managing compliance <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#configuration-options'>generic rules</a> or creating your own <a href='https://qodo-merge-docs.qodo.ai/tools/compliance/#custom-compliance'>custom rules</a> </details></td></tr> <tr><td align="center" colspan="2"> - [ ] Update <!-- /compliance --update_compliance=true --> </td></tr></tbody></table> <details><summary>Compliance status legend</summary> 🟢 - Fully Compliant<br> 🟡 - Partial Compliant<br> 🔴 - Not Compliant<br> ⚪ - Requires Further Human Verification<br> 🏷️ - Compliance label<br> </details>
qodo-code-review[bot] commented 2026-01-10 01:55:25 +00:00 (Migrated from github.com)
Author
Owner

Imported GitHub PR comment.

Original author: @qodo-code-review[bot]
Original URL: https://github.com/carverauto/serviceradar/pull/2238#issuecomment-3731457594
Original created: 2026-01-10T01:55:25Z

PR Code Suggestions

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Leverage NATS features for service monitoring

The custom gateway monitoring system in pkg/core/gateways.go should be
simplified. Instead of bespoke health checks and status management, leverage
built-in NATS features like the Key-Value Store and service heartbeats for a
more robust and maintainable solution.

Examples:

pkg/core/gateways.go [1-1549]

Solution Walkthrough:

Before:

// pkg/core/gateways.go

// Server struct with DB, cache, mutexes, etc.
type Server struct {
    DB db.DB
    gatewayStatusCache map[string]*models.GatewayStatus
    cacheMutex sync.RWMutex
    // ...
}

// Custom monitoring loop
func (s *Server) MonitorGateways(ctx context.Context) {
    ticker := time.NewTicker(monitorInterval)
    for range ticker.C {
        gatewayStatuses, _ := s.getGatewayStatuses(ctx, ...)
        for _, ps := range gatewayStatuses {
            // Manually check if last_seen is too old
            if ps.LastSeen.Before(threshold) {
                s.handleGatewayDown(ctx, ps.GatewayID, ...)
            }
        }
    }
}

// gRPC handler to receive status
func (s *Server) PushStatus(ctx context.Context, req *proto.GatewayStatusRequest) (*proto.GatewayStatusResponse, error) {
    // ...
    // Manually update status in DB and cache
    s.DB.UpdateGatewayStatus(ctx, gatewayStatus)
    // ...
}

After:

// Simplified monitoring using NATS

type NatsMonitor struct {
    NatsConn *nats.Conn
    KV       nats.KeyValue
    // ...
}

func NewNatsMonitor(nc *nats.Conn) *NatsMonitor {
    js, _ := nc.JetStream()
    kv, _ := js.KeyValue("gateway_status")
    return &NatsMonitor{NatsConn: nc, KV: kv}
}

// Monitor using NATS advisories
func (m *NatsMonitor) MonitorGateways(ctx context.Context) {
    // NATS services send heartbeats automatically.
    // Subscribe to advisories for offline events.
    m.NatsConn.Subscribe("*.

Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies that the custom-built monitoring in pkg/core/gateways.go could be greatly simplified by using built-in NATS features like KV Store and service heartbeats, reducing significant code complexity.

High
Possible issue
Prevent race condition in goroutine

To prevent a potential race condition, pass the req object as an argument to the
goroutine instead of capturing it in the closure.

pkg/core/gateways.go [624-629]

-		go func(normalizedIP string, services []*proto.GatewayServiceStatus) {
+		go func(request *proto.GatewayStatusRequest, normalizedIP string, services []*proto.GatewayServiceStatus) {
 			// Run in a separate goroutine to not block the main status report flow.
 			// Create a detached context but preserve trace information
 			detachedCtx := context.WithoutCancel(ctx)
-			s.registerServiceOrCoreDevice(detachedCtx, req.GatewayId, req.Partition, normalizedIP, services, now)
-		}(normSourceIP, req.Services)
+			s.registerServiceOrCoreDevice(detachedCtx, request.GatewayId, request.Partition, normalizedIP, services, now)
+		}(req, normSourceIP, req.Services)

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies and fixes a potential race condition by passing the req pointer as an argument to the goroutine, preventing the closure from capturing a variable that could be modified concurrently.

Medium
Set actual gateway ID in status chunk

In buildGatewayStatusChunks, populate the GatewayId field of
proto.GatewayStatusChunk with the gatewayID variable instead of an empty string.

pkg/sync/service.go [1257-1269]

 statusChunks = append(statusChunks, &proto.GatewayStatusChunk{
     Services:    []*proto.GatewayServiceStatus{status},
-    GatewayId:   "",
+    GatewayId:   gatewayID,
     AgentId:     agentID,
     Timestamp:   chunk.Timestamp,
     Partition:   partition,
     IsFinal:     chunk.IsFinal,
     ChunkIndex:  chunk.ChunkIndex,
     TotalChunks: chunk.TotalChunks,
     KvStoreId:   "",
     TenantId:    tenantID,
     TenantSlug:  tenantSlug,
 })

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that GatewayId is hardcoded to an empty string, while the correct gatewayID variable is available and should be used for proper message correlation.

Medium
Populate GatewayId in heartbeat request

In pushHeartbeat, retrieve s.config.GatewayID and use it to populate the
GatewayId field in the GatewayStatusRequest instead of using an empty string.

pkg/sync/service.go [1342-1370]

 s.configMu.RLock()
 agentID := s.config.AgentID
 partition := s.config.Partition
+gatewayID := s.config.GatewayID
 s.configMu.RUnlock()
 // ...
 request := &proto.GatewayStatusRequest{
     Services:   []*proto.GatewayServiceStatus{status},
-    GatewayId:  "",
+    GatewayId:  gatewayID,
     AgentId:    agentID,
     Timestamp:  time.Now().Unix(),
     Partition:  partition,
     TenantId:   tenantID,
     TenantSlug: tenantSlug,
 }

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 7

__

Why: The suggestion correctly points out that GatewayId in the heartbeat request is hardcoded to an empty string, and it should be populated with the value from the service configuration.

Medium
General
Add missing tenant fields to response

Add the TenantId and TenantSlug fields to the AgentConfigResponse struct to
ensure it provides comprehensive tenant context.

proto/monitoring.pb.go [1518-1532]

 // AgentConfigResponse contains the agent's configuration from the SaaS control plane.
 type AgentConfigResponse struct {
 	state           protoimpl.MessageState `protogen:"open.v1"`
 	NotModified     bool                   `protobuf:"varint,1,opt,name=not_modified,json=notModified,proto3" json:"not_modified,omitempty"`             // True if config_version matches current; config fields empty
 	ConfigVersion   string                 `protobuf:"bytes,2,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"`        // New config version hash
 	ConfigTimestamp int64                  `protobuf:"varint,3,opt,name=config_timestamp,json=configTimestamp,proto3" json:"config_timestamp,omitempty"` // When config was last updated (unix timestamp)
 	// Agent settings
 	HeartbeatIntervalSec  int32 `protobuf:"varint,4,opt,name=heartbeat_interval_sec,json=heartbeatIntervalSec,proto3" json:"heartbeat_interval_sec,omitempty"`      // How often to push status (seconds)
 	ConfigPollIntervalSec int32 `protobuf:"varint,5,opt,name=config_poll_interval_sec,json=configPollIntervalSec,proto3" json:"config_poll_interval_sec,omitempty"` // How often to check for config updates (seconds)
 	// Checks to perform
 	Checks []*AgentCheckConfig `protobuf:"bytes,6,rep,name=checks,proto3" json:"checks,omitempty"`
 	// Optional: raw JSON config for extensibility
 	ConfigJson    []byte `protobuf:"bytes,7,opt,name=config_json,json=configJson,proto3" json:"config_json,omitempty"`
+	// Tenant information
+	TenantId   string `protobuf:"bytes,8,opt,name=tenant_id,json=tenantId,proto3" json:"tenant_id,omitempty"`
+	TenantSlug string `protobuf:"bytes,9,opt,name=tenant_slug,json=tenantSlug,proto3" json:"tenant_slug,omitempty"`
 	unknownFields protoimpl.UnknownFields
 	sizeCache     protoimpl.SizeCache
 }

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that AgentConfigResponse is missing tenant fields, which is inconsistent with other new messages, and proposes adding them to make the configuration response more complete.

Medium
  • Update
Imported GitHub PR comment. Original author: @qodo-code-review[bot] Original URL: https://github.com/carverauto/serviceradar/pull/2238#issuecomment-3731457594 Original created: 2026-01-10T01:55:25Z --- ## PR Code Suggestions ✨ <!-- 92d6ba6 --> Explore these optional code suggestions: <table><thead><tr><td><strong>Category</strong></td><td align=left><strong>Suggestion&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </strong></td><td align=center><strong>Impact</strong></td></tr><tbody><tr><td rowspan=1>High-level</td> <td> <details><summary>Leverage NATS features for service monitoring</summary> ___ **The custom gateway monitoring system in <code>pkg/core/gateways.go</code> should be <br>simplified. Instead of bespoke health checks and status management, leverage <br>built-in NATS features like the Key-Value Store and service heartbeats for a <br>more robust and maintainable solution.** ### Examples: <details> <summary> <a href="https://github.com/carverauto/serviceradar/pull/2238/files#diff-260332914ad2238e720f4637a71b0f9f01e899102bc6b37f7827782e56b0b5c0R1-R1549">pkg/core/gateways.go [1-1549]</a> </summary></details> ### Solution Walkthrough: #### Before: ```go // pkg/core/gateways.go // Server struct with DB, cache, mutexes, etc. type Server struct { DB db.DB gatewayStatusCache map[string]*models.GatewayStatus cacheMutex sync.RWMutex // ... } // Custom monitoring loop func (s *Server) MonitorGateways(ctx context.Context) { ticker := time.NewTicker(monitorInterval) for range ticker.C { gatewayStatuses, _ := s.getGatewayStatuses(ctx, ...) for _, ps := range gatewayStatuses { // Manually check if last_seen is too old if ps.LastSeen.Before(threshold) { s.handleGatewayDown(ctx, ps.GatewayID, ...) } } } } // gRPC handler to receive status func (s *Server) PushStatus(ctx context.Context, req *proto.GatewayStatusRequest) (*proto.GatewayStatusResponse, error) { // ... // Manually update status in DB and cache s.DB.UpdateGatewayStatus(ctx, gatewayStatus) // ... } ``` #### After: ```go // Simplified monitoring using NATS type NatsMonitor struct { NatsConn *nats.Conn KV nats.KeyValue // ... } func NewNatsMonitor(nc *nats.Conn) *NatsMonitor { js, _ := nc.JetStream() kv, _ := js.KeyValue("gateway_status") return &NatsMonitor{NatsConn: nc, KV: kv} } // Monitor using NATS advisories func (m *NatsMonitor) MonitorGateways(ctx context.Context) { // NATS services send heartbeats automatically. // Subscribe to advisories for offline events. m.NatsConn.Subscribe("*. ``` <details><summary>Suggestion importance[1-10]: 9</summary> __ Why: The suggestion correctly identifies that the custom-built monitoring in `pkg/core/gateways.go` could be greatly simplified by using built-in NATS features like KV Store and service heartbeats, reducing significant code complexity. </details></details></td><td align=center>High </td></tr><tr><td rowspan=3>Possible issue</td> <td> <details><summary>Prevent race condition in goroutine</summary> ___ **To prevent a potential race condition, pass the <code>req</code> object as an argument to the <br>goroutine instead of capturing it in the closure.** [pkg/core/gateways.go [624-629]](https://github.com/carverauto/serviceradar/pull/2238/files#diff-260332914ad2238e720f4637a71b0f9f01e899102bc6b37f7827782e56b0b5c0R624-R629) ```diff - go func(normalizedIP string, services []*proto.GatewayServiceStatus) { + go func(request *proto.GatewayStatusRequest, normalizedIP string, services []*proto.GatewayServiceStatus) { // Run in a separate goroutine to not block the main status report flow. // Create a detached context but preserve trace information detachedCtx := context.WithoutCancel(ctx) - s.registerServiceOrCoreDevice(detachedCtx, req.GatewayId, req.Partition, normalizedIP, services, now) - }(normSourceIP, req.Services) + s.registerServiceOrCoreDevice(detachedCtx, request.GatewayId, request.Partition, normalizedIP, services, now) + }(req, normSourceIP, req.Services) ``` `[To ensure code accuracy, apply this suggestion manually]` <details><summary>Suggestion importance[1-10]: 8</summary> __ Why: The suggestion correctly identifies and fixes a potential race condition by passing the `req` pointer as an argument to the goroutine, preventing the closure from capturing a variable that could be modified concurrently. </details></details></td><td align=center>Medium </td></tr><tr><td> <details><summary>Set actual gateway ID in status chunk</summary> ___ **In <code>buildGatewayStatusChunks</code>, populate the <code>GatewayId</code> field of <br><code>proto.GatewayStatusChunk</code> with the <code>gatewayID</code> variable instead of an empty string.** [pkg/sync/service.go [1257-1269]](https://github.com/carverauto/serviceradar/pull/2238/files#diff-b4ea5a5b3d811fa94c6a84c71c0ddb920ce177a376d13cb776f05dd6017c4c7eR1257-R1269) ```diff statusChunks = append(statusChunks, &proto.GatewayStatusChunk{ Services: []*proto.GatewayServiceStatus{status}, - GatewayId: "", + GatewayId: gatewayID, AgentId: agentID, Timestamp: chunk.Timestamp, Partition: partition, IsFinal: chunk.IsFinal, ChunkIndex: chunk.ChunkIndex, TotalChunks: chunk.TotalChunks, KvStoreId: "", TenantId: tenantID, TenantSlug: tenantSlug, }) ``` `[To ensure code accuracy, apply this suggestion manually]` <details><summary>Suggestion importance[1-10]: 7</summary> __ Why: The suggestion correctly identifies that `GatewayId` is hardcoded to an empty string, while the correct `gatewayID` variable is available and should be used for proper message correlation. </details></details></td><td align=center>Medium </td></tr><tr><td> <details><summary>Populate GatewayId in heartbeat request</summary> ___ **In <code>pushHeartbeat</code>, retrieve <code>s.config.GatewayID</code> and use it to populate the <br><code>GatewayId</code> field in the <code>GatewayStatusRequest</code> instead of using an empty string.** [pkg/sync/service.go [1342-1370]](https://github.com/carverauto/serviceradar/pull/2238/files#diff-b4ea5a5b3d811fa94c6a84c71c0ddb920ce177a376d13cb776f05dd6017c4c7eR1342-R1370) ```diff s.configMu.RLock() agentID := s.config.AgentID partition := s.config.Partition +gatewayID := s.config.GatewayID s.configMu.RUnlock() // ... request := &proto.GatewayStatusRequest{ Services: []*proto.GatewayServiceStatus{status}, - GatewayId: "", + GatewayId: gatewayID, AgentId: agentID, Timestamp: time.Now().Unix(), Partition: partition, TenantId: tenantID, TenantSlug: tenantSlug, } ``` `[To ensure code accuracy, apply this suggestion manually]` <details><summary>Suggestion importance[1-10]: 7</summary> __ Why: The suggestion correctly points out that `GatewayId` in the heartbeat request is hardcoded to an empty string, and it should be populated with the value from the service configuration. </details></details></td><td align=center>Medium </td></tr><tr><td rowspan=1>General</td> <td> <details><summary>Add missing tenant fields to response</summary> ___ **Add the <code>TenantId</code> and <code>TenantSlug</code> fields to the <code>AgentConfigResponse</code> struct to <br>ensure it provides comprehensive tenant context.** [proto/monitoring.pb.go [1518-1532]](https://github.com/carverauto/serviceradar/pull/2238/files#diff-4f7e955b42854cc9cf3fb063b95e58a04f36271e6a0c1cb42ea6d7953dd96cc4R1518-R1532) ```diff // AgentConfigResponse contains the agent's configuration from the SaaS control plane. type AgentConfigResponse struct { state protoimpl.MessageState `protogen:"open.v1"` NotModified bool `protobuf:"varint,1,opt,name=not_modified,json=notModified,proto3" json:"not_modified,omitempty"` // True if config_version matches current; config fields empty ConfigVersion string `protobuf:"bytes,2,opt,name=config_version,json=configVersion,proto3" json:"config_version,omitempty"` // New config version hash ConfigTimestamp int64 `protobuf:"varint,3,opt,name=config_timestamp,json=configTimestamp,proto3" json:"config_timestamp,omitempty"` // When config was last updated (unix timestamp) // Agent settings HeartbeatIntervalSec int32 `protobuf:"varint,4,opt,name=heartbeat_interval_sec,json=heartbeatIntervalSec,proto3" json:"heartbeat_interval_sec,omitempty"` // How often to push status (seconds) ConfigPollIntervalSec int32 `protobuf:"varint,5,opt,name=config_poll_interval_sec,json=configPollIntervalSec,proto3" json:"config_poll_interval_sec,omitempty"` // How often to check for config updates (seconds) // Checks to perform Checks []*AgentCheckConfig `protobuf:"bytes,6,rep,name=checks,proto3" json:"checks,omitempty"` // Optional: raw JSON config for extensibility ConfigJson []byte `protobuf:"bytes,7,opt,name=config_json,json=configJson,proto3" json:"config_json,omitempty"` + // Tenant information + TenantId string `protobuf:"bytes,8,opt,name=tenant_id,json=tenantId,proto3" json:"tenant_id,omitempty"` + TenantSlug string `protobuf:"bytes,9,opt,name=tenant_slug,json=tenantSlug,proto3" json:"tenant_slug,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } ``` `[To ensure code accuracy, apply this suggestion manually]` <details><summary>Suggestion importance[1-10]: 7</summary> __ Why: The suggestion correctly identifies that `AgentConfigResponse` is missing tenant fields, which is inconsistent with other new messages, and proposes adding them to make the configuration response more complete. </details></details></td><td align=center>Medium </td></tr> <tr><td align="center" colspan="2"> - [ ] Update <!-- /improve_multi --more_suggestions=true --> </td><td></td></tr></tbody></table>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
carverauto/serviceradar!2642
No description provided.