Bug Reporting Pipeline (bonedigger-report)#
Overview#
The bug reporting pipeline is a privacy-first, on-device diagnostic collection system built into Bluefin. Users run ujust report — a shell script (bonedigger-report) collects system state, scrubs PII locally, lets the user review everything, then uploads a GitHub Gist and optionally files a bug. Nothing leaves the machine until the user explicitly confirms it.
Entry point: /usr/libexec/bonedigger-report — invoked by the ujust report recipe in projectbluefin/common.
The pipeline integrates with the bonedigger lifecycle bot, which manages the downstream issue flow: filed → approved → queued → claimed → done .
User Commands#
ujust report # collect diagnostics, review, upload to gist, file issue
ujust confirm <issue#> # record that you also hit an existing bug (priority signal)
ujust verify <issue#> # confirm a shipped fix works; closes the loop
confirm count is used by the bonedigger bot as a priority escalation signal .
What Gets Collected#
All data is gathered from the local machine only. Source fields :
| Category | Data |
|---|---|
| Image | Name, tag, flavor, ref (image-info.json); booted image + digest; staged image (bootc status) |
| System | Kernel version, architecture, load average, memory usage, GNOME version + active extensions |
| Services | Failed systemd units; logs for gnome-shell, gdm, NetworkManager, bluetooth, rpm-ostree, systemd-coredump |
| GPU | PCI list (lspci); NVIDIA via nvidia-smi -q; AMD via DRM sysfs (busy %, VRAM/GTT, temp, power) |
| Crash / Panic | Previous boot end-state (4-bucket classifier); panic/oops keyword scan; last kernel errors; hardware fingerprint (DMI only) |
| Crash Artifacts | pstore mount + file count; kdump service status; userspace coredumps from last 7 days |
| Optional | Deep hardware metrics via OpenTelemetry (35-second sample) |
The boot end-state classifier produces exactly four buckets: clean shutdown, suspend-entered-no-resume, abrupt-end-after-resume, or abrupt-end-no-markers . The Linux version kernel line is intentionally excluded from the hardware fingerprint to avoid leaking build host strings .
PII Scrubbing#
All scrubbing is on-device, before upload. Two scrubber functions are applied layered :
scrub_kernel_log()— MAC addresses →[MAC-REDACTED], IPv4/IPv6 →[IP-REDACTED], UUIDs →[UUID-REDACTED], disk serials (eui/naa/wwn) →[SERIAL-REDACTED], home paths →[REDACTED]. MAC runs before IPv6 to prevent mislabeling.scrub_journal_log()— wrapsscrub_kernel_logand additionally stripsUSER=,LOGNAME=env vars and email addresses.
Additional scrubbing applied inline :
| Data | Scrubbed To |
|---|---|
groups leading username | [REDACTED] |
| NVIDIA GPU UUID, serial, bus ID, minor number | [REDACTED] |
machine-id | 8-char SHA256 anonymous HOST_ID (non-reversible) |
host.id, host.name, host.ip, host.mac (OTel) | Deleted by resource/privacy processor |
_MACHINE_ID, _BOOT_ID, _UID, _GID, _CMDLINE (journald) | Deleted from OTel log attributes |
Optional Deep Hardware Metrics (OpenTelemetry)#
Gated on the presence of /usr/share/ublue-os/otel/ujust-report-config.yaml in the image . When the user opts in:
otelcol-contribruns for 35 seconds, writing two spec-compliant OTLP JSON Lines files :metrics.otlp.jsonl— CPU, memory, disk, filesystem, network, paging, processes, Podman containerslogs.otlp.jsonl— journald service errors/warnings + kernel dmesg
- Binary resolution order:
$HOME/.local/bin/otelcol-contrib→/usr/local/bin/otelcol-contrib→command -v→ Podman fallback usingdocker.io/otel/opentelemetry-collector-contrib. - The Podman fallback mounts
/proc,/sys,/var/log/journal, and the Podman socket — it runs privileged with a 45-second timeout .
Inspect locally: jq -c '.' metrics.otlp.jsonl
Upload Flow#
The full flow :
- Report rendered via
glow+gum pagerfor local review - User confirms upload with
gum confirm— cancellation preserves files in$REPORT_DIR - If
ghis authenticated:gh gist create --publicuploadssummary.md+journal.txt(always) + OTel files (if captured) - If not authenticated:
summary.mdis copied to clipboard viawl-copyorxclip; issue URL is shown - User is offered
gum choose: "File a bug report" / "Request a feature" / "Skip"- Bug reports route to the image's own tracker (auto-detected from
image-info.json) - Feature requests always go to
projectbluefin/common
- Bug reports route to the image's own tracker (auto-detected from
Issue routing by image :
| Image | Bug report destination |
|---|---|
bluefin (non-LTS) | projectbluefin/bluefin |
bluefin (LTS tag) | projectbluefin/bluefin-lts |
dakota | projectbluefin/dakota |
| Other / unknown | projectbluefin/common |
Report Output Structure#
$XDG_RUNTIME_DIR/ujust-report/report-XXXXXX/
summary.md — Markdown report (always)
journal.txt — Current boot system/service logs (always)
metrics.otlp.jsonl — OTel host/container metrics (if OTel captured)
logs.otlp.jsonl — OTel journald + kernel logs (if OTel captured)
A persistent copy is saved to $HOME/.local/state/ujust-report/last/ after successful upload . The temp directory is cleaned on EXIT trap.
Key Files#
| File | Repo | Purpose |
|---|---|---|
/usr/libexec/bonedigger-report | projectbluefin/common | Main diagnostic script |
just/60-bonedigger.just | projectbluefin/common | ujust report recipe (v0.1.0) |
otel/ujust-report-config.yaml | projectbluefin/common | OTel collector config |
docs/skills/bonedigger-overview.md | projectbluefin/bonedigger | Architecture overview |
docs/skills/bonedigger-ujust.md | projectbluefin/bonedigger | Full ujust tool reference |
.github/workflows/lifecycle.yml | projectbluefin/bonedigger | Issue lifecycle bot |
Ownership rule: The recipe and OTel config are image content — they live in
projectbluefin/commonand ship viacommon.bst. Do not copy them to other repos or write sync workflows.
Dependencies#
| Tool | Role | Required? |
|---|---|---|
gum | TUI prompts and styling | Required |
gh | GitHub CLI for gist upload | Required for upload |
bootc | Reads booted image status | Required |
jq | Parses JSON from bootc/image-info | Required |
glow | Markdown rendering in terminal | Optional |
wl-copy / xclip | Clipboard fallback (no auth) | Optional |
otelcol-contrib or podman | Deep hardware metrics | Optional |