1933 bugui settingspoller missing config options in forms #2409

Merged
mfreeman451 merged 9 commits from refs/pull/2409/head into main 2025-11-11 02:08:15 +00:00
mfreeman451 commented 2025-11-11 00:51:05 +00:00 (Migrated from github.com)
Owner

Imported from GitHub pull request.

Original GitHub pull request: #1934
Original author: @mfreeman451
Original URL: https://github.com/carverauto/serviceradar/pull/1934
Original created: 2025-11-11T00:51:05Z
Original updated: 2025-11-11T02:08:43Z
Original head: carverauto/serviceradar:1933-bugui-settingspoller-missing-config-options-in-forms
Original base: main
Original merged: 2025-11-11T02:08: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, Bug fix


Description

  • Add KV-backed checker config seeding to agent startup

  • Implement retry logic for KV manager initialization with configurable timeouts

  • Expand agent and poller config forms with comprehensive security and logging options

  • Fix remote watcher target deduplication and agent-scoped service scope normalization

  • Upgrade agent and poller KV permissions from reader to writer role


Diagram Walkthrough

flowchart LR
  A["Agent Startup"] -->|seedCheckerConfigsFromDisk| B["Read Checker JSON Files"]
  B -->|PutIfAbsent| C["KV Store"]
  D["KV Manager Init"] -->|NewKVManagerFromEnv| E{Connection Success?}
  E -->|Fail| F["NewKVManagerFromEnvWithRetry"]
  F -->|Exponential Backoff| E
  E -->|Success| G["Config Loader Ready"]
  H["Agent/Poller Forms"] -->|SecurityFields Component| I["TLS/SPIFFE Config"]
  H -->|OTel Config| J["Logging & Telemetry"]
  K["Watcher Targets"] -->|Deduplication| L["Normalized Target Map"]
  L -->|Scope Override| M["Agent-Scoped Services"]

File Walkthrough

Relevant files
Enhancement
10 files
main.go
Add checker config seeding from disk to KV                             
+104/-0 
service.go
Add retry logic for KV manager initialization                       
+12/-1   
config.go
Support explicit KV key paths for direct access                   
+5/-0     
kv_client.go
Implement KV manager retry with backoff and validation     
+157/-11
kv_loader.go
Add explicit KV key prefix detection and derivation           
+33/-1   
client.go
Implement watch stream resilience with exponential backoff
+147/-40
config.go
Add retry logic for core KV manager initialization             
+7/-1     
AgentConfigForm.tsx
Redesign agent form with security and logging sections     
+329/-197
PollerConfigForm.tsx
Redesign poller form with agents, checks, and security     
+667/-224
SecurityFields.tsx
Create reusable security configuration component                 
+196/-0 
Tests
2 files
config_test.go
Add test for explicit agent KV key loading                             
+27/-0   
kv_client_test.go
Add tests for KV retry logic and environment validation   
+120/-0 
Dependencies
1 files
BUILD.bazel
Add gRPC status code dependencies                                               
+2/-0     
Bug fix
3 files
auth.go
Deduplicate and normalize remote watcher targets                 
+35/-17 
ServicesTreeNavigation.tsx
Filter global services to allowed types only                         
+22/-6   
WatcherTelemetryPanel.tsx
Normalize watcher scopes for agent-scoped services             
+22/-2   
Configuration changes
3 files
deploy.sh
Upgrade agent KV role from reader to writer                           
+1/-1     
serviceradar-config.yaml
Upgrade agent KV role from reader to writer                           
+2/-2     
configmap.yaml
Upgrade agent KV role from reader to writer                           
+2/-2     
Formatting
1 files
BUILD.bazel
Fix error message wording in build script                               
+1/-1     

Imported from GitHub pull request. Original GitHub pull request: #1934 Original author: @mfreeman451 Original URL: https://github.com/carverauto/serviceradar/pull/1934 Original created: 2025-11-11T00:51:05Z Original updated: 2025-11-11T02:08:43Z Original head: carverauto/serviceradar:1933-bugui-settingspoller-missing-config-options-in-forms Original base: main Original merged: 2025-11-11T02:08: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, Bug fix ___ ### **Description** - Add KV-backed checker config seeding to agent startup - Implement retry logic for KV manager initialization with configurable timeouts - Expand agent and poller config forms with comprehensive security and logging options - Fix remote watcher target deduplication and agent-scoped service scope normalization - Upgrade agent and poller KV permissions from reader to writer role ___ ### Diagram Walkthrough ```mermaid flowchart LR A["Agent Startup"] -->|seedCheckerConfigsFromDisk| B["Read Checker JSON Files"] B -->|PutIfAbsent| C["KV Store"] D["KV Manager Init"] -->|NewKVManagerFromEnv| E{Connection Success?} E -->|Fail| F["NewKVManagerFromEnvWithRetry"] F -->|Exponential Backoff| E E -->|Success| G["Config Loader Ready"] H["Agent/Poller Forms"] -->|SecurityFields Component| I["TLS/SPIFFE Config"] H -->|OTel Config| J["Logging & Telemetry"] K["Watcher Targets"] -->|Deduplication| L["Normalized Target Map"] L -->|Scope Override| M["Agent-Scoped Services"] ``` <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>10 files</summary><table> <tr> <td><strong>main.go</strong><dd><code>Add checker config seeding from disk to KV</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-61358711e980ccf505246fd3915f97cbd3a380e9b66f6fa5aad46749968c5ca3">+104/-0</a>&nbsp; </td> </tr> <tr> <td><strong>service.go</strong><dd><code>Add retry logic for KV manager initialization</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-bdbe338c04da107ded4d961b6a02c05f7580a5b70d33d2e141c4b60769a35ea7">+12/-1</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>config.go</strong><dd><code>Support explicit KV key paths for direct access</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-a3d824da3c42420cd5cbb0a4a2c0e7b5bfddd819652788a0596d195dc6e31fa5">+5/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>kv_client.go</strong><dd><code>Implement KV manager retry with backoff and validation</code>&nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-0c911990aa32d43404f0f23dadc0363ec97ed4ca315592e6c9bd24510e82e06d">+157/-11</a></td> </tr> <tr> <td><strong>kv_loader.go</strong><dd><code>Add explicit KV key prefix detection and derivation</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-1d1c25f337f10b6e230c25c4bb7914a1b97106b106570d1c72f116bea17824a7">+33/-1</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>client.go</strong><dd><code>Implement watch stream resilience with exponential backoff</code></dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-9343ef5d37a9a21d1204c492e3375db1d541f2f07ca1ba6a03266558f06acf8e">+147/-40</a></td> </tr> <tr> <td><strong>config.go</strong><dd><code>Add retry logic for core KV manager initialization</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-a2dcdf3bac7ca59032d52f7a0635b5dbcfcb83a6f07cc45db8f57fba0cc33c30">+7/-1</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>AgentConfigForm.tsx</strong><dd><code>Redesign agent form with security and logging sections</code>&nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-cef412c83159bfda7fd977cfbe954990f5d1eb6f41a527027fbed887841b4599">+329/-197</a></td> </tr> <tr> <td><strong>PollerConfigForm.tsx</strong><dd><code>Redesign poller form with agents, checks, and security</code>&nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-a461cf9c9de7dcc94fbb380a8926ad17b741a2707b58a1d0ae76c70fed432484">+667/-224</a></td> </tr> <tr> <td><strong>SecurityFields.tsx</strong><dd><code>Create reusable security configuration component</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-71fc0352794e3b02f0c763f398dd13259051d23ed4f54864bf4db833bbff8d43">+196/-0</a>&nbsp; </td> </tr> </table></details></td></tr><tr><td><strong>Tests</strong></td><td><details><summary>2 files</summary><table> <tr> <td><strong>config_test.go</strong><dd><code>Add test for explicit agent KV key loading</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-29cea1b5b831c8655c7155f43e2367cec73e66d1e338f8b3c7877a2f339b8811">+27/-0</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>kv_client_test.go</strong><dd><code>Add tests for KV retry logic and environment validation</code>&nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-09814dd9ab05f9d40f40974f297806d71fe2eca5f8120492c9f79311153d3aef">+120/-0</a>&nbsp; </td> </tr> </table></details></td></tr><tr><td><strong>Dependencies</strong></td><td><details><summary>1 files</summary><table> <tr> <td><strong>BUILD.bazel</strong><dd><code>Add gRPC status code dependencies</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></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-fe829eea80a490a776c6729ae58aa08a6089cb43428719cc4d0fab01f1678b27">+2/-0</a>&nbsp; &nbsp; &nbsp; </td> </tr> </table></details></td></tr><tr><td><strong>Bug fix</strong></td><td><details><summary>3 files</summary><table> <tr> <td><strong>auth.go</strong><dd><code>Deduplicate and normalize remote watcher targets</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-61eb09279471ca59a1b57a306f0ad05988a8cb39eca163b32bfb86c53f8a553e">+35/-17</a>&nbsp; </td> </tr> <tr> <td><strong>ServicesTreeNavigation.tsx</strong><dd><code>Filter global services to allowed types only</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-1ed7ef6d80b5c019b943bbd7a1827806a8f054b84e1ca993bc51179748e9f4b5">+22/-6</a>&nbsp; &nbsp; </td> </tr> <tr> <td><strong>WatcherTelemetryPanel.tsx</strong><dd><code>Normalize watcher scopes for agent-scoped services</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-b35ea6ada7032b27a263d2e00a6ad5112693b6485cfbd07c48fca7fab626caa9">+22/-2</a>&nbsp; &nbsp; </td> </tr> </table></details></td></tr><tr><td><strong>Configuration changes</strong></td><td><details><summary>3 files</summary><table> <tr> <td><strong>deploy.sh</strong><dd><code>Upgrade agent KV role from reader to writer</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-e37a2eb47f6488f6f391d56a7376be0ca4f93afa355028a71dd0608d3ef1a8ba">+1/-1</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>serviceradar-config.yaml</strong><dd><code>Upgrade agent KV role from reader to writer</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-b8c8d2484103b11c396bc60d290c81df63c30a0f81103eceb5852a17e1d2b5e3">+2/-2</a>&nbsp; &nbsp; &nbsp; </td> </tr> <tr> <td><strong>configmap.yaml</strong><dd><code>Upgrade agent KV role from reader to writer</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-f4548beaa0a3a01a46971c82c5647a0f3f49eb38d66dd939d06d19018173fcd6">+2/-2</a>&nbsp; &nbsp; &nbsp; </td> </tr> </table></details></td></tr><tr><td><strong>Formatting</strong></td><td><details><summary>1 files</summary><table> <tr> <td><strong>BUILD.bazel</strong><dd><code>Fix error message wording in build script</code>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </dd></td> <td><a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-0e4db31c224a8f72ae8e870a849e38a59d74a2c7f7b04347b0b3eb07e20c5a80">+1/-1</a>&nbsp; &nbsp; &nbsp; </td> </tr> </table></details></td></tr></tr></tbody></table> </details> ___
qodo-code-review[bot] commented 2025-11-11 00:51:46 +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/1934#issuecomment-3514512928
Original created: 2025-11-11T00:51:46Z

PR Compliance Guide 🔍

(Compliance updated until commit github.com/carverauto/serviceradar@756ba115dc)

Below is a summary of compliance checks for this PR:

Security Compliance
Retry without jitter

Description: The retry loop for KV connection lacks a jitter component, which can cause thundering herd
and predictable backoff timing under load or outages.
kv_client.go [149-166]

Referred Code
		wait := baseBackoff << (attempt - 1)
		if wait > maxBackoff {
			wait = maxBackoff
		}

		select {
		case <-time.After(wait):
		case <-ctx.Done():
			if ctx.Err() != nil {
				return nil, ctx.Err()
			}
		}

		if time.Now().After(deadline) {
			return nil, fmt.Errorf("timed out waiting for KV connection after %d attempts: %w", attempt, lastErr)
		}
	}
}
Unvalidated config ingestion

Description: Seeding checker configs from disk into KV may ingest unvalidated JSON from local files,
risking malicious or malformed configuration if filesystem contents are untrusted.
main.go [108-114]

Referred Code
}

// Step 3: Create agent server with proper logger
if err := agent.SeedCheckerConfigsFromDisk(ctx, bootstrapResult.Manager(), &cfg, *configPath, agentLogger); err != nil {
	agentLogger.Warn().Err(err).Msg("Failed to seed checker configs to KV")
}

Ticket Compliance
🟡
🎫 #1933
🟢 Poller settings UI forms are missing configuration options and should expose comprehensive
fields.
Include security configuration options in poller forms (e.g., TLS, mTLS, SPIFFE).
Include logging and telemetry (OTel) options in poller forms.
Ensure forms support agent and checker configurations relevant to poller usage.
Fix any related UI deficiencies so users can configure pollers without editing raw config.
Visual/UI verification that all new fields render correctly and persist changes.
Browser/device compatibility per ticket template (various OS/browsers).
End-to-end validation that saved settings are honored by backend behavior.
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: Robust Error Handling and Edge Case Management

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

Status: Passed

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: Passed

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: 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:
Action Logging: The seeding of checker configurations into KV performs create operations but does not emit
structured audit logs including actor identity and outcome beyond generic info/warn
messages.

Referred Code

entries, err := os.ReadDir(cfg.CheckersDir)
if err != nil {
	return fmt.Errorf("read checker directory: %w", err)
}

for _, entry := range entries {
	if entry.IsDir() || filepath.Ext(entry.Name()) != ".json" {
		continue
	}

	path := filepath.Join(cfg.CheckersDir, entry.Name())
	data, err := os.ReadFile(path)
	if err != nil {
		log.Warn().Err(err).Str("file", path).Msg("Skipping checker seed; failed reading file")
		continue
	}

	key := fmt.Sprintf("agents/%s/checkers/%s", agentID, entry.Name())
	created, err := kvMgr.PutIfAbsent(ctx, key, data, 0)
	if err != nil {


 ... (clipped 9 lines)

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 Paths: Logs include filesystem paths and KV keys for seeded configs which might reveal
environment structure and agent IDs; confirm this is acceptable and that no secrets are
ever logged.

Referred Code
	log.Warn().Err(err).Str("file", path).Msg("Skipping checker seed; failed reading file")
	continue
}

key := fmt.Sprintf("agents/%s/checkers/%s", agentID, entry.Name())
created, err := kvMgr.PutIfAbsent(ctx, key, data, 0)
if err != nil {
	log.Warn().Err(err).Str("kv_key", key).Msg("Failed to seed checker config")
	continue
}

if created {
	log.Info().Str("kv_key", key).Str("file", path).Msg("Seeded checker config into KV")
} else {
	log.Debug().Str("kv_key", key).Msg("Checker config already present in KV; skipping seed")
}

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

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
- Requires Further Human Verification
🏷️ - Compliance label

Previous compliance checks

Compliance check up to commit 31e1361
Security Compliance
Header injection risk

Description: The OTEL headers field accepts arbitrary JSON object input from the UI and writes it into
configuration without sanitization, which could enable header injection to external OTEL
endpoints if this data is propagated directly to requests.
PollerConfigForm.tsx [487-500]

Referred Code
  <label className="block text-sm font-medium mb-2">Headers (JSON object)</label>
  <textarea
    value={otelHeadersText}
    onChange={(e) => setOtelHeadersText(e.target.value)}
    onBlur={handleHeadersBlur}
    className="w-full h-32 font-mono text-sm p-2 border border-gray-300 dark:border-gray-600 rounded-md bg-gray-50 dark:bg-gray-900"
    spellCheck={false}
  />
  {otelHeadersError && (
    <p className="text-sm text-red-600 mt-1">{otelHeadersError}</p>
  )}
</div>
<div className="grid grid-cols-3 gap-4">
  <div>
Unvalidated config write

Description: Seeding checker configs reads arbitrary JSON files from disk and writes them into KV
without schema validation, which could allow malicious or malformed config content to be
propagated if the directory is writable by untrusted actors.
checker_seed.go [70-98]

Referred Code
entries, err := os.ReadDir(cfg.CheckersDir)
if err != nil {
	return fmt.Errorf("read checker directory: %w", err)
}

for _, entry := range entries {
	if entry.IsDir() || filepath.Ext(entry.Name()) != ".json" {
		continue
	}

	path := filepath.Join(cfg.CheckersDir, entry.Name())
	data, err := os.ReadFile(path)
	if err != nil {
		log.Warn().Err(err).Str("file", path).Msg("Skipping checker seed; failed reading file")
		continue
	}

	key := fmt.Sprintf("agents/%s/checkers/%s", agentID, entry.Name())
	created, err := kvMgr.PutIfAbsent(ctx, key, data, 0)
	if err != nil {
		log.Warn().Err(err).Str("kv_key", key).Msg("Failed to seed checker config")


 ... (clipped 8 lines)
Ticket Compliance
🟡
🎫 #1933
🟢 The Poller settings UI forms are missing configuration options and should expose the full
set of relevant security and logging options.
Ensure the UI supports configuring poller agents, their security, and checks with
appropriate fields.
Provide expected behavior for forms so users can input KV-related endpoints and
telemetry/logging settings.
Visually verify the new PollerConfigForm renders correctly, is accessible, and matches
design expectations across browsers.
Manually test that JSON headers parsing/validation UX is clear and error messages are
helpful.
Validate end-to-end that saved configurations persist and load correctly from the backend
in the deployed environment.
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: Robust Error Handling and Edge Case Management

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

Status: Passed

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: Passed

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: 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:
Action logging: Seeding checker configs into KV performs create operations but does not produce structured
audit logs tied to an actor/user ID, making it unclear who initiated these critical
writes.

Referred Code

entries, err := os.ReadDir(cfg.CheckersDir)
if err != nil {
	return fmt.Errorf("read checker directory: %w", err)
}

for _, entry := range entries {
	if entry.IsDir() || filepath.Ext(entry.Name()) != ".json" {
		continue
	}

	path := filepath.Join(cfg.CheckersDir, entry.Name())
	data, err := os.ReadFile(path)
	if err != nil {
		log.Warn().Err(err).Str("file", path).Msg("Skipping checker seed; failed reading file")
		continue
	}

	key := fmt.Sprintf("agents/%s/checkers/%s", agentID, entry.Name())
	created, err := kvMgr.PutIfAbsent(ctx, key, data, 0)
	if err != nil {


 ... (clipped 9 lines)

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:
Log sensitivity: Seeding logs include KV key paths and filesystem paths which may reveal internal
structure; verify no sensitive values from JSON payloads or secrets are logged at any
level.

Referred Code

entries, err := os.ReadDir(cfg.CheckersDir)
if err != nil {
	return fmt.Errorf("read checker directory: %w", err)
}

for _, entry := range entries {
	if entry.IsDir() || filepath.Ext(entry.Name()) != ".json" {
		continue
	}

	path := filepath.Join(cfg.CheckersDir, entry.Name())
	data, err := os.ReadFile(path)
	if err != nil {
		log.Warn().Err(err).Str("file", path).Msg("Skipping checker seed; failed reading file")
		continue
	}

	key := fmt.Sprintf("agents/%s/checkers/%s", agentID, entry.Name())
	created, err := kvMgr.PutIfAbsent(ctx, key, data, 0)
	if err != nil {


 ... (clipped 9 lines)

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

Compliance check up to commit dea4a76
Security Compliance
Information disclosure

Description: The function resolveAgentID reads a JSON config file path provided via configPath and
returns errors containing file paths and parsing details, which may disclose sensitive
file system information to logs if not handled properly.
main.go [222-249]

Referred Code
func resolveAgentID(configPath, current string) (string, error) {
	candidate := strings.TrimSpace(current)
	if candidate != "" && candidate != defaultAgentID {
		return candidate, nil
	}
	if envID := strings.TrimSpace(os.Getenv("AGENT_ID")); envID != "" && envID != defaultAgentID {
		return envID, nil
	}
	path := strings.TrimSpace(configPath)
	if path == "" {
		return "", fmt.Errorf("agent_id not set and config path unavailable")
	}

	payload, err := os.ReadFile(path)
	if err != nil {
		return "", fmt.Errorf("read config for agent_id: %w", err)
	}
	var stub struct {
		AgentID string `json:"agent_id"`
	}
	if err := json.Unmarshal(payload, &stub); err != nil {


 ... (clipped 7 lines)
Resource exhaustion

Description: The watch retry logic treats many errors as retryable and may loop indefinitely until
context timeout; if contexts are long-lived, this could enable resource exhaustion by an
attacker causing persistent reconnection attempts.
client.go [70-177]

Referred Code
func (k *Client) watchStream(ctx context.Context, key string, stream proto.KVService_WatchClient, out chan<- []byte) {
	defer close(out)

	backoff := watchBackoffInitial
	current := stream

	for {
		if current == nil {
			var ok bool
			current, backoff, ok = k.establishStream(ctx, key, backoff)
			if !ok {
				return
			}
			continue
		}

		resp, err := current.Recv()
		if err != nil {
			if !shouldRetryWatch(ctx, err) {
				return
			}


 ... (clipped 87 lines)
Ticket Compliance
🟡
🎫 #1933
🟢 Poller settings UI form should expose missing configuration options so users can configure
pollers fully.
Ensure form supports security configuration (TLS/mTLS/SPIFFE) for poller and connections
it uses.
Include logging and OpenTelemetry options in poller settings.
Allow configuration of agents and their checks within the poller configuration UI.
Improve overall UX for configuring poller-related KV and service fields.
🔴
Visual/UI verification that all new fields render correctly and are usable across
supported browsers.
Validation that JSON headers editor behaves correctly for invalid inputs and user
interactions.
End-to-end check that saved form data maps to backend schema as expected.
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: Robust Error Handling and Edge Case Management

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

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:
Retry Logging: New KV connection retry logic logs attempts and outcomes but it is unclear whether all
critical KV-related actions (e.g., seeding configs, PutIfAbsent decisions) are
consistently logged with user/action context across the system.

Referred Code
lastErr = err
log.Warn().
	Err(err).
	Int("attempt", attempt).
	Msg("KV connection attempt failed; retrying")

wait := baseBackoff << (attempt - 1)
if wait > maxBackoff {
	wait = maxBackoff
}

select {
case <-time.After(wait):
case <-ctx.Done():
	if ctx.Err() != nil {
		return nil, ctx.Err()
	}
}

if time.Now().After(deadline) {
	return nil, fmt.Errorf("timed out waiting for KV connection after %d attempts: %w", attempt, lastErr)


 ... (clipped 1 lines)

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:
Error Exposure: User-facing context is not shown here, but added errors (e.g., resolveAgentID and seeding)
return detailed messages that might propagate; verify they are not exposed to end users in
UIs or APIs.

Referred Code
func resolveAgentID(configPath, current string) (string, error) {
	candidate := strings.TrimSpace(current)
	if candidate != "" && candidate != defaultAgentID {
		return candidate, nil
	}
	if envID := strings.TrimSpace(os.Getenv("AGENT_ID")); envID != "" && envID != defaultAgentID {
		return envID, nil
	}
	path := strings.TrimSpace(configPath)
	if path == "" {
		return "", fmt.Errorf("agent_id not set and config path unavailable")
	}

	payload, err := os.ReadFile(path)
	if err != nil {
		return "", fmt.Errorf("read config for agent_id: %w", err)
	}
	var stub struct {
		AgentID string `json:"agent_id"`
	}
	if err := json.Unmarshal(payload, &stub); err != nil {


 ... (clipped 7 lines)

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:
Log Sensitivity: Seeding logs include KV keys and file paths which seem safe, but headers and config
content fields in UI forms could be sensitive if later logged; ensure no secrets (e.g.,
OTEL headers) are ever written to logs.

Referred Code
entries, err := os.ReadDir(cfg.CheckersDir)
if err != nil {
	return fmt.Errorf("read checker directory: %w", err)
}

for _, entry := range entries {
	if entry.IsDir() || filepath.Ext(entry.Name()) != ".json" {
		continue
	}

	path := filepath.Join(cfg.CheckersDir, entry.Name())
	data, err := os.ReadFile(path)
	if err != nil {
		log.Warn().Err(err).Str("file", path).Msg("Skipping checker seed; failed reading file")
		continue
	}

	key := fmt.Sprintf("agents/%s/checkers/%s", agentID, entry.Name())
	created, err := kvMgr.PutIfAbsent(ctx, key, data, 0)
	if err != nil {
		log.Warn().Err(err).Str("kv_key", key).Msg("Failed to seed checker config")


 ... (clipped 9 lines)

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:
UI Validation: The new forms accept numerous free-text fields (endpoints, headers JSON, file paths) with
minimal validation beyond JSON parse, which may require stronger client/server-side
validation and sanitization.

Referred Code
<div className="space-y-6">
  <div className="grid grid-cols-4 gap-4">
    <div>
      <label className="block text-sm font-medium mb-2">Log Level</label>
      <select
        value={config.logging?.level ?? 'info'}
        onChange={(e) => updateConfig('logging.level', e.target.value)}
        className="w-full p-2 border border-gray-300 dark:border-gray-600 rounded-md"
      >
        <option value="debug">Debug</option>
        <option value="info">Info</option>
        <option value="warn">Warn</option>
        <option value="error">Error</option>
      </select>
    </div>
    <div>
      <label className="block text-sm font-medium mb-2">Output</label>
      <select
        value={config.logging?.output ?? 'stdout'}
        onChange={(e) => updateConfig('logging.output', e.target.value)}
        className="w-full p-2 border border-gray-300 dark:border-gray-600 rounded-md"


 ... (clipped 128 lines)

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

Imported GitHub PR comment. Original author: @qodo-code-review[bot] Original URL: https://github.com/carverauto/serviceradar/pull/1934#issuecomment-3514512928 Original created: 2025-11-11T00:51:46Z --- ## PR Compliance Guide 🔍 <!-- https://github.com/carverauto/serviceradar/commit/756ba115dcfa127a15bfde30704baba009a6f5e5 --> #### (Compliance updated until commit https://github.com/carverauto/serviceradar/commit/756ba115dcfa127a15bfde30704baba009a6f5e5) 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 rowspan=2>⚪</td> <td><details><summary><strong>Retry without jitter </strong></summary><br> <b>Description:</b> The retry loop for KV connection lacks a jitter component, which can cause thundering herd <br>and predictable backoff timing under load or outages.<br> <strong><a href='https://github.com/carverauto/serviceradar/pull/1934/files#diff-0c911990aa32d43404f0f23dadc0363ec97ed4ca315592e6c9bd24510e82e06dR149-R166'>kv_client.go [149-166]</a></strong><br> <details open><summary>Referred Code</summary> ```go wait := baseBackoff << (attempt - 1) if wait > maxBackoff { wait = maxBackoff } select { case <-time.After(wait): case <-ctx.Done(): if ctx.Err() != nil { return nil, ctx.Err() } } if time.Now().After(deadline) { return nil, fmt.Errorf("timed out waiting for KV connection after %d attempts: %w", attempt, lastErr) } } } ``` </details></details></td></tr> <tr><td><details><summary><strong>Unvalidated config ingestion</strong></summary><br> <b>Description:</b> Seeding checker configs from disk into KV may ingest unvalidated JSON from local files, <br>risking malicious or malformed configuration if filesystem contents are untrusted.<br> <strong><a href='https://github.com/carverauto/serviceradar/pull/1934/files#diff-61358711e980ccf505246fd3915f97cbd3a380e9b66f6fa5aad46749968c5ca3R108-R114'>main.go [108-114]</a></strong><br> <details open><summary>Referred Code</summary> ```go } // Step 3: Create agent server with proper logger if err := agent.SeedCheckerConfigsFromDisk(ctx, bootstrapResult.Manager(), &cfg, *configPath, agentLogger); err != nil { agentLogger.Warn().Err(err).Msg("Failed to seed checker configs to KV") } ``` </details></details></td></tr> <tr><td colspan='2'><strong>Ticket Compliance</strong></td></tr> <tr><td>🟡</td> <td> <details> <summary>🎫 <a href=https://github.com/carverauto/serviceradar/issues/1933>#1933</a></summary> <table width='100%'><tbody> <tr><td rowspan=5>🟢</td> <td>Poller settings UI forms are missing configuration options and should expose comprehensive <br>fields.</td></tr> <tr><td>Include security configuration options in poller forms (e.g., TLS, mTLS, SPIFFE).</td></tr> <tr><td>Include logging and telemetry (OTel) options in poller forms.</td></tr> <tr><td>Ensure forms support agent and checker configurations relevant to poller usage.</td></tr> <tr><td>Fix any related UI deficiencies so users can configure pollers without editing raw config.</td></tr> <tr><td rowspan=3>⚪</td> <td>Visual/UI verification that all new fields render correctly and persist changes.</td></tr> <tr><td>Browser/device compatibility per ticket template (various OS/browsers).</td></tr> <tr><td>End-to-end validation that saved settings are honored by backend behavior.</td></tr> </tbody></table> </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=4>🟢</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> <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:** 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> <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:** 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> <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:** 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=2>⚪</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/1934/files#diff-e59d16c2621f9241f14e037549badf987107edaa5ad5d27eb160d27b5ccaf276R69-R98'><strong>Action Logging</strong></a>: The seeding of checker configurations into KV performs create operations but does not emit <br>structured audit logs including actor identity and outcome beyond generic info/warn <br>messages.<br> <details open><summary>Referred Code</summary> ```go entries, err := os.ReadDir(cfg.CheckersDir) if err != nil { return fmt.Errorf("read checker directory: %w", err) } for _, entry := range entries { if entry.IsDir() || filepath.Ext(entry.Name()) != ".json" { continue } path := filepath.Join(cfg.CheckersDir, entry.Name()) data, err := os.ReadFile(path) if err != nil { log.Warn().Err(err).Str("file", path).Msg("Skipping checker seed; failed reading file") continue } key := fmt.Sprintf("agents/%s/checkers/%s", agentID, entry.Name()) created, err := kvMgr.PutIfAbsent(ctx, key, data, 0) if err != nil { ... (clipped 9 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><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/1934/files#diff-e59d16c2621f9241f14e037549badf987107edaa5ad5d27eb160d27b5ccaf276R83-R98'><strong>Sensitive Paths</strong></a>: Logs include filesystem paths and KV keys for seeded configs which might reveal <br>environment structure and agent IDs; confirm this is acceptable and that no secrets are <br>ever logged.<br> <details open><summary>Referred Code</summary> ```go log.Warn().Err(err).Str("file", path).Msg("Skipping checker seed; failed reading file") continue } key := fmt.Sprintf("agents/%s/checkers/%s", agentID, entry.Name()) created, err := kvMgr.PutIfAbsent(ctx, key, data, 0) if err != nil { log.Warn().Err(err).Str("kv_key", key).Msg("Failed to seed checker config") continue } if created { log.Info().Str("kv_key", key).Str("file", path).Msg("Seeded checker config into KV") } else { log.Debug().Str("kv_key", key).Msg("Checker config already present in KV; skipping seed") } ``` </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"> <!-- placeholder --> <!-- /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> ___ #### Previous compliance checks <details> <summary>Compliance check up to commit <a href='https://github.com/carverauto/serviceradar/commit/31e136186cb2c95093018b8ef4e4e7d3931d0b8f'>31e1361</a></summary><br> <table><tbody><tr><td colspan='2'><strong>Security Compliance</strong></td></tr> <tr><td rowspan=2>⚪</td> <td><details><summary><strong>Header injection risk </strong></summary><br> <b>Description:</b> The OTEL headers field accepts arbitrary JSON object input from the UI and writes it into <br>configuration without sanitization, which could enable header injection to external OTEL <br>endpoints if this data is propagated directly to requests.<br> <strong><a href='https://github.com/carverauto/serviceradar/pull/1934/files#diff-a461cf9c9de7dcc94fbb380a8926ad17b741a2707b58a1d0ae76c70fed432484R487-R500'>PollerConfigForm.tsx [487-500]</a></strong><br> <details open><summary>Referred Code</summary> ```tsx <label className="block text-sm font-medium mb-2">Headers (JSON object)</label> <textarea value={otelHeadersText} onChange={(e) => setOtelHeadersText(e.target.value)} onBlur={handleHeadersBlur} className="w-full h-32 font-mono text-sm p-2 border border-gray-300 dark:border-gray-600 rounded-md bg-gray-50 dark:bg-gray-900" spellCheck={false} /> {otelHeadersError && ( <p className="text-sm text-red-600 mt-1">{otelHeadersError}</p> )} </div> <div className="grid grid-cols-3 gap-4"> <div> ``` </details></details></td></tr> <tr><td><details><summary><strong>Unvalidated config write</strong></summary><br> <b>Description:</b> Seeding checker configs reads arbitrary JSON files from disk and writes them into KV <br>without schema validation, which could allow malicious or malformed config content to be <br>propagated if the directory is writable by untrusted actors.<br> <strong><a href='https://github.com/carverauto/serviceradar/pull/1934/files#diff-e59d16c2621f9241f14e037549badf987107edaa5ad5d27eb160d27b5ccaf276R70-R98'>checker_seed.go [70-98]</a></strong><br> <details open><summary>Referred Code</summary> ```go entries, err := os.ReadDir(cfg.CheckersDir) if err != nil { return fmt.Errorf("read checker directory: %w", err) } for _, entry := range entries { if entry.IsDir() || filepath.Ext(entry.Name()) != ".json" { continue } path := filepath.Join(cfg.CheckersDir, entry.Name()) data, err := os.ReadFile(path) if err != nil { log.Warn().Err(err).Str("file", path).Msg("Skipping checker seed; failed reading file") continue } key := fmt.Sprintf("agents/%s/checkers/%s", agentID, entry.Name()) created, err := kvMgr.PutIfAbsent(ctx, key, data, 0) if err != nil { log.Warn().Err(err).Str("kv_key", key).Msg("Failed to seed checker config") ... (clipped 8 lines) ``` </details></details></td></tr> <tr><td colspan='2'><strong>Ticket Compliance</strong></td></tr> <tr><td>🟡</td> <td> <details> <summary>🎫 <a href=https://github.com/carverauto/serviceradar/issues/1933>#1933</a></summary> <table width='100%'><tbody> <tr><td rowspan=3>🟢</td> <td>The Poller settings UI forms are missing configuration options and should expose the full <br>set of relevant security and logging options.</td></tr> <tr><td>Ensure the UI supports configuring poller agents, their security, and checks with <br>appropriate fields.</td></tr> <tr><td>Provide expected behavior for forms so users can input KV-related endpoints and <br>telemetry/logging settings.</td></tr> <tr><td rowspan=3>⚪</td> <td>Visually verify the new PollerConfigForm renders correctly, is accessible, and matches <br>design expectations across browsers.</td></tr> <tr><td>Manually test that JSON headers parsing/validation UX is clear and error messages are <br>helpful.</td></tr> <tr><td>Validate end-to-end that saved configurations persist and load correctly from the backend <br>in the deployed environment.</td></tr> </tbody></table> </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=4>🟢</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> <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:** 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> <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:** 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> <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:** 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=2>⚪</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/1934/files#diff-e59d16c2621f9241f14e037549badf987107edaa5ad5d27eb160d27b5ccaf276R69-R98'><strong>Action logging</strong></a>: Seeding checker configs into KV performs create operations but does not produce structured <br>audit logs tied to an actor/user ID, making it unclear who initiated these critical <br>writes.<br> <details open><summary>Referred Code</summary> ```go entries, err := os.ReadDir(cfg.CheckersDir) if err != nil { return fmt.Errorf("read checker directory: %w", err) } for _, entry := range entries { if entry.IsDir() || filepath.Ext(entry.Name()) != ".json" { continue } path := filepath.Join(cfg.CheckersDir, entry.Name()) data, err := os.ReadFile(path) if err != nil { log.Warn().Err(err).Str("file", path).Msg("Skipping checker seed; failed reading file") continue } key := fmt.Sprintf("agents/%s/checkers/%s", agentID, entry.Name()) created, err := kvMgr.PutIfAbsent(ctx, key, data, 0) if err != nil { ... (clipped 9 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><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/1934/files#diff-e59d16c2621f9241f14e037549badf987107edaa5ad5d27eb160d27b5ccaf276R69-R98'><strong>Log sensitivity</strong></a>: Seeding logs include KV key paths and filesystem paths which may reveal internal <br>structure; verify no sensitive values from JSON payloads or secrets are logged at any <br>level.<br> <details open><summary>Referred Code</summary> ```go entries, err := os.ReadDir(cfg.CheckersDir) if err != nil { return fmt.Errorf("read checker directory: %w", err) } for _, entry := range entries { if entry.IsDir() || filepath.Ext(entry.Name()) != ".json" { continue } path := filepath.Join(cfg.CheckersDir, entry.Name()) data, err := os.ReadFile(path) if err != nil { log.Warn().Err(err).Str("file", path).Msg("Skipping checker seed; failed reading file") continue } key := fmt.Sprintf("agents/%s/checkers/%s", agentID, entry.Name()) created, err := kvMgr.PutIfAbsent(ctx, key, data, 0) if err != nil { ... (clipped 9 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"> <!-- /compliance --update_compliance=true --> </td></tr></tbody></table> </details> <details> <summary>Compliance check up to commit <a href='https://github.com/carverauto/serviceradar/commit/dea4a76f7eac4074e306df49170cf086f4c58a59'>dea4a76</a></summary><br> <table><tbody><tr><td colspan='2'><strong>Security Compliance</strong></td></tr> <tr><td rowspan=2>⚪</td> <td><details><summary><strong>Information disclosure </strong></summary><br> <b>Description:</b> The function <code>resolveAgentID</code> reads a JSON config file path provided via <code>configPath</code> and <br>returns errors containing file paths and parsing details, which may disclose sensitive <br>file system information to logs if not handled properly.<br> <strong><a href='https://github.com/carverauto/serviceradar/pull/1934/files#diff-61358711e980ccf505246fd3915f97cbd3a380e9b66f6fa5aad46749968c5ca3R222-R249'>main.go [222-249]</a></strong><br> <details open><summary>Referred Code</summary> ```go func resolveAgentID(configPath, current string) (string, error) { candidate := strings.TrimSpace(current) if candidate != "" && candidate != defaultAgentID { return candidate, nil } if envID := strings.TrimSpace(os.Getenv("AGENT_ID")); envID != "" && envID != defaultAgentID { return envID, nil } path := strings.TrimSpace(configPath) if path == "" { return "", fmt.Errorf("agent_id not set and config path unavailable") } payload, err := os.ReadFile(path) if err != nil { return "", fmt.Errorf("read config for agent_id: %w", err) } var stub struct { AgentID string `json:"agent_id"` } if err := json.Unmarshal(payload, &stub); err != nil { ... (clipped 7 lines) ``` </details></details></td></tr> <tr><td><details><summary><strong>Resource exhaustion</strong></summary><br> <b>Description:</b> The watch retry logic treats many errors as retryable and may loop indefinitely until <br>context timeout; if contexts are long-lived, this could enable resource exhaustion by an <br>attacker causing persistent reconnection attempts.<br> <strong><a href='https://github.com/carverauto/serviceradar/pull/1934/files#diff-9343ef5d37a9a21d1204c492e3375db1d541f2f07ca1ba6a03266558f06acf8eR70-R177'>client.go [70-177]</a></strong><br> <details open><summary>Referred Code</summary> ```go func (k *Client) watchStream(ctx context.Context, key string, stream proto.KVService_WatchClient, out chan<- []byte) { defer close(out) backoff := watchBackoffInitial current := stream for { if current == nil { var ok bool current, backoff, ok = k.establishStream(ctx, key, backoff) if !ok { return } continue } resp, err := current.Recv() if err != nil { if !shouldRetryWatch(ctx, err) { return } ... (clipped 87 lines) ``` </details></details></td></tr> <tr><td colspan='2'><strong>Ticket Compliance</strong></td></tr> <tr><td>🟡</td> <td> <details> <summary>🎫 <a href=https://github.com/carverauto/serviceradar/issues/1933>#1933</a></summary> <table width='100%'><tbody> <tr><td rowspan=5>🟢</td> <td>Poller settings UI form should expose missing configuration options so users can configure <br>pollers fully.</td></tr> <tr><td>Ensure form supports security configuration (TLS/mTLS/SPIFFE) for poller and connections <br>it uses.</td></tr> <tr><td>Include logging and OpenTelemetry options in poller settings.</td></tr> <tr><td>Allow configuration of agents and their checks within the poller configuration UI.</td></tr> <tr><td>Improve overall UX for configuring poller-related KV and service fields.</td></tr> <tr><td rowspan=1>🔴</td> <td></td></tr> <tr><td rowspan=3>⚪</td> <td>Visual/UI verification that all new fields render correctly and are usable across <br>supported browsers.</td></tr> <tr><td>Validation that JSON headers editor behaves correctly for invalid inputs and user <br>interactions.</td></tr> <tr><td>End-to-end check that saved form data maps to backend schema as expected.</td></tr> </tbody></table> </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=2>🟢</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> <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:** 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=4>⚪</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/1934/files#diff-0c911990aa32d43404f0f23dadc0363ec97ed4ca315592e6c9bd24510e82e06dR120-R141'><strong>Retry Logging</strong></a>: New KV connection retry logic logs attempts and outcomes but it is unclear whether all <br>critical KV-related actions (e.g., seeding configs, PutIfAbsent decisions) are <br>consistently logged with user/action context across the system.<br> <details open><summary>Referred Code</summary> ```go lastErr = err log.Warn(). Err(err). Int("attempt", attempt). Msg("KV connection attempt failed; retrying") wait := baseBackoff << (attempt - 1) if wait > maxBackoff { wait = maxBackoff } select { case <-time.After(wait): case <-ctx.Done(): if ctx.Err() != nil { return nil, ctx.Err() } } if time.Now().After(deadline) { return nil, fmt.Errorf("timed out waiting for KV connection after %d attempts: %w", attempt, lastErr) ... (clipped 1 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><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/1934/files#diff-61358711e980ccf505246fd3915f97cbd3a380e9b66f6fa5aad46749968c5ca3R222-R249'><strong>Error Exposure</strong></a>: User-facing context is not shown here, but added errors (e.g., resolveAgentID and seeding) <br>return detailed messages that might propagate; verify they are not exposed to end users in <br>UIs or APIs.<br> <details open><summary>Referred Code</summary> ```go func resolveAgentID(configPath, current string) (string, error) { candidate := strings.TrimSpace(current) if candidate != "" && candidate != defaultAgentID { return candidate, nil } if envID := strings.TrimSpace(os.Getenv("AGENT_ID")); envID != "" && envID != defaultAgentID { return envID, nil } path := strings.TrimSpace(configPath) if path == "" { return "", fmt.Errorf("agent_id not set and config path unavailable") } payload, err := os.ReadFile(path) if err != nil { return "", fmt.Errorf("read config for agent_id: %w", err) } var stub struct { AgentID string `json:"agent_id"` } if err := json.Unmarshal(payload, &stub); err != nil { ... (clipped 7 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><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/1934/files#diff-61358711e980ccf505246fd3915f97cbd3a380e9b66f6fa5aad46749968c5ca3R188-R217'><strong>Log Sensitivity</strong></a>: Seeding logs include KV keys and file paths which seem safe, but headers and config <br>content fields in UI forms could be sensitive if later logged; ensure no secrets (e.g., <br>OTEL headers) are ever written to logs.<br> <details open><summary>Referred Code</summary> ```go entries, err := os.ReadDir(cfg.CheckersDir) if err != nil { return fmt.Errorf("read checker directory: %w", err) } for _, entry := range entries { if entry.IsDir() || filepath.Ext(entry.Name()) != ".json" { continue } path := filepath.Join(cfg.CheckersDir, entry.Name()) data, err := os.ReadFile(path) if err != nil { log.Warn().Err(err).Str("file", path).Msg("Skipping checker seed; failed reading file") continue } key := fmt.Sprintf("agents/%s/checkers/%s", agentID, entry.Name()) created, err := kvMgr.PutIfAbsent(ctx, key, data, 0) if err != nil { log.Warn().Err(err).Str("kv_key", key).Msg("Failed to seed checker config") ... (clipped 9 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><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/1934/files#diff-a461cf9c9de7dcc94fbb380a8926ad17b741a2707b58a1d0ae76c70fed432484R383-R531'><strong>UI Validation</strong></a>: The new forms accept numerous free-text fields (endpoints, headers JSON, file paths) with <br>minimal validation beyond JSON parse, which may require stronger client/server-side <br>validation and sanitization.<br> <details open><summary>Referred Code</summary> ```tsx <div className="space-y-6"> <div className="grid grid-cols-4 gap-4"> <div> <label className="block text-sm font-medium mb-2">Log Level</label> <select value={config.logging?.level ?? 'info'} onChange={(e) => updateConfig('logging.level', e.target.value)} className="w-full p-2 border border-gray-300 dark:border-gray-600 rounded-md" > <option value="debug">Debug</option> <option value="info">Info</option> <option value="warn">Warn</option> <option value="error">Error</option> </select> </div> <div> <label className="block text-sm font-medium mb-2">Output</label> <select value={config.logging?.output ?? 'stdout'} onChange={(e) => updateConfig('logging.output', e.target.value)} className="w-full p-2 border border-gray-300 dark:border-gray-600 rounded-md" ... (clipped 128 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"> <!-- /compliance --update_compliance=true --> </td></tr></tbody></table> </details>
qodo-code-review[bot] commented 2025-11-11 00:53:09 +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/1934#issuecomment-3514515428
Original created: 2025-11-11T00:53:09Z

PR Code Suggestions

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
PR scope exceeds bug fix

The PR's scope extends beyond the stated UI bug fix, introducing major backend
architectural changes. These include agent-to-KV config seeding, KV connection
retry logic, and resilient configuration watching, which should be reviewed as a
new feature.

Examples:

cmd/agent/main.go [115-117]
	if err := seedCheckerConfigsFromDisk(ctx, bootstrapResult.Manager(), &cfg, *configPath, agentLogger); err != nil {
		agentLogger.Warn().Err(err).Msg("Failed to seed checker configs to KV")
	}
pkg/config/kv_client.go [76-143]
// NewKVManagerFromEnvWithRetry blocks until a KV manager can be created or the configured timeout expires.
func NewKVManagerFromEnvWithRetry(ctx context.Context, role models.ServiceRole, log logger.Logger) (*KVManager, error) {
	if !ShouldUseKVFromEnv() {
		return nil, nil
	}

	if log == nil {
		log = logger.NewTestLogger()
	}


 ... (clipped 58 lines)

Solution Walkthrough:

Before:

// in pkg/config/kv_client.go
func NewKVManagerFromEnv(ctx, role) *KVManager {
  // Returns nil if KV is not configured
  // No retry logic, fails immediately on connection error
  client := createKVClientFromEnv(ctx, role)
  if client == nil {
    return nil
  }
  return &KVManager{client: client}
}

// in pkg/config/kvgrpc/client.go
func (k *Client) Watch(ctx, key) (<-chan []byte, error) {
  // Establishes a stream
  stream, err := k.c.Watch(ctx, &proto.WatchRequest{Key: key})
  // ...
  go func() {
    // Loop receives updates
    // Any error terminates the watch goroutine
  }()
  return ch, nil
}

After:

// in cmd/agent/main.go
func run() error {
  // ...
  // New feature: Agent seeds its checker configs into the KV store
  if err := seedCheckerConfigsFromDisk(...); err != nil {
    agentLogger.Warn().Err(err).Msg("Failed to seed checker configs to KV")
  }
  // ...
}

// in pkg/config/kv_client.go
func NewKVManagerFromEnvWithRetry(ctx, role, log) (*KVManager, error) {
  // Blocks and retries with exponential backoff until KV is available or timeout
  for {
    manager, err := NewKVManagerFromEnv(ctx, role)
    if err == nil && manager != nil {
      return manager, nil
    }
    // ... wait and retry ...
  }
}

// in pkg/config/kvgrpc/client.go
func (k *Client) watchStream(ctx, key, stream, out) {
  // New resilient watch loop
  for {
    // ... receive from stream ...
    if err != nil {
      // If error is retryable, re-establish stream with backoff
      if shouldRetryWatch(ctx, err) {
        current = nil // Mark stream as dead to trigger re-establishment
        continue
      }
      return // Non-retryable error
    }
    // ... send to output channel ...
  }
}

Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies that the PR's scope is much larger than the ticket's description, introducing significant backend architectural changes like KV connection retries and agent config seeding, which are critical to review as new features.

High
Possible issue
Fix race condition in PutIfAbsent
Suggestion Impact:The commit changed PutIfAbsent to call m.client.Create(ctx, key, value, ttl) and handle kv.ErrKeyExists, removing the prior Get+Put sequence and returning success only when the create succeeds atomically.

code diff:

-	_, found, err := m.client.Get(ctx, key)
-	if err != nil {
+	err := m.client.Create(ctx, key, value, ttl)
+	if err != nil {
+		if errors.Is(err, kv.ErrKeyExists) {
+			return false, nil
+		}
 		return false, err
 	}
-	if found {
-		return false, nil
-	}
-
-	return true, m.client.Put(ctx, key, value, ttl)
+
+	return true, nil
 }

To fix a race condition in PutIfAbsent, replace the non-atomic Get followed by
Put with a single, atomic "create" or "put-if-absent" operation at the KV store
client level.

pkg/config/kv_client.go [263-271]

-	_, found, err := m.client.Get(ctx, key)
+	// This assumes the kv.KVStore interface is extended with a Create method.
+	// The Create method should atomically create the key only if it does not exist.
+	// It should return a specific error (e.g., kv.ErrKeyExists) if the key already exists.
+	err := m.client.Create(ctx, key, value, ttl)
 	if err != nil {
+		if errors.Is(err, kv.ErrKeyExists) { // Assuming a standard error for this case
+			return false, nil
+		}
 		return false, err
 	}
-	if found {
-		return false, nil
-	}
 
-	return true, m.client.Put(ctx, key, value, ttl)
+	return true, nil

[Suggestion processed]

Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a critical check-then-act race condition in PutIfAbsent, which could lead to data overwrites in a concurrent environment, violating the function's contract.

High
General
Handle database errors when collecting targets
Suggestion Impact:The commit added error checks and warning logs for failures from ListPollers and ListAgentsWithPollers, instead of silently proceeding only when err == nil.

code diff:

 	if s.dbService != nil {
-		if pollerIDs, err := s.dbService.ListPollers(ctx); err == nil {
+		if pollerIDs, err := s.dbService.ListPollers(ctx); err != nil {
+			s.logger.Warn().Err(err).Msg("failed to list pollers for remote watcher targets")
+		} else {
 			for _, pollerID := range pollerIDs {
 				if pollerID == "" {
 					continue
@@ -325,7 +327,9 @@
 			}
 		}
 
-		if agents, err := s.dbService.ListAgentsWithPollers(ctx); err == nil {
+		if agents, err := s.dbService.ListAgentsWithPollers(ctx); err != nil {
+			s.logger.Warn().Err(err).Msg("failed to list agents for remote watcher targets")
+		} else {
 			for _, agent := range agents {
 				if agent.AgentID == "" {
 					continue

Add error handling and logging for the s.dbService.ListPollers and
s.dbService.ListAgentsWithPollers calls to prevent silent failures and improve
debuggability.

pkg/core/api/auth.go [318-342]

 	if s.dbService != nil {
-		if pollerIDs, err := s.dbService.ListPollers(ctx); err == nil {
+		pollerIDs, err := s.dbService.ListPollers(ctx)
+		if err != nil {
+			s.logger.Warn().Err(err).Msg("failed to list pollers for remote watcher targets")
+		} else {
 			for _, pollerID := range pollerIDs {
 				if pollerID == "" {
 					continue
 				}
 				addTarget("poller", pollerID)
 			}
 		}
 
-		if agents, err := s.dbService.ListAgentsWithPollers(ctx); err == nil {
+		agents, err := s.dbService.ListAgentsWithPollers(ctx)
+		if err != nil {
+			s.logger.Warn().Err(err).Msg("failed to list agents for remote watcher targets")
+		} else {
 			for _, agent := range agents {
 				if agent.AgentID == "" {
 					continue
 				}
 				addTarget("agent", agent.AgentID)
 				for _, desc := range agentDescriptors {
 					if desc.Name == "agent" {
 						continue
 					}
 					addTarget(desc.Name, agent.AgentID)
 				}
 			}
 		}
 	}

[Suggestion processed]

Suggestion importance[1-10]: 7

__

Why: The suggestion correctly points out that database errors are ignored, and proposes adding logging to improve observability and aid debugging, which is a valuable improvement for robustness.

Medium
  • Update
Imported GitHub PR comment. Original author: @qodo-code-review[bot] Original URL: https://github.com/carverauto/serviceradar/pull/1934#issuecomment-3514515428 Original created: 2025-11-11T00:53:09Z --- ## PR Code Suggestions ✨ <!-- dea4a76 --> 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>PR scope exceeds bug fix</summary> ___ **The PR's scope extends beyond the stated UI bug fix, introducing major backend <br>architectural changes. These include agent-to-KV config seeding, KV connection <br>retry logic, and resilient configuration watching, which should be reviewed as a <br>new feature.** ### Examples: <details> <summary> <a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-61358711e980ccf505246fd3915f97cbd3a380e9b66f6fa5aad46749968c5ca3R115-R117">cmd/agent/main.go [115-117]</a> </summary> ```go if err := seedCheckerConfigsFromDisk(ctx, bootstrapResult.Manager(), &cfg, *configPath, agentLogger); err != nil { agentLogger.Warn().Err(err).Msg("Failed to seed checker configs to KV") } ``` </details> <details> <summary> <a href="https://github.com/carverauto/serviceradar/pull/1934/files#diff-0c911990aa32d43404f0f23dadc0363ec97ed4ca315592e6c9bd24510e82e06dR76-R143">pkg/config/kv_client.go [76-143]</a> </summary> ```go // NewKVManagerFromEnvWithRetry blocks until a KV manager can be created or the configured timeout expires. func NewKVManagerFromEnvWithRetry(ctx context.Context, role models.ServiceRole, log logger.Logger) (*KVManager, error) { if !ShouldUseKVFromEnv() { return nil, nil } if log == nil { log = logger.NewTestLogger() } ... (clipped 58 lines) ``` </details> ### Solution Walkthrough: #### Before: ```go // in pkg/config/kv_client.go func NewKVManagerFromEnv(ctx, role) *KVManager { // Returns nil if KV is not configured // No retry logic, fails immediately on connection error client := createKVClientFromEnv(ctx, role) if client == nil { return nil } return &KVManager{client: client} } // in pkg/config/kvgrpc/client.go func (k *Client) Watch(ctx, key) (<-chan []byte, error) { // Establishes a stream stream, err := k.c.Watch(ctx, &proto.WatchRequest{Key: key}) // ... go func() { // Loop receives updates // Any error terminates the watch goroutine }() return ch, nil } ``` #### After: ```go // in cmd/agent/main.go func run() error { // ... // New feature: Agent seeds its checker configs into the KV store if err := seedCheckerConfigsFromDisk(...); err != nil { agentLogger.Warn().Err(err).Msg("Failed to seed checker configs to KV") } // ... } // in pkg/config/kv_client.go func NewKVManagerFromEnvWithRetry(ctx, role, log) (*KVManager, error) { // Blocks and retries with exponential backoff until KV is available or timeout for { manager, err := NewKVManagerFromEnv(ctx, role) if err == nil && manager != nil { return manager, nil } // ... wait and retry ... } } // in pkg/config/kvgrpc/client.go func (k *Client) watchStream(ctx, key, stream, out) { // New resilient watch loop for { // ... receive from stream ... if err != nil { // If error is retryable, re-establish stream with backoff if shouldRetryWatch(ctx, err) { current = nil // Mark stream as dead to trigger re-establishment continue } return // Non-retryable error } // ... send to output channel ... } } ``` <details><summary>Suggestion importance[1-10]: 9</summary> __ Why: The suggestion correctly identifies that the PR's scope is much larger than the ticket's description, introducing significant backend architectural changes like KV connection retries and agent config seeding, which are critical to review as new features. </details></details></td><td align=center>High </td></tr><tr><td rowspan=1>Possible issue</td> <td> <details><summary>✅ <s>Fix race condition in PutIfAbsent<!-- not_implemented --></s></summary> ___ <details><summary><b>Suggestion Impact:</b></summary>The commit changed PutIfAbsent to call m.client.Create(ctx, key, value, ttl) and handle kv.ErrKeyExists, removing the prior Get+Put sequence and returning success only when the create succeeds atomically. code diff: ```diff - _, found, err := m.client.Get(ctx, key) - if err != nil { + err := m.client.Create(ctx, key, value, ttl) + if err != nil { + if errors.Is(err, kv.ErrKeyExists) { + return false, nil + } return false, err } - if found { - return false, nil - } - - return true, m.client.Put(ctx, key, value, ttl) + + return true, nil } ``` </details> ___ **To fix a race condition in <code>PutIfAbsent</code>, replace the non-atomic <code>Get</code> followed by <br><code>Put</code> with a single, atomic "create" or "put-if-absent" operation at the KV store <br>client level.** [pkg/config/kv_client.go [263-271]](https://github.com/carverauto/serviceradar/pull/1934/files#diff-0c911990aa32d43404f0f23dadc0363ec97ed4ca315592e6c9bd24510e82e06dR263-R271) ```diff - _, found, err := m.client.Get(ctx, key) + // This assumes the kv.KVStore interface is extended with a Create method. + // The Create method should atomically create the key only if it does not exist. + // It should return a specific error (e.g., kv.ErrKeyExists) if the key already exists. + err := m.client.Create(ctx, key, value, ttl) if err != nil { + if errors.Is(err, kv.ErrKeyExists) { // Assuming a standard error for this case + return false, nil + } return false, err } - if found { - return false, nil - } - return true, m.client.Put(ctx, key, value, ttl) + return true, nil ``` `[Suggestion processed]` <details><summary>Suggestion importance[1-10]: 9</summary> __ Why: The suggestion correctly identifies a critical check-then-act race condition in `PutIfAbsent`, which could lead to data overwrites in a concurrent environment, violating the function's contract. </details></details></td><td align=center>High </td></tr><tr><td rowspan=1>General</td> <td> <details><summary>✅ <s>Handle database errors when collecting targets</s></summary> ___ <details><summary><b>Suggestion Impact:</b></summary>The commit added error checks and warning logs for failures from ListPollers and ListAgentsWithPollers, instead of silently proceeding only when err == nil. code diff: ```diff if s.dbService != nil { - if pollerIDs, err := s.dbService.ListPollers(ctx); err == nil { + if pollerIDs, err := s.dbService.ListPollers(ctx); err != nil { + s.logger.Warn().Err(err).Msg("failed to list pollers for remote watcher targets") + } else { for _, pollerID := range pollerIDs { if pollerID == "" { continue @@ -325,7 +327,9 @@ } } - if agents, err := s.dbService.ListAgentsWithPollers(ctx); err == nil { + if agents, err := s.dbService.ListAgentsWithPollers(ctx); err != nil { + s.logger.Warn().Err(err).Msg("failed to list agents for remote watcher targets") + } else { for _, agent := range agents { if agent.AgentID == "" { continue ``` </details> ___ **Add error handling and logging for the <code>s.dbService.ListPollers</code> and <br><code>s.dbService.ListAgentsWithPollers</code> calls to prevent silent failures and improve <br>debuggability.** [pkg/core/api/auth.go [318-342]](https://github.com/carverauto/serviceradar/pull/1934/files#diff-61eb09279471ca59a1b57a306f0ad05988a8cb39eca163b32bfb86c53f8a553eR318-R342) ```diff if s.dbService != nil { - if pollerIDs, err := s.dbService.ListPollers(ctx); err == nil { + pollerIDs, err := s.dbService.ListPollers(ctx) + if err != nil { + s.logger.Warn().Err(err).Msg("failed to list pollers for remote watcher targets") + } else { for _, pollerID := range pollerIDs { if pollerID == "" { continue } addTarget("poller", pollerID) } } - if agents, err := s.dbService.ListAgentsWithPollers(ctx); err == nil { + agents, err := s.dbService.ListAgentsWithPollers(ctx) + if err != nil { + s.logger.Warn().Err(err).Msg("failed to list agents for remote watcher targets") + } else { for _, agent := range agents { if agent.AgentID == "" { continue } addTarget("agent", agent.AgentID) for _, desc := range agentDescriptors { if desc.Name == "agent" { continue } addTarget(desc.Name, agent.AgentID) } } } } ``` `[Suggestion processed]` <details><summary>Suggestion importance[1-10]: 7</summary> __ Why: The suggestion correctly points out that database errors are ignored, and proposes adding logging to improve observability and aid debugging, which is a valuable improvement for robustness. </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!2409
No description provided.