Skip to content

feat(api): admin-only scrubbed diagnostics bundle (server side of #180) - #385

Merged
badbread merged 1 commit into
mainfrom
feat/admin-diagnostics-bundle
Jul 23, 2026
Merged

feat(api): admin-only scrubbed diagnostics bundle (server side of #180)#385
badbread merged 1 commit into
mainfrom
feat/admin-diagnostics-bundle

Conversation

@badbread

Copy link
Copy Markdown
Owner

The server-side piece of #180: an admin-only, downloadable, scrubbed diagnostics bundle so a maintainer can triage a tester's server-side issue without shell access. (The desktop client already shipped its half in #274.)

What it adds

  • GET /diagnostics/bundle (AdminUser-gated → 403 otherwise): a pretty-JSON snapshot delivered as a file attachment (crumb-diagnostics-<ts>.json), containing:
    • version (service / version / git sha / build time)
    • effective server settings (the DB server_settings row)
    • a curated, non-secret env whitelist (LOG_FORMAT, TZ, MOTION_HWACCEL, ...)
    • applied schema migrations (count + latest few) — tells whether the DB is at the expected version
  • A "Diagnostics — support bundle" download button in the admin console's server-settings panel.

Secure by default (load-bearing)

Everything is run through a recursive redact() pass before it leaves the box:

  • any value under a secret-shaped key (token / password / secret / hash / api_key / credential / private / ...) → "***REDACTED***"
  • any string carrying URL userinfo (scheme://user:pass@host) → scheme://***@host (dependency-free, no regex crate)

Two independent nets, so a leak would need both a surprising field name and a non-URL secret shape. env is a whitelist, never std::env::vars(). Footage and live logs are never included.

Deliberately out of scope (follow-up on #180)

Live logs and runtime health. Logs are stdout-only, so shipping them needs an in-process ring buffer, and the recorder's logs live in a separate process — a bigger piece. The config + schema snapshot already covers a large class of "why isn't X working" server-side.

Tests

  • redact() unit tests: secret-shaped keys anywhere in the tree, credential-URL masking (with documentation-range IPs), and a URL under a non-secret key.
  • Route test: admin → 200 + attachment; authenticated viewer → 403.
  • fmt + clippy -D warnings + full cargo test --workspace all green; admin.html script passes node --check.

Addresses #180 (server bundle piece).

🤖 Generated with Claude Code

Adds GET /diagnostics/bundle (admin-only): a downloadable JSON snapshot of
the server's version, effective config, key environment, and applied schema
migrations, so a maintainer can triage a tester's server-side issue without
a shell on the box.

Secure by default: the whole bundle is run through a recursive redactor
before it leaves the box. Any value under a secret-shaped key (token /
password / secret / hash / api_key / credential / ...) is masked, and any URL
userinfo (scheme://user:pass@host) is stripped, so a leak would need both a
surprising field name AND a non-URL secret shape. The env section is a
NON-secret whitelist, never a full env dump. The route is AdminUser-gated
(403 otherwise).

Adds a "Diagnostics -- support bundle" download button to the admin console's
server-settings panel.

Out of scope (follow-up on #180): live logs (stdout-only, so it needs an
in-process ring buffer, and the recorder's logs are a separate process) and
runtime health. The config + schema snapshot already covers a large class of
server-side misconfiguration without them.

Tests: redact() unit tests (secret keys, credential URLs, nested trees) and a
route test (admin 200 + attachment, viewer 403); the full gate is green.

Addresses #180

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: badbread <badbread@users.noreply.github.com>
@badbread
badbread merged commit 63cedb1 into main Jul 23, 2026
7 checks passed
@badbread
badbread deleted the feat/admin-diagnostics-bundle branch July 23, 2026 19:17
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.

1 participant