Skip to content
Back to skills

Ovstorage Operator Debug Broker

ASecurity

Use when triaging a misbehaving ovstorage-broker - covers startup failures, authz denies, listener authn mismatches, streaming write aborts, reload misfires, and drain hangs.

  • 15 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 19, 2026
ai-agentsrustgobashdebuggingbackend

Works with

  • cli

Security analysis

A100/100

Scanned October 19, 2026

npx -y skills add NVIDIA-Omniverse/ovstorage --skill ovstorage-operator-debug-broker --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ovstorage Operator Debug Broker?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Ovstorage Operator Debug Broker
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/nvidia-omniverse-ovstorage-operator-debug-broker/badge)](https://www.skillsdirectory.com/skills/nvidia-omniverse-ovstorage-operator-debug-broker)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: ovstorage-operator-debug-broker
description: Use when triaging a misbehaving ovstorage-broker - covers startup failures, authz denies, listener authn mismatches, streaming write aborts, reload misfires, and drain hangs.
license: CC-BY-4.0
version: "0.1.0"
author: NVIDIA Omniverse
tags: [ovstorage, broker, debugging]
tools: [Read, Bash]
compatibility: Requires access to broker logs, metrics, configuration, and operator-approved diagnostic commands. Credentials are user-supplied.
---

# Debug the Broker

## Goal

Triage a misbehaving broker using the typed errors, metric labels,
and tracing fields the daemon emits. The broker fails closed by
design; most live-incident classes surface as a typed error before
any backend dispatch.

## Recipe

1. Read
   [`docs/public/broker-operator/README.md`](../../docs/public/broker-operator/README.md)
   § *Debug runbook* for the structured walkthrough.
2. For startup failures, run
   `cargo run -p ovstorage-cli -- list-routes --config /etc/ovstorage/broker.toml`
   against the broker's config. The same TOML validator the daemon
   runs at startup will report bad routes, unresolvable secret
   refs, and invalid listener authn config without binding any
   sockets.
3. For authz denies, look at the tracing output for
   `broker_authz_decisions_total{outcome="deny"}`. The deny path
   threads the plugin's `reason` and `explanation` into the gRPC
   `PermissionDenied` message; the `explanation` is typically a
   stable rule id from the built-in policy evaluator.
4. For `PolicyEpochStale` errors, the request was stamped with a
   pre-reload epoch. Nothing in the SDK refreshes and retries it:
   it reaches the caller as `FailedPrecondition` (HTTP 409), which
   the caller re-issues itself against the reloaded policy.
5. For listener authn failures (`Unauthenticated`), confirm the
   mode matches what your callers send:
   - `jwt_verify` mode: bearer JWT against the configured
     `issuer` / `audience` / `jwks_url`. JWKS is cached
     5 minutes; an unknown `kid` triggers one refetch before
     `Unauthenticated`.
   - `peer_cred` mode: UDS / npipe only. Invalid on TCP
     listeners.
   - `trusted_*` modes: only on `trusted_proxy = true` listeners
     with `trusted_peers` CIDR allow-list.
   - `mtls`: reserved; startup fails with `Unsupported` if
     configured.
6. For "broker is up but no routes are visible," check
   `[[connections]]` blocks: backends register at startup; a
   missing or misnamed plugin manifest fails startup. Confirm
   `OVSTORAGE_PLUGIN_DIR` is set and readable. Remember that
   `list-routes` shows only roots marked `visible`: the broker carries a
   `hidden` root to clients marked hidden, and the client keeps it routable
   without listing it. A `suppressed` root is absent from the wire and a direct
   caller receives `NoRoute`, as does an address whose scheme is not in
   `anonymous_fallback_schemes` when no connection serves it. A granted scheme
   reaches clients as a hidden `s3:///` root, and a brokered client honours it
   only when its own `[ovstorage.layers.broker]` table grants the scheme too.
7. For streaming-write issues (slow, corrupted, aborted),
   distinguish:
   - **Graceful EOF** (`Ok(None)` from the inbound stream) —
     broker commits with the chunks received.
   - **RST_STREAM(CANCEL)** (`Err(status)` with
     `status.code() == Cancelled`) — broker aborts with
     `Status::cancelled`. Look for `broker.write` spans
     ending in `Cancelled` to identify these.
   - Inline upload is bounded by `WRITE_BODY_BYTE_CAP` (64 MiB)
     after authz. Larger writes need the redirect branch (S3
     multipart, GCS resumable, etc.); the plugin must mint
     redirects via `WriteStep::Redirects`.
8. For lifecycle issues:
   - `broker_lifecycle_events_total{event="reload_failed"}`
     increments on validation failure; old broker stays live.
   - `broker_policy_epoch_advances_total` increments on
     successful reload.
   - Drain hangs: tune `drain_timeout` (default
     `DEFAULT_DRAIN_TIMEOUT`). A wedged plugin / upstream
     pushes the broker past the deadline and forces truncated
     in-flight RPCs.

## Common live-incident classes

- **Cert expired.** TCP+TLS handshake fails; rotate via SIGHUP
  (Unix) or process restart (Windows). Cert hot-reload is not
  implemented.
- **JWKS unreachable.** `Unauthenticated` for every `jwt_verify`
  request. Check the IdP's reachability from the broker host.
- **Authorization latency.** The built-in policy evaluator is local and
  synchronous; rising RPC latency points to listener authentication, storage
  dispatch, or an outer timeout rather than a remote policy plugin. Watch
  `histogram_quantile(0.99, rate(broker_rpc_seconds_bucket[5m]))`
  trending up — though note the RPC-latency histogram is
  dormant today (registered but not observed), so this query
  may return empty.
- **State root I/O error.** Policy-epoch persistence fails;
  `broker_lifecycle_events_total{event="reload_failed"}`
  increments and the broker keeps the previous epoch.
- **Watch fan-out exhausted.** The 257th concurrent watcher for one
  principal (summed across every watch key on the connection) receives
  `ResourceExhausted` (the per-principal cap is 256).

## Pre-deploy validation

Always run
`cargo run -p ovstorage-cli -- list-routes --config <broker-config>`
against a config change before SIGHUP or restart. The same
validator the daemon runs at startup will surface typed errors
without binding any socket.

## What's not debuggable today

- No `explain-decision <audit-id>` tool. Trace the `audit_id`
  through your log aggregator.
- No durable audit sink; rely on `tracing` output.
- `route.id` and `backend.id` are not stamped on per-RPC spans
  yet — closing that gap is a tracked work item.

## References

- [`docs/public/broker-operator/README.md`](../../docs/public/broker-operator/README.md)
  — full debug runbook + observability + implementation gaps.
- [`ovstorage-operator-monitor-broker`](../ovstorage-operator-monitor-broker/SKILL.md)
  — what to scrape and which spans carry which fields.
- [`ovstorage-operator-configure-broker-policy`](../ovstorage-operator-configure-broker-policy/SKILL.md)
  — interpreting authz denies and policy-epoch advances.
- [`ovstorage-operator-deploy-broker`](../ovstorage-operator-deploy-broker/SKILL.md) —
  baseline deployment checklist.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.