Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
08a31bd
feat: degrade to in-memory reporting on read-only/ephemeral file syst…
krassx Oct 14, 2026
184d102
fix: address review of data-directory fallback (#9)
krassx Oct 14, 2026
01e337c
fix: second review round for data-directory fallback (#9)
krassx Oct 14, 2026
cc96a41
feat(bugsee): populate utc_offset, hardware model and Windows locale
krassx Oct 14, 2026
a7410a4
fix(bugsee): address review of hostinfo (iOS model, tm_gmtoff gating,…
krassx Oct 14, 2026
11226fb
fix(core): exactly-once recovery and queue draining across processes …
krassx Oct 14, 2026
faf4344
feat: define the shutdown/flush contract; opt-in SIGTERM/SIGINT flush
krassx Oct 14, 2026
5ec98a8
feat: general PII scrubber and report rate limiting
krassx Oct 14, 2026
16937c8
fix(core): arbitrate cross-process claims and session liveness with O…
krassx Oct 14, 2026
c462eef
fix: harden the termination hook and shutdown after review
krassx Oct 14, 2026
31a293c
fix: keep draining existing data dirs that cannot take new files (#9)
krassx Oct 14, 2026
f8162d7
fix(scrub): second-review hardening of the PII scrubber
krassx Oct 14, 2026
229ec84
Merge remote-tracking branch 'origin/fix/issue-9' into fix/issue-8
krassx Oct 14, 2026
b9430e6
Merge origin/fix/issue-9 into fix/issue-11
krassx Oct 14, 2026
10271f3
fix(core): harden the file-lock claims (second review)
krassx Oct 14, 2026
fdbb296
fix: keep the scheduled memory drain independent of the stop flag
krassx Oct 14, 2026
716c363
test: gate unix-only helpers so Windows clippy stays clean (#9)
krassx Oct 14, 2026
69a6bc8
Merge origin/fix/issue-9 into fix/issue-14
krassx Oct 14, 2026
6e71a45
feat(native): best-effort flush of in-flight events at crash time
krassx Oct 14, 2026
9ae8a05
fix(core): queue the previous crash on the launch path before launch …
krassx Oct 14, 2026
0b78a10
fix: drain every trusted unwritable default tree, not just one; stale…
krassx Oct 14, 2026
9c384ad
Merge remote-tracking branch 'origin/fix/issue-9' into fix/issue-8
krassx Oct 14, 2026
3bf7ac7
fix(scrub,runtime): second re-review fixes
krassx Oct 14, 2026
e739839
fix: PR #31 review and CI fixes
krassx Oct 14, 2026
6267bd5
Merge origin/fix/issue-9; portable clippy fixes for lock claims
krassx Oct 14, 2026
e9c49f9
Merge origin/fix/issue-9 into fix/issue-11
krassx Oct 14, 2026
412cff1
Merge remote-tracking branch 'origin/fix/issue-9' into fix/issue-13
krassx Oct 14, 2026
0cb980b
fix(core): run launch-path recovery on a bounded helper, after the cr…
krassx Oct 14, 2026
a0a779b
Merge origin/fix/issue-14 into fix/issue-10
krassx Oct 14, 2026
1760cf2
fix(native): harden in-flight crash flush (review feedback, #13)
krassx Oct 14, 2026
ee3f808
fix(core): review round 3 on lock claims
krassx Oct 14, 2026
38f73e6
feat(health): local session health records for release health (#12)
krassx Oct 14, 2026
c4f81d6
fix(core): make the lock-less heartbeat robust to clock skew and slow…
krassx Oct 14, 2026
6dfc9c8
fix(core): keep unique crashes the launch pass cannot queue; scan new…
krassx Oct 14, 2026
ee725bc
Merge origin/fix/issue-10 into fix/issue-13: port the DYING gate onto…
krassx Oct 14, 2026
6d6faa2
Merge origin/fix/issue-14 into fix/issue-10
krassx Oct 14, 2026
460e093
fix(health): address review of release health (#12)
krassx Oct 14, 2026
74605d1
Merge origin/fix/issue-10 into fix/issue-12
krassx Oct 14, 2026
4530024
fix(core): tried sessions first, and a queue-cap refusal is not an at…
krassx Oct 14, 2026
979c6e8
fix(native): address review of the in-flight flush (#13)
krassx Oct 14, 2026
1d84feb
fix: never recover the same directory twice in one launch (#9)
krassx Oct 14, 2026
3b90a28
fix(core): a lock file that vanishes under a scan is not evidence of …
krassx Oct 14, 2026
546024b
fix: a stop during a flush's memory pass must not start a disk upload
krassx Oct 14, 2026
3703010
Merge remote-tracking branch 'origin/fix/issue-9' into fix/issue-8
krassx Oct 14, 2026
69378f1
fix(health): keep panic.info for abort correlation, no eager registra…
krassx Oct 14, 2026
4002558
fix(core): a failed enqueue write is not a recovery attempt
krassx Oct 14, 2026
7aad047
Merge remote-tracking branch 'origin/fix/issue-14' into fix/issue-10
krassx Oct 14, 2026
46872ff
fix(health): do not expire panic.info from a hook timer
krassx Oct 14, 2026
b606938
fix(core): a session the launch pass defers is picked up even if the …
krassx Oct 14, 2026
168b672
fix(health): mark a panicking drop so a slow unwind is still a crash
krassx Oct 14, 2026
12d4672
fix(core): deferred launch-pass recovery uses the recovery directory,…
krassx Oct 14, 2026
1748ada
fix(scrub): do not redact public OIDC/OAuth metadata keys
krassx Oct 14, 2026
75e6611
Merge remote-tracking branch 'origin/fix/issue-9' into fix/issue-11
krassx Oct 14, 2026
fbd6644
fix: remember every undeletable retired bundle, not just delivered on…
krassx Oct 14, 2026
5496529
Merge remote-tracking branch 'origin/fix/issue-9' into fix/issue-10
krassx Oct 14, 2026
1b91328
Merge origin/fix/issue-10 into fix/issue-13
krassx Oct 14, 2026
04a927a
Merge origin/fix/issue-16 into fix/issue-13 (libc stays a normal unix…
krassx Oct 14, 2026
bb281f1
test(core): wait on an observable condition in the full-queue test
krassx Oct 14, 2026
4893817
Merge origin/fix/issue-10 into fix/issue-13
krassx Oct 14, 2026
97dc58b
fix(scrub): narrow the oauth exclusion to public metadata
krassx Oct 14, 2026
c3f1748
Merge remote-tracking branch 'origin/fix/issue-9' into fix/issue-11
krassx Oct 14, 2026
862072a
Merge origin/fix/issue-13 into fix/issue-12
krassx Oct 14, 2026
19a26ee
Merge origin/fix/issue-9 into fix/issue-11
krassx Oct 14, 2026
d0608a2
Merge remote-tracking branch 'origin/fix/issue-12' into fix/issue-8
krassx Oct 14, 2026
7ab8a90
fix(core): declare kernel32 calls once (clashing_extern_declarations …
krassx Oct 14, 2026
7e1adab
fix(scrub): free-text oauth_verifier/oauth_pin and short pin/otp codes
krassx Oct 14, 2026
aa238d8
Merge remote-tracking branch 'origin/fix/issue-13' into fix/issue-12
krassx Oct 14, 2026
20cf3a7
Merge remote-tracking branch 'origin/fix/issue-12' into fix/issue-8
krassx Oct 14, 2026
605126d
fix(scrub): structured matching redacts code_verifier (PKCE)
krassx Oct 14, 2026
1881878
Merge origin/fix/issue-8 into fix/issue-11
krassx Oct 14, 2026
b6ce5e0
Merge origin/main into fix/issue-9
krassx Oct 14, 2026
e01a20a
Merge origin/fix/issue-9 into fix/issue-14
krassx Oct 14, 2026
e00b09d
Merge origin/fix/issue-14 into fix/issue-10
krassx Oct 14, 2026
3e18e85
Merge remote-tracking branch 'origin/fix/issue-10' into HEAD
krassx Oct 14, 2026
acee6db
docs: keep the corrected native feature comment from main
krassx Oct 14, 2026
5a844b8
Merge origin/fix/issue-13 into fix/issue-12
krassx Oct 14, 2026
50da593
Merge origin/fix/issue-12 into fix/issue-8
krassx Oct 14, 2026
e86e426
Merge origin/fix/issue-8 into fix/issue-11
krassx Oct 14, 2026
1ecfca8
fix: de-duplicate the unix libc dependency after merging main (#27's …
krassx Oct 14, 2026
fbbabb2
Merge origin/fix/issue-9 into fix/issue-14
krassx Oct 14, 2026
66e4f18
Merge origin/fix/issue-14 into fix/issue-10
krassx Oct 14, 2026
4e42eda
Merge remote-tracking branch 'origin/fix/issue-10' into HEAD
krassx Oct 14, 2026
fe63783
Merge origin/fix/issue-13 into fix/issue-12
krassx Oct 14, 2026
f5dcac4
Merge origin/fix/issue-12 into fix/issue-8
krassx Oct 14, 2026
75dbf32
Merge origin/fix/issue-8 into fix/issue-11
krassx Oct 14, 2026
0f94b90
fix(core): make the crash-flush handshake robust on slow runners
krassx Oct 14, 2026
54c5414
docs: describe backend behaviour generically in release-health notes
krassx Oct 14, 2026
a89ce8a
Merge origin/main (squashes of #14, #10) into fix/issue-13
krassx Oct 14, 2026
4858ce7
docs: keep design notes generic (no private-component references) (#36)
krassx Oct 14, 2026
4d891b1
Merge origin/fix/issue-13 into fix/issue-12
krassx Oct 14, 2026
e738c93
Merge origin/main (squash of #13) into fix/issue-12
krassx Oct 14, 2026
b7c5507
Merge origin/fix/issue-12 into fix/issue-8
krassx Oct 14, 2026
fa0a34e
Merge origin/main (squash of #12) into fix/issue-8
krassx Oct 14, 2026
fa4f539
Merge remote-tracking branch 'origin/fix/issue-8' into HEAD
krassx Oct 14, 2026
87d8244
Merge origin/main (squashes of #12, #8, clean-ups) into fix/issue-11
krassx Oct 14, 2026
2e1b442
docs: drop numeric server error codes from notes and comments (#37)
krassx Oct 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions PROGRESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,34 @@ in [`DESIGN.md`](./DESIGN.md); the wire contract is `bugsee/report-bundle-struct
| 2 — Handled errors + caught panics | ✅ | `catch_unwind` guards, panic snapshot, error/cause chains. Follow-ups: `tracing` Layer + `log` adapter done. Subsystem quarantine still open. |
| 3 — Fatal + next-launch + correlation | ✅ (core) | Native handler, session generations + liveness markers, next-launch recovery, panic↔SIGABRT correlation, client-side native dedup signature from frame offsets. **New:** Windows native capture — SEH/VEH handler, PE CodeView module map, marker + frame capture — so all three desktop platforms report fatal crashes. In-flight events are now flushed at crash (bounded 50 ms, signal-safe wake of the capture worker; #13). Open: full out-of-process minidump. |
| 4 — Integrations & APM | ✅ (core) | APM transactions/spans, sysinfo telemetry, reqwest network capture. **New:** the environment is actually populated — OS version, kernel, memory, disk, locale, and app identity (`package_id`/`version`/`build`) via `LaunchOptions::app_version`. Open: sessions / release-health. |
| 5 — Hardening | ✅ (core) | Durable retry queue (backoff, retry cap, blacklist), `before_send`/`before_breadcrumb`, event sampling. **New:** `on_report_dropped` — delivery failure is observable at last; `flush()` alone never could distinguish delivered from discarded. Open: general PII scrubber, rate limits. |
| 5 — Hardening | ✅ (core) | Durable retry queue (backoff, retry cap, blacklist), `before_send`/`before_breadcrumb`, event sampling. **New:** `on_report_dropped` — delivery failure is observable at last; `flush()` alone never could distinguish delivered from discarded. **New:** general PII scrubber (`bugsee_core::scrub`, on by default, `disable_scrubbing()`) and token-bucket rate limiting (`bugsee_core::ratelimit`, on by default, `disable_rate_limiting()`, `DropReason::RateLimited`). |
| 6 — Mobile/FFI | ✅ (core) | `bugsee-ffi` C ABI (`include/bugsee.h`). Open: actual iOS/Android target builds + Swift/Kotlin wrappers. |

## Behaviour change: PII scrubbing and rate limiting are ON by default (issue #11)

There is no CHANGELOG file in this repo, so this is the migration note. Upgrading
changes what leaves the process:

- **Scrubbing (default on).** Every report is scrubbed at assembly, after
`before_send`: capture channels, `crash.json`, summary/description/labels/
attributes, `request.json` (environment) and the session-registration
environment. Emails, known token shapes, PEM private keys, URL passwords,
`password=`-style values, card numbers and home-directory user names become
markers (`[email]`, `[token]`, `[redacted]`, `[card]`, `[user]`). The reporter's
`email` identity and the dedup `signatures` are never touched; attachments and
minidumps are opaque and not scrubbed. Tune with `LaunchOptions::scrub(...)`
(`allow`/`deny`/`sensitive_keys`), disable with `disable_scrubbing()`.
- **Rate limiting (default on).** Non-fatal errors: per signature burst 5, +1/10 s;
global burst 60, +1/s. Crashes bypass those and use a crash floor (burst 20,
+1/6 s, never below 1); manual bug reports are exempt. Drops surface as
`DropReason::RateLimited` and as the `bugsee.reports_suppressed` attribute on
the next admitted non-crash report; `Recorder::suppressed_reports()` gives the
running total. Tune with `LaunchOptions::rate_limit(...)`, disable with
`disable_rate_limiting()`.
- Apps that relied on raw values appearing in reports (an email in a log line, a
token-looking attribute) must opt out or add `allow` entries.
- `bugsee-ffi` does not expose these options yet (follow-up); it gets the defaults.

## Recent work — the symbol pipeline, end to end (`f224188`, `3e2f9bf`, `51f4dc7`)

Closing the last gap between "a Rust crash arrives" and "a Rust crash is
Expand Down Expand Up @@ -540,7 +565,6 @@ Rust and are worth evaluating before building one.
- Phase 2: subsystem quarantine (auto-disable a repeatedly-faulting integration).
- Phase 3: full out-of-process minidump (desktop) — see the backend note below, which is the same machinery.
- Phase 4: sessions / release-health: SDK half done, experimental and off by default (#12: eager session registration plus local session records; the backend has no session-health ingest, see DESIGN.md §10).
- Phase 5: general PII scrubber, rate limits.
- Phase 6: iOS/Android target builds; Swift/Kotlin language wrappers.
- CI: ~~cross-platform matrix~~ **done**; loom/miri/fuzz jobs still open — fuzzing is
newly justified now that `pe_debug_id` parses headers of arbitrary third-party
Expand Down
2 changes: 2 additions & 0 deletions crates/bugsee-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ pub mod origin;
pub mod panic_info;
pub(crate) mod process;
pub mod queue;
pub mod ratelimit;
pub mod recovery;
pub mod reporting;
pub mod runtime;
pub mod scrub;
pub mod session;
pub mod signature;
pub mod transport;
Expand Down
10 changes: 10 additions & 0 deletions crates/bugsee-core/src/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,12 +246,22 @@ fn blacklist_path(data_dir: &Path) -> PathBuf {
queue_dir(data_dir).join(".blacklist")
}

static BLACKLIST_READS: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);

/// How many times the on-disk blacklist has been read since process start.
/// Exists so tests can prove a rate-limited storm performs no disk reads.
#[doc(hidden)]
pub fn blacklist_read_count() -> usize {
BLACKLIST_READS.load(std::sync::atomic::Ordering::Relaxed)
}

/// The locally blacklisted signatures in `data_dir` (empty if none or unreadable).
pub fn blacklisted_signatures(data_dir: &Path) -> BTreeSet<String> {
load_blacklist(data_dir)
}

fn load_blacklist(data_dir: &Path) -> BTreeSet<String> {
BLACKLIST_READS.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
std::fs::read_to_string(blacklist_path(data_dir))
.map(|s| {
s.lines()
Expand Down
Loading
Loading