Skip to content

feat(cli): mir doctor --share + beta checklist — measured beta, no telemetry (B2) - #80

Merged
frahlg merged 1 commit into
mainfrom
79-doctor-share
Aug 29, 2026
Merged

feat(cli): mir doctor --share + beta checklist — measured beta, no telemetry (B2)#80
frahlg merged 1 commit into
mainfrom
79-doctor-share

Conversation

@frahlg

@frahlg frahlg commented Aug 29, 2026

Copy link
Copy Markdown
Member

Closes #79.

What --share includes

  • mir version + commit, OS/arch + Go runtime, tmux presence + version
  • every doctor check result, pass/warn/fail, same texts as plain doctor

What --share withholds (test-enforced)

  • owner identity and machine ids → (redacted)
  • machine names (doctor never prints them; the test pins it)
  • state paths → basename only, plus every line scrubbed of the home directory
  • custom relay URLs → custom, including inside HTTP error strings (which embed both the dialed URL and the resolved host:port)

TestDoctorShareRedactsPrivateMaterial seeds recognizable fake secrets and asserts none survive; plain mir doctor stays verbatim for local use.

Decisions

  • Reconnect timings stay out of --share: extracting them means parsing agent logs, which hold machine names and paths — the checklist asks the tester to copy the reconnected in … line themselves instead.
  • No new network calls; --share probes exactly what doctor already probes.

Wired into the report flow

  • bug_report.yml and BETA.md now ask for mir doctor --share
  • new docs/beta-checklist.md walks a tester through the release gates (timed install, reconnect feel, warm switching, rename, retire + re-pair), linked from BETA.md

Tests

go test ./... green, gofmt -l clean, web 152/152.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KeiotDVE94wEzvc7wcvm1y


Note

Low Risk
Changes are additive CLI output redaction and documentation; default mir doctor behavior is preserved and sensitive leakage is test-guarded.

Overview
Adds mir doctor --share, which runs the same local checks as mir doctor but prints a report safe to paste into public issues. Identities become (redacted), state paths collapse to basenames with home-dir scrubbing on every line, and non-default relay URLs (including in HTTP error text) show as custom. Plain mir doctor output is unchanged.

Beta feedback flow: the bug report template and BETA.md now ask for --share instead of full doctor output. New docs/beta-checklist.md is a ~10-minute walk-through (install timing, reconnect, warm switching, rename, retire/re-pair, environment notes) tied to release gates, linked from BETA.md because the product has no telemetry.

Redaction is covered by doctor_share_test.go (seeded secrets must not appear in --share output).

Reviewed by Cursor Bugbot for commit b11ffaf. Bugbot is set up for automated code reviews on this repo. Configure here.

…thout telemetry (B2)

--share runs doctor's checks and prints a report built for a public issue:
version, platform, tmux, and check results — with identities, machine
names, state paths, and custom relay URLs withheld at the source, every
line additionally scrubbed of the home directory, and a test that seeds
recognizable secrets and asserts none survive. The bug template and
BETA.md now ask for --share, and docs/beta-checklist.md walks a tester
through the release gates so the north-star is measurable from reports
alone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeiotDVE94wEzvc7wcvm1y

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b11ffaf8dc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread go/internal/cli/doctor.go
Comment on lines +331 to +332
if !d.share || rawURL == defaults.SignalURL() {
return s

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Redact relays configured through MIR_SIGNAL

When a self-hosted user configures the relay via the documented MIR_SIGNAL override and the health check fails, rawURL == defaults.SignalURL() is true, so this branch returns the HTTP error unchanged. Go's HTTP errors include the requested URL, causing mir doctor --share to expose the private relay hostname in the public bug report the new template requests; the comparison needs to use the baked-in public relay or redact every relay URL in share mode.

Useful? React with 👍 / 👎.

Comment thread go/internal/cli/doctor.go
Comment on lines +61 to +62
d.w = func(format string, values ...any) {
fmt.Fprint(a.out, scrubHome(fmt.Sprintf(format, values...)))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Redact keychain references from shared errors

When the OS keychain is locked or its entry is unavailable, client.InspectIdentityStorage propagates the commandSecretStore.Get error, which embeds the unique SecretRef as owner secret %q. The share-mode writer only scrubs the home directory, so the supposedly paste-safe report publishes this owner-correlated keychain identifier; known identity-storage errors should be sanitized before being written.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-29T11:54:30.611033Z b11ffaf PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b11ffaf. Configure here.

Comment thread go/internal/cli/doctor.go
return "custom"
}
return raw
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Custom MIR_SIGNAL URL not redacted

Medium Severity

shareURL and scrubValue treat a relay as public when it equals defaults.SignalURL(), which returns MIR_SIGNAL when set. That is the documented self-host override, so mir doctor --share can print a home-server URL in health failures and unsafe-URL lines.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b11ffaf. Configure here.

Comment thread go/internal/cli/doctor.go
s = strings.ReplaceAll(s, u.Host, "custom")
}
return s
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Health errors leak resolved relay IPs

Medium Severity

scrubValue only substitutes the raw URL and u.Host. Go dial errors for a hostname custom relay include the resolved IP and port, which those replacements do not match, so a failed --share health check can still expose a private relay address.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b11ffaf. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Left a non-blocking comment: Cursor Bugbot found two unresolved medium-severity redaction issues, so this PR is not approved. Human review is needed; reviewers were assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@cursor
cursor Bot requested review from Leitet and wachtelhund August 29, 2026 11:57
Comment thread go/internal/cli/doctor.go
// the default relay is shown, anything else becomes "custom" (a private URL
// can identify a home server).
func (d *doctorReport) shareURL(raw string) string {
if d.share && raw != defaults.SignalURL() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Agentic Security Review
Severity: MEDIUM

shareURL and scrubValue treat a relay as public when it equals defaults.SignalURL(). That helper returns MIR_SIGNAL when set, which is the documented self-host override, and --signal defaults to the same value.

A tester who only exported MIR_SIGNAL (no extra flag) will paste the private relay URL into the public issue the new bug template requires. Invalid/non-HTTPS failures print it via shareURL; failed health checks skip scrubbing entirely because rawURL == defaults.SignalURL().

Impact: Home-lab or internal relay hostnames (and the URLs in Go HTTP errors) can be published as if they were the hosted default.

Fix in Cursor Fix in Web

Reviewed by Cursor Security Reviewer for commit b11ffaf. Configure here.

Comment thread go/internal/cli/doctor.go
s = strings.ReplaceAll(s, base, "custom")
}
if u, err := url.Parse(rawURL); err == nil && u.Host != "" {
s = strings.ReplaceAll(s, u.Host, "custom")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Agentic Security Review
Severity: MEDIUM

Even when custom-URL scrubbing runs, it only ReplaceAlls the configured URL string and u.Host. Go net/http dial errors separately embed the resolved address (dial tcp 10.0.0.5:443). After hostname replacement that IP:port remains.

The new test uses http://127.0.0.1:1, where u.Host already matches the dial target, so it does not catch hostname → IP leakage. Testers are asked to paste --share into public issues.

Impact: A failed health check of a hostname custom relay can still publish a private or RFC1918 relay address.

Fix in Cursor Fix in Web

Reviewed by Cursor Security Reviewer for commit b11ffaf. Configure here.

@frahlg
frahlg merged commit 4b3a6a0 into main Aug 29, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

B2: measure without telemetry — mir doctor --share + cohort checklist

1 participant