feat(cli): add non-mutating buzz doctor command (#3926) - #4063
Open
iroiro147 wants to merge 2 commits into
Open
Conversation
Adds a root-level `buzz doctor` subcommand that runs independent local + remote readiness checks and aggregates them into a single structured JSON report. Use it to answer 'is my Buzz environment ready to use?' without publishing events or mutating state. Checks performed: - relay URL presence, syntax, canonicalization - BUZZ_PRIVATE_KEY parseability (never printed; only the derived public identity is reported) - BUZZ_AUTH_TAG syntax + verification against the signing identity (never printed) - CLI version - relay unauthenticated reachability probe - NIP-11 parseation against the relay info document - authenticated read probe (single bounded query) - community membership probe (kind:39002 #p=self) `--offline` runs only local checks and marks remote probes as skipped. Missing or malformed config surfaces as a check result with status error, not as an argument-time failure, so doctor remains useful when the environment being debugged is the broken one. Exit behavior distinguishes failed required checks from warnings: 0 all applicable checks ok (warnings allowed) 3 any auth/identity check failed 2 any relay/network check failed All applicable checks run so one invocation can reveal multiple problems. Tests cover the aggregator's exit-precedence (auth wins over network, skipped never affects outcome, warnings stay zero) and the JSON output shape. Signed-off-by: iroiro147 <sarthak.singh@juspay.in>
… not auth (exit 3) (block#3926) The first cut routed every authed-read failure into the same auth-shaped bucket. On an unreachable relay the relay_reachable probe was reported error, then the authed read ALSO reported auth_read error, which the aggregator mapped to exit 3 — even though a DNS/connect failure has nothing to do with credentials. Split the failure handling: - Distinguish true auth rejections (Auth variant, or relay 401/403) from transport/other relay failures. Only the former produces an auth_read error -> exit 3. - Track whether the unauthenticated reachability probe already failed; if so, skip re-emitting the relay-side error and mark auth_read/membership as skipped instead. - If reachability passed but the authed read failed for a transport reason, emit a relay_reachable error explaining the authed leg failed. Smoke-verified: with BUZZ_RELAY_URL pointing at an unresolvable host, exit is now 2 with relay_reachable + nip11 reporting the transport problem and auth_read/membership cleanly skipped. Signed-off-by: iroiro147 <sarthak.singh@juspay.in>
Author
|
Added a follow-up commit |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat(cli): add non-mutating
buzz doctorcommand (#3926)Closes #3926.
What
Adds a root-level
buzz doctorsubcommand that runs independent local + remote readiness checks and aggregates them into a single structured JSON report, so users / agents / automation / support flows can answer "is my Buzz environment ready to use?" without--helptrivia and without failing at the first problem.Why
Buzz Desktophas a Doctor surface for managed ACP runtimes, but that's a different scope and unavailable headlessly.How
Command
The subcommand is added directly to the top-level
Cmdenum (not nested under a group), matching the existing architecture.Dispatch order
run()incrates/buzz-cli/src/lib.rsis reshaped so doctor dispatches before the credential gate. Every other command still requiresBUZZ_PRIVATE_KEY; doctor must remain usable when the broken environment is the one being debugged, so missing/malformed credentials surface as a check result (statuserror), not as an argument-time failure.Checks (all independent, all run; one invocation reveals multiple problems)
Local, always-on:
relay_url— presence, syntax, canonicalization via the samenormalize_relay_urlthe rest of the CLI uses.identity—BUZZ_PRIVATE_KEYparseability. Key material is never printed; only the derived public identity (hex) is reported on success.auth_tag—BUZZ_AUTH_TAGparse + verification against the signing identity viabuzz_sdk::nip_oa::parse_auth_tag/verify_auth_tag. The tag is never printed. When set but the identity is invalid, we degrade towarning.version—env!("CARGO_PKG_VERSION").Remote (skipped when
--offline):relay_reachable— an unauthenticatedGET /withAccept: application/nostr+json, just to prove DNS/TLS/reachability.nip11— fetches and parses the NIP-11 information document end-to-end. Done with a barereqwest::Clientso doctor works even when the identity is broken.auth_read— bounded authenticated read (singlequery_paginatedcall withlimit=1) againstkinds:[39002] #p=self. This doubles as the membership probe input.membership— interprets the previous call: zero events →warning("not a member of any channel visible to this relay"), ≥1 events →ok.--offlinemarks the four remote probesskippedand they do not affect the outcome.Output
Single JSON document on stdout:
{ "status": "ok" | "warning" | "error", "checks": [ { "id": "relay_url" | "identity" | "auth_tag" | "version" | "relay_reachable" | "nip11" | "auth_read" | "membership", "status": "ok" | "warning" | "error" | "skipped", "message": "…", "remediation": "…" | null } ] }Field identifiers are stable for automation.
Exit behavior
0when every applicable check isok(warnings allowed; skipped never affects).3when anyidentity/auth_tag/auth_readcheck iserror(auth-shaped).2when the only errors arerelay_reachable/nip11(transport-shaped), viaCliError::Relay { status: 0, .. }.This matches the existing
0=ok 1=bad input 2=relay 3=auth 4=other 5=conflictconvention.Never exposes
Testing
commands/doctor.rscovering:ok→Ok(()), indico exit0Ok(()), exit0identityerror →CliError::Auth→ exit3auth_readerror →CliError::Auth→ exit3relay_reachableerror →CliError::Relay{0,..}→ exit2skippednever affects outcomestatus+checksarray with expected keyscommand_inventory_is_stableto includedoctor(22 groups).cargo test -p buzz-cli --lib: 279 passed, 0 failed.cargo clippy -p buzz-cli --all-targets -- -D warnings: clean.buzz doctor --helpandbuzz doctor --offlineprint the expected shapes; the latter exits3cleanly whenBUZZ_PRIVATE_KEYis unset.Out of scope (per the issue's own staging)
Notes for reviewers
relay_reachableandnip11share an HTTP request path (bothGET /with the metadata accept header); currently issued as two probes for clarity, easy to fuse if a reviewer prefers.buzz users me/whoamiwork in feat(cli): add buzz users me for external-agent identity #2933 (when it lands) is complementary — it would givedoctora clean way to also report the resolved user profile, but isn't required for v1.