{"id":43553521,"url":"https://github.com/alltheseas/bugstr","last_synced_at":"2026-02-03T19:36:29.947Z","repository":{"id":325353319,"uuid":"1100851275","full_name":"alltheseas/bugstr","owner":"alltheseas","description":"Zero-infrastructure crash reporting","archived":false,"fork":false,"pushed_at":"2026-01-16T21:02:25.000Z","size":365,"stargazers_count":2,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-16T21:34:35.712Z","etag":null,"topics":["android","crash-report","crash-reporting","crash-reporting-backend","crash-reports","electron","error-logging","foss","go","kotlin","python","react","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alltheseas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-11-20T21:05:42.000Z","updated_at":"2026-01-16T18:29:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/alltheseas/bugstr","commit_stats":null,"previous_names":["alltheseas/bugstr"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/alltheseas/bugstr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alltheseas%2Fbugstr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alltheseas%2Fbugstr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alltheseas%2Fbugstr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alltheseas%2Fbugstr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alltheseas","download_url":"https://codeload.github.com/alltheseas/bugstr/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alltheseas%2Fbugstr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29054835,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-03T15:43:47.601Z","status":"ssl_error","status_checked_at":"2026-02-03T15:43:46.709Z","response_time":96,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","crash-report","crash-reporting","crash-reporting-backend","crash-reports","electron","error-logging","foss","go","kotlin","python","react","rust"],"created_at":"2026-02-03T19:36:29.076Z","updated_at":"2026-02-03T19:36:29.934Z","avatar_url":"https://github.com/alltheseas.png","language":"Rust","readme":"# Bugstr\n\nZero-infrastructure crash reporting — no server to run, no SaaS to pay for.\n\nBugstr delivers crash reports via [NIP-17](https://github.com/nostr-protocol/nips/blob/master/17.md) encrypted direct messages with user consent. Reports auto-expire after 30 days.\n\n\u003cimg width=\"256\" height=\"256\" alt=\"Bugstr logo\" src=\"https://github.com/user-attachments/assets/1c3c17dc-6a6d-4881-9ac7-32217bd4e1ad\" /\u003e\n\n## Platforms\n\n| Platform | Directory | Tested |\n|----------|-----------|--------|\n| Android/Kotlin | [`android/`](android/) | ✅ [Zapstore](https://github.com/zapstore/zapstore/pull/272) |\n| Electron | [`electron/`](electron/) | 🐹 Guinea pigs needed |\n| Flutter/Dart | [`dart/`](dart/) | 🐹 Guinea pigs needed |\n| Rust | [`rust/`](rust/) | 🐹 Guinea pigs needed |\n| Go | [`go/`](go/) | 🐹 Guinea pigs needed |\n| Python | [`python/`](python/) | 🐹 Guinea pigs needed |\n| React Native | [`react-native/`](react-native/) | 🐹 Guinea pigs needed |\n\n## How It Works\n\n```\nCrash → Cache locally → App restart → Show consent dialog → User approves → Send encrypted DM (expires in 30 days)\n```\n\n1. **Crash occurs** - Exception handler captures stack trace\n2. **Local cache** - Report saved to disk (no network)\n3. **User consent** - Dialog shows on next app launch\n4. **NIP-17 DM** - Encrypted, gift-wrapped message sent to developer\n5. **Auto-expiration** - Report deleted from relays after 30 days\n\n## Default Relays\n\nAll SDKs use the same default relay list, chosen for reliability:\n\n| Relay | Max Event Size | Max WebSocket | Notes |\n|-------|----------------|---------------|-------|\n| `wss://relay.damus.io` | 64 KB | 128 KB | strfry defaults |\n| `wss://relay.primal.net` | 64 KB | 128 KB | strfry defaults |\n| `wss://nos.lol` | 128 KB | 128 KB | Fallback relay |\n\n**Note:** Most relays use strfry defaults (64 KB event size, 128 KB websocket payload). The practical limit for crash reports is ~60 KB to allow for gift-wrap envelope overhead.\n\nYou can override these defaults via the `relays` configuration option in each SDK.\n\n## Size Limits \u0026 Compression\n\nCrash reports are subject to relay message size limits (see [NIP-11](https://github.com/nostr-protocol/nips/blob/master/11.md) `max_message_length`).\n\n| Relay Limit | Compatibility |\n|-------------|---------------|\n| 64 KB | ~99% of relays |\n| 128 KB | ~90% of relays |\n| 512 KB+ | Major relays only |\n\n**Practical limit:** Keep compressed payloads under **60 KB** for universal delivery (allows ~500 bytes for gift-wrap envelope overhead).\n\n| Payload Size | Behavior |\n|--------------|----------|\n| \u003c 1 KB | Sent as plain JSON |\n| ≥ 1 KB | Compressed with gzip, base64-encoded |\n\n### Compression Format\n\nLarge payloads are wrapped in a versioned envelope:\n\n```json\n{\n  \"v\": 1,\n  \"compression\": \"gzip\",\n  \"payload\": \"\u003cbase64-encoded-gzip-data\u003e\"\n}\n```\n\nStack traces are automatically truncated to fit within limits (default: 200 KB before compression). The receiver CLI/WebUI automatically detects and decompresses payloads.\n\n### Compression Efficiency\n\nGzip typically achieves **70-90% reduction** on stack traces due to their repetitive text patterns:\n\n| Original Size | Compressed | Reduction |\n|---------------|------------|-----------|\n| 10 KB | ~1-2 KB | ~80-90% |\n| 50 KB | ~5-10 KB | ~80-90% |\n| 200 KB | ~20-40 KB | ~80-85% |\n\nWith gzip compression (70-90% reduction), most crash reports fit well within the 64 KB strfry default limit. For maximum compatibility, keep compressed payloads under 60 KB.\n\n## Nostr Protocol\n\nAll implementations use these NIPs:\n\n- [**NIP-17**](https://github.com/nostr-protocol/nips/blob/master/17.md) - Private Direct Messages (kind 14 rumors)\n- [**NIP-44**](https://github.com/nostr-protocol/nips/blob/master/44.md) - Versioned Encryption (v2, XChaCha20-Poly1305)\n- [**NIP-59**](https://github.com/nostr-protocol/nips/blob/master/59.md) - Gift Wrap (rumor → seal → gift wrap)\n- [**NIP-40**](https://github.com/nostr-protocol/nips/blob/master/40.md) - Expiration Timestamp\n\n### Implementation Notes\n\nPer NIP-17, rumors (kind 14) must include:\n- `id` - SHA256 hash of `[0, pubkey, created_at, kind, tags, content]`\n- `sig: \"\"` - Empty string (not omitted)\n\nSome clients (e.g., 0xchat) reject messages missing these fields.\n\n## Shared Test Vectors\n\nThe [`test-vectors/`](test-vectors/) directory contains JSON test cases for NIP-17. All platform implementations should validate against these vectors.\n\n## Symbolication\n\nRelease builds typically use code obfuscation/minification, producing stack traces with mangled names and memory addresses instead of readable function names and line numbers.\n\n**Current status:** Symbolication tooling is not yet implemented. Crash reports contain raw stack traces as captured.\n\n**Planned approach:**\n- Store mapping files (ProGuard, dSYM, sourcemaps) locally or in your CI\n- Use platform-specific tools to symbolicate:\n  - **Android**: `retrace` with ProGuard mapping\n  - **iOS/macOS**: `atos` or `symbolicatecrash` with dSYM\n  - **JavaScript**: Source map support in browser devtools\n  - **Flutter**: `flutter symbolize` with app symbols\n\nContributions welcome for automated symbolication in the receiver CLI/WebUI.\n\n## Contributing\n\nSee [AGENTS.md](AGENTS.md) for contributor guidelines covering:\n- Documentation requirements\n- Commit conventions\n- NIP implementation notes\n\n## License\n\n[MIT](LICENSE)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falltheseas%2Fbugstr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falltheseas%2Fbugstr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falltheseas%2Fbugstr/lists"}