Skip to content

fix(gateway-status): downgrade SecretRef warning when gateway probe succeeds#45549

Closed
reed1898 wants to merge 1 commit intoopenclaw:mainfrom
reed1898:fix/gateway-status-secretref-false-warning
Closed

fix(gateway-status): downgrade SecretRef warning when gateway probe succeeds#45549
reed1898 wants to merge 1 commit intoopenclaw:mainfrom
reed1898:fix/gateway-status-secretref-false-warning

Conversation

@reed1898
Copy link
Copy Markdown
Contributor

Problem

When the gateway is running and healthy, openclaw gateway status still shows a Warning: about unresolved SecretRef for gateway.auth.token. This is a false positive — the secret (e.g., env:GATEWAY_TOKEN) is resolved at gateway runtime but is not readable from the CLI process context (the env var may only be set in the gateway's LaunchAgent/systemd environment).

This confuses users into thinking their auth config is broken when everything is actually working fine.

Fix

  • When the gateway probe succeeds (probe.ok === true), SecretRef diagnostics are downgraded from auth_secretref_unresolved (Warning) to auth_secretref_cli_only (Note)
  • The note message includes (gateway is healthy; secrets are resolved at runtime) for clarity
  • When the gateway probe fails, the original auth_secretref_unresolved warning is preserved — this is a genuine problem
  • Warning and Note sections are rendered separately: warnings in warn color, notes in muted color

Tests

  • Updated existing test to verify the downgraded code when probe succeeds
  • Added new test: keeps auth_secretref_unresolved code when gateway probe fails — verifies warnings are preserved for unhealthy gateways

All 13 gateway-status tests pass locally.

When the gateway probe succeeds, the CLI-side SecretRef resolution
diagnostic is misleading — the secret is resolved at runtime but
the CLI process cannot read it (e.g. env var only available to the
gateway daemon). This commit:

- Introduces auth_secretref_cli_only code for healthy-gateway cases
- Displays these diagnostics as muted 'Note:' instead of 'Warning:'
- Preserves auth_secretref_unresolved for genuinely broken gateways
- Adds test coverage for both healthy and unhealthy probe scenarios
@openclaw-barnacle openclaw-barnacle bot added commands Command implementations size: S labels Mar 14, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 14, 2026

Greptile Summary

This PR addresses a false-positive Warning: about an unresolved SecretRef that appeared in openclaw gateway status even when the gateway was running healthily. The fix is well-targeted: when probe.ok === true, the auth_secretref_unresolved diagnostic is downgraded to auth_secretref_cli_only (rendered as a muted "Note:" in human output), while the original warning is preserved when the probe fails.

Changes:

  • gateway-status.ts: diagnostic severity is now gated on result.probe.ok; human-readable rendering splits actual warnings (theme.warn) from informational notes (theme.muted).
  • gateway-status.test.ts: existing test updated to assert the new auth_secretref_cli_only code; a new test added to confirm warnings are preserved for failing probes.

Points to consider:

  • The JSON (--json) output still routes downgraded notes into the warnings array. Programmatic consumers (e.g. CI scripts) that check warnings.length > 0 will still react to auth_secretref_cli_only entries even though the gateway is healthy — consider adding a separate notes field in the JSON envelope.
  • The string "auth_secretref_cli_only" is hardcoded in three places; a named constant would guard against silent typo bugs.

Confidence Score: 4/5

  • Safe to merge; the core logic change is correct and well-tested, with two minor style improvements recommended.
  • The probe-gated severity downgrade is logically sound and both the healthy and unhealthy paths are covered by tests. The two concerns flagged (JSON output inconsistency and magic string duplication) are style-level and non-blocking, but the JSON issue could bite CI consumers if left unaddressed.
  • Pay attention to src/commands/gateway-status.ts around the JSON serialisation block to decide whether auth_secretref_cli_only items should be separated from true warnings in the machine-readable output.

Comments Outside Diff (1)

  1. src/commands/gateway-status.ts, line 250-260 (link)

    warnings array in JSON output includes downgraded notes

    The human-readable output correctly separates actual warnings from notes, but the JSON output (--json) still lumps both auth_secretref_unresolved and auth_secretref_cli_only entries into the same warnings array (line 259). Any programmatic consumer that does a simple check like if (result.warnings.length > 0) { alertOrExit(); } — e.g., a CI/CD pipeline script — will still fire on auth_secretref_cli_only items even though the gateway is healthy, defeating the purpose of the downgrade.

    Consider one of:

    • Adding a sibling notes array to the JSON envelope and routing auth_secretref_cli_only items there instead of into warnings.
    • Or, at minimum, explicitly documenting (in the JSON schema / API docs) that consumers must filter by code and that codes ending in _cli_only are non-actionable.
    // Example: separate field approach
    {
      warnings: warnings.filter(w => w.code !== "auth_secretref_cli_only"),
      notes: warnings.filter(w => w.code === "auth_secretref_cli_only"),
      ...
    }
    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: src/commands/gateway-status.ts
    Line: 250-260
    
    Comment:
    **`warnings` array in JSON output includes downgraded notes**
    
    The human-readable output correctly separates actual warnings from notes, but the JSON output (`--json`) still lumps both `auth_secretref_unresolved` and `auth_secretref_cli_only` entries into the same `warnings` array (line 259). Any programmatic consumer that does a simple check like `if (result.warnings.length > 0) { alertOrExit(); }` — e.g., a CI/CD pipeline script — will still fire on `auth_secretref_cli_only` items even though the gateway is healthy, defeating the purpose of the downgrade.
    
    Consider one of:
    - Adding a sibling `notes` array to the JSON envelope and routing `auth_secretref_cli_only` items there instead of into `warnings`.
    - Or, at minimum, explicitly documenting (in the JSON schema / API docs) that consumers must filter by `code` and that codes ending in `_cli_only` are non-actionable.
    
    ```ts
    // Example: separate field approach
    {
      warnings: warnings.filter(w => w.code !== "auth_secretref_cli_only"),
      notes: warnings.filter(w => w.code === "auth_secretref_cli_only"),
      ...
    }
    ```
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/commands/gateway-status.ts
Line: 250-260

Comment:
**`warnings` array in JSON output includes downgraded notes**

The human-readable output correctly separates actual warnings from notes, but the JSON output (`--json`) still lumps both `auth_secretref_unresolved` and `auth_secretref_cli_only` entries into the same `warnings` array (line 259). Any programmatic consumer that does a simple check like `if (result.warnings.length > 0) { alertOrExit(); }` — e.g., a CI/CD pipeline script — will still fire on `auth_secretref_cli_only` items even though the gateway is healthy, defeating the purpose of the downgrade.

Consider one of:
- Adding a sibling `notes` array to the JSON envelope and routing `auth_secretref_cli_only` items there instead of into `warnings`.
- Or, at minimum, explicitly documenting (in the JSON schema / API docs) that consumers must filter by `code` and that codes ending in `_cli_only` are non-actionable.

```ts
// Example: separate field approach
{
  warnings: warnings.filter(w => w.code !== "auth_secretref_cli_only"),
  notes: warnings.filter(w => w.code === "auth_secretref_cli_only"),
  ...
}
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/commands/gateway-status.ts
Line: 235-318

Comment:
**Magic string `"auth_secretref_cli_only"` repeated in three places**

The string `"auth_secretref_cli_only"` is hardcoded at line 236 (push), line 317 (filter `!==`), and line 318 (filter `===`). A one-character typo in any of the three will silently break the separation logic — notes would appear as warnings or vice-versa, with no compile-time or runtime error. Extracting it to a local or module-level constant eliminates the risk.

```ts
const AUTH_SECRETREF_CLI_ONLY = "auth_secretref_cli_only";

// line ~236
code: AUTH_SECRETREF_CLI_ONLY,

// lines ~317-318
const actualWarnings = warnings.filter((w) => w.code !== AUTH_SECRETREF_CLI_ONLY);
const infoNotes      = warnings.filter((w) => w.code === AUTH_SECRETREF_CLI_ONLY);
```

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: 6ad2acb

Comment on lines 235 to +318
@@ -304,13 +314,22 @@ export async function gatewayStatusCommand(
);
runtime.log(colorize(rich, theme.muted, `Probe budget: ${overallTimeoutMs}ms`));

if (warnings.length > 0) {
const actualWarnings = warnings.filter((w) => w.code !== "auth_secretref_cli_only");
const infoNotes = warnings.filter((w) => w.code === "auth_secretref_cli_only");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Magic string "auth_secretref_cli_only" repeated in three places

The string "auth_secretref_cli_only" is hardcoded at line 236 (push), line 317 (filter !==), and line 318 (filter ===). A one-character typo in any of the three will silently break the separation logic — notes would appear as warnings or vice-versa, with no compile-time or runtime error. Extracting it to a local or module-level constant eliminates the risk.

const AUTH_SECRETREF_CLI_ONLY = "auth_secretref_cli_only";

// line ~236
code: AUTH_SECRETREF_CLI_ONLY,

// lines ~317-318
const actualWarnings = warnings.filter((w) => w.code !== AUTH_SECRETREF_CLI_ONLY);
const infoNotes      = warnings.filter((w) => w.code === AUTH_SECRETREF_CLI_ONLY);
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/commands/gateway-status.ts
Line: 235-318

Comment:
**Magic string `"auth_secretref_cli_only"` repeated in three places**

The string `"auth_secretref_cli_only"` is hardcoded at line 236 (push), line 317 (filter `!==`), and line 318 (filter `===`). A one-character typo in any of the three will silently break the separation logic — notes would appear as warnings or vice-versa, with no compile-time or runtime error. Extracting it to a local or module-level constant eliminates the risk.

```ts
const AUTH_SECRETREF_CLI_ONLY = "auth_secretref_cli_only";

// line ~236
code: AUTH_SECRETREF_CLI_ONLY,

// lines ~317-318
const actualWarnings = warnings.filter((w) => w.code !== AUTH_SECRETREF_CLI_ONLY);
const infoNotes      = warnings.filter((w) => w.code === AUTH_SECRETREF_CLI_ONLY);
```

How can I resolve this? If you propose a fix, please make it concise.

@joshavant
Copy link
Copy Markdown
Contributor

Thanks for the PR, @reed1898.

Closing this as superseded by #47794.

How it relates to your PR:

  • Your change targeted the right core issue (suppressing false-positive SecretRef warning output when probe succeeds).
  • secrets: harden read-only SecretRef command paths and diagnostics #47794 includes that behavior, and expands the same fix line holistically across related read-only SecretRef surfaces (gateway/daemon status parity, doctor/status/security-audit degrade-safe behavior, and regression coverage in one integrated pass).

Appreciate your contribution and the direction you pushed here.

@joshavant joshavant closed this Mar 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commands Command implementations size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants