yuzu

diagnostics

What it doesAgent diagnostics — log level, certificates, connection info
Version0.2.0
KindCollector · read-only · gathered (device.diagnostics.log_level, device.diagnostics.certificates, device.diagnostics.connection_info)
PlatformsWindows ✅ · macOS ✅ · Linux ✅
Actionscertificates (definition device.diagnostics.certificates) · connection_info (definition device.diagnostics.connection_info) · log_level (definition device.diagnostics.log_level)
Securitylog_level: securable Inventory · operation Read · risk Low · dispatch ReadOnly · approval gate None; certificates: securable Security · operation Read · risk Medium · dispatch ReadOnly · approval gate None; connection_info: securable PluginSecret · operation Read · risk Medium · dispatch ReadOnly · approval gate None
Rolesexecute: log_level: endpoint-admin, endpoint-operator; certificates: endpoint-admin; connection_info: endpoint-admin · author: content-author

How it works

All three actions are pure reads against the agent’s in-process config store (yuzu_ctx_get_config, wrapped by PluginContext::get_config); none of them makes an OS call, opens a socket, or spawns a process. log_level reads a single key, agent.log_level, defaulting to "info" when unset. certificates reads three configured paths (tls.ca_cert, tls.client_cert, tls.client_key) and stats each one with std::filesystem::exists — it reports path and existence only, never file contents. connection_info reads eight config keys covering server address, TLS-enabled flag, session ID, gRPC channel state, reconnect count, latency, and connection timestamps, and additionally computes uptime_seconds from agent.start_time_epoch at read time. Every config lookup that returns empty falls back to a fixed placeholder ("info", "(not configured)", "(none)", "unknown", "0", "false") rather than omitting the field.

The originating spec expected diagnostics to include a state-changing action; a full read of the shipped code found all three actions to be pure reports with no host, config, or filesystem write anywhere in the plugin, so every row is classified ReadOnly/None against the code as found, not the spec’s expectation.

flowchart LR
  OP[Operator / workflow] --> SRV[Server<br/>authz: Inventory/Security/PluginSecret . Read]
  SRV -- gRPC mTLS --> HOST[Agent plugin host] --> EX[diagnostics.execute]
  EX --> WIN[Windows leg<br/>in-process agent config]
  EX --> MAC[macOS leg<br/>in-process agent config]
  EX --> LIN[Linux leg<br/>in-process agent config]
  WIN & MAC & LIN --> ROWS[key/value rows,<br/>no typed status] --> RS[(ResponseStore)] --> API[REST /api/responses]

OS capability

ActionWindowsmacOSLinux
certificates✅ supported · rung 1 · in-process agent config (tls.*_cert/tls.client_key) + std::filesystem::exists✅ supported · rung 1 · in-process agent config (tls.*_cert/tls.client_key) + std::filesystem::exists✅ supported · rung 1 · in-process agent config (tls.*_cert/tls.client_key) + std::filesystem::exists
connection_info✅ supported · rung 1 · in-process agent config (agent.server_address/tls.enabled/*)✅ supported · rung 1 · in-process agent config (agent.server_address/tls.enabled/*)✅ supported · rung 1 · in-process agent config (agent.server_address/tls.enabled/*)
log_level✅ supported · rung 1 · in-process agent config (agent.log_level)✅ supported · rung 1 · in-process agent config (agent.log_level)✅ supported · rung 1 · in-process agent config (agent.log_level)

Privileges and prerequisites

OSRuns asExtra grant neededMeasuredIf the read is refused
Windowsagent service account (LocalSystem today, #1442)None — no OS call; the config store is read in-process.2026-09-07, bare-metal, SYSTEMn/a — an unset config key returns the plugin’s fixed placeholder, not an error
macOSagent daemon (root today per docs/agent-privilege-model.md)None.2026-09-07, bare-metal, euid 501 (unprivileged — the capture ran outside the real daemon identity)n/a — same placeholder fallback
Linuxagent daemon (yuzu user, unprivileged, per docs/agent-privilege-model.md)None.2026-09-06, container, euid 0n/a — same placeholder fallback

No external binaries, no subprocesses, no network access. The only filesystem touch is certificates’ std::filesystem::exists stat of the three configured cert/key paths (agents/plugins/diagnostics/src/diagnostics_plugin.cpp:144); a stat failure is swallowed into exists=false via the discarded std::error_code, never surfaced as a distinct error.

Data contract

Inputs

No action takes parameters.

Outputs

One key|value row per field via write_output() — not a fixed-width pipe schema like most plugins, but a variable-length sequence of labelled rows per call (agents/plugins/diagnostics/src/diagnostics_plugin.cpp:10-12). certificates additionally prefixes each row with the literal discriminator cert. There is no empty-result placeholder row: every action always emits its full fixed set of rows, substituting a fallback string ("(not configured)", "(none)", "unknown", "0", "false", "info") for any config key that is unset — - is never used as a placeholder in this plugin.

device.diagnostics.certificates — cert_type|path|exists

FieldTypeValuesAvailableExampleDescription
cert_typestringca_cert client_cert client_keyWindows, Linux, macOSca_certWhich certificate/key slot this row reports.
pathstring-Windows, Linux, macOS(not configured)Filesystem path configured for this slot’s config key, or the literal “(not configured)” when unset. Values: free text (path) or “(not configured)”.
existsbool-Windows, Linux, macOSfalseWhether std::filesystem::exists() found a file at path; always false when path is unconfigured.

device.diagnostics.connection_info — server_address|tls_enabled|session_id|grpc_channel_state|reconnect_count|latency_ms|uptime_seconds|connected_since

FieldTypeValuesAvailableExampleDescription
server_addressstring-Windows, Linux, macOS(not configured)gRPC server endpoint the agent is configured to connect to, or the literal “(not configured)” when unset. Values: free text (host:port) or “(not configured)”.
tls_enabledbool-Windows, Linux, macOSfalseWhether mTLS is enabled for the agent’s server connection, read from tls.enabled; false when unset.
session_idstring-Windows, Linux, macOS(none)Current gRPC session identifier (the live agent session credential), or the literal “(none)” when there is no active session. Values: free text or “(none)”.
grpc_channel_statestring-Windows, Linux, macOSunknownCurrent gRPC channel connectivity state, read verbatim from agent.grpc_channel_state, or “unknown” when unset. Values: free text (e.g. READY, CONNECTING, TRANSIENT_FAILURE) or “unknown”.
reconnect_countint32-Windows, Linux, macOS0Number of times the agent has reconnected to the server since startup; 0 when unset. Values: integer >= 0.
latency_msint32-Windows, Linux, macOS0Last measured round-trip latency to the server in milliseconds; 0 when unset. Values: integer >= 0.
uptime_secondsint64-Windows, Linux, macOS0Seconds since agent.start_time_epoch, computed at read time; 0 when start_time_epoch is unset or unparsable. Values: integer >= 0.
connected_sincestring-Windows, Linux, macOS0Unix epoch timestamp (as a string) of when the current connection was established, or “0” when unset. Values: free text (epoch seconds) or “0”.

device.diagnostics.log_level — log_level

FieldTypeValuesAvailableExampleDescription
log_levelstringtrace debug info warn error critical offWindows, Linux, macOSinfoThe agent’s current spdlog log level, read verbatim from agent.log_level.

Result status

This plugin does not set a typed result status; the agent records UNDECLARED and every sample shows UNDECLARED / UNKNOWN /.

Where the data goes

Sample output

Windows — captured: windows Microsoft Windows NT 10.0.26200.0 x64 · bare-metal · 2026-09-07 · SYSTEM · leg-hash c768172a2281

== action=log_level
log_level|info
[result_status] UNDECLARED / UNKNOWN

== action=certificates
cert|ca_cert|(not configured)|false
cert|client_cert|(not configured)|false
cert|client_key|(not configured)|false
[result_status] UNDECLARED / UNKNOWN

== action=connection_info
server_address|(not configured)
tls_enabled|false
session_id|(none)
grpc_channel_state|unknown
reconnect_count|0
latency_ms|0
uptime_seconds|0
connected_since|0
[result_status] UNDECLARED / UNKNOWN

macOS — captured: macos macOS 26.6.2 arm64 · bare-metal · 2026-09-07 · euid 501 (jsmith) · leg-hash c768172a2281

== action=log_level
log_level|info
[result_status] UNDECLARED / UNKNOWN

== action=certificates
cert|ca_cert|(not configured)|false
cert|client_cert|(not configured)|false
cert|client_key|(not configured)|false
[result_status] UNDECLARED / UNKNOWN

== action=connection_info
server_address|(not configured)
tls_enabled|false
session_id|(none)
grpc_channel_state|unknown
reconnect_count|0
latency_ms|0
uptime_seconds|0
connected_since|0
[result_status] UNDECLARED / UNKNOWN

Linux — captured: linux Debian GNU/Linux 13 (trixie) aarch64 · container · 2026-09-06 · euid 0 · leg-hash c768172a2281

== action=log_level
log_level|info
[result_status] UNDECLARED / UNKNOWN

== action=certificates
cert|ca_cert|(not configured)|false
cert|client_cert|(not configured)|false
cert|client_key|(not configured)|false
[result_status] UNDECLARED / UNKNOWN

== action=connection_info
server_address|(not configured)
tls_enabled|false
session_id|(none)
grpc_channel_state|unknown
reconnect_count|0
latency_ms|0
uptime_seconds|0
connected_since|0
[result_status] UNDECLARED / UNKNOWN

Caveats and known gaps

  1. All three captures are identical across every OS because none reflects a configured agent. The capture driver loads the plugin via PluginHandle::load + LocalDispatcher::run without calling init() (per the capture methodology), so g_ctx stays nullptr for the whole run; yuzu_ctx_get_config(nullptr, key) returns nullptr unconditionally (agents/core/src/agent.cpp:559-560), and every field falls back to its hardcoded default. A real agent with a populated config store would show real values, not this placeholder set.
  2. No typed result status. The plugin never calls set_result_status; every capture reads UNDECLARED / UNKNOWN / regardless of platform or outcome. There is no way to distinguish “config genuinely unset” from “no host config was reachable” from the status field alone.
  3. certificates’ filesystem stat swallows its own error code. std::filesystem::exists(path_str, ec) takes an std::error_code output parameter but the plugin never inspects it (agents/plugins/diagnostics/src/diagnostics_plugin.cpp:144), so a permission-denied stat and a genuinely-missing file both read as exists=false.
  4. connection_info.session_id carries the live agent session credential. This is why the action is classified under the PluginSecret securable rather than Inventory (server/core/src/capability_decls/plugin_action_catalogue_b.hpp:685-687); do not relax its securable to match the other two actions.
  5. log_level is not validated against the spdlog enum. The plugin returns whatever string sits at agent.log_level verbatim (or "info" if unset) — a misconfigured value would pass through unchanged rather than being rejected or normalized.

Source and tests