add go, python, react native, flutter libraries#5
Conversation
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (15)
📝 WalkthroughWalkthroughAdds new Go, Python, and React Native SDKs and docs implementing NIP-17/Nostr crash reporting, plus README updates describing default relays, size limits, compression envelope, redaction, confirmation hooks, and packaging/config files for each SDK. Changes
Sequence Diagram(s)sequenceDiagram
participant App as Application
participant SDK as Bugstr SDK
participant Hook as Hook (before_send/confirm_send)
participant Relay as Nostr Relay
participant Dev as Developer
App->>SDK: error occurs / captureException(...)
SDK->>SDK: buildPayload() — message, stack, ts, env, release
SDK->>SDK: redact(payload)
SDK->>SDK: maybeCompress(payload) -> optional gzip+envelope
alt beforeSend hook present
SDK->>Hook: before_send(payload)
Hook-->>SDK: modified payload / cancel
end
alt confirmation required
SDK->>Hook: confirm_send(summary)
Hook-->>SDK: true / false
alt user declines
SDK-->>App: abort send
end
end
SDK->>SDK: construct NIP-14 rumor -> seal (nip44 / kind-13) -> wrap (kind-1059)
SDK->>Relay: publish wrapped event(s)
Relay-->>Dev: deliver encrypted message
Dev->>Dev: decrypt & inspect report
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
a50146d to
f494df5
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@go/go.mod`:
- Line 22: The go.mod currently pins the indirect dependency golang.org/x/crypto
at v0.28.0 which has multiple critical CVEs; determine the latest patched
release that addresses GO-2024-3321, GO-2025-3487, GO-2025-4116, GO-2025-4134,
GO-2025-4135, GHSA-f6x5-jh6r-wrfv, GHSA-hcg3-q754-cr77, GHSA-j5w8-q4qc-rx2x, and
GHSA-v778-237x-gjrc, then update the module to that version by updating the
golang.org/x/crypto dependency in the Go module (use the Go tooling to set
golang.org/x/crypto@<patched-version>) and run module cleanup (go mod tidy) so
the go.mod/go.sum reflect the fixed version.
In `@python/pyproject.toml`:
- Around line 1-35: The pyproject.toml is missing setuptools package discovery
configuration for the project "bugstr"; add explicit setuptools package
discovery by adding a [tool.setuptools.packages.find] table and include pattern
(e.g. include = ["bugstr*"]) or set packages = ["find:"] under [tool.setuptools]
so setuptools knows to locate the bugstr package (if you use a src/ layout also
add where = ["src"] in the find table).
In `@react-native/src/index.ts`:
- Around line 140-160: unsignedKind14 is missing the NIP-01 computed id (SHA-256
of [0, pubkey, created_at, kind, tags, content]), so compute the rumor id and
add it to unsignedKind14 before encrypting/sealing; use the same fields used to
build the event (pubkey from getPublicKey(senderPrivkey), created_at from
randomPastTimestamp(), kind = 14, tags, content = plaintext), compute the hex
SHA-256 digest and set unsignedKind14.id, then continue to derive
conversationKey via nip44.getConversationKey, encrypt with nip44.encrypt and
pass the finalized event to finalizeEvent as before so the recipient can decrypt
and verify the rumor structure per NIP-01.
In `@react-native/tsconfig.json`:
- Around line 1-16: The build is failing because react-native-builder-bob is
pointed at "tsconfig.build.json" but only "tsconfig.json" exists; either add a
new tsconfig.build.json that extends tsconfig.json and excludes tests/mocks
(e.g., extends "./tsconfig.json" and exclude
["node_modules","lib","**/__tests__","**/__mocks__"]) or update package.json's
builder config to reference "tsconfig.json" instead; locate the package.json
builder entry referencing "project": "tsconfig.build.json" and choose one of
these fixes, ensuring the final project file name and exclusion rules match the
intended build output.
🧹 Nitpick comments (8)
react-native/package.json (2)
46-53:@types/react-nativemay be unnecessary with React Native 0.73+.React Native 0.73 ships with built-in TypeScript types, so
@types/react-nativeis typically no longer needed and may cause type conflicts.Consider removing `@types/react-native`
"devDependencies": { "@types/react": "^18.2.0", - "@types/react-native": "^0.72.0", "react": "18.2.0", "react-native": "0.73.0", "react-native-builder-bob": "^0.23.0", "typescript": "^5.3.0" },
54-57: Consider specifying minimum peer dependency versions.Using
"*"for peer dependencies is very permissive and may lead to compatibility issues with older versions. Consider specifying minimum supported versions.Specify minimum peer dependency versions
"peerDependencies": { - "react": "*", - "react-native": "*" + "react": ">=17.0.0", + "react-native": ">=0.68.0" },go/bugstr.go (3)
201-213: Unsafe type assertion may panic.At line 210,
data.(string)will panic ifnip19.Decodereturns a non-string type fornpub(though this should be the expected type). Adding a type check makes this more defensive.Suggested safer type assertion
func decodePubkey(pubkey string) string { if pubkey == "" { return "" } if strings.HasPrefix(pubkey, "npub") { prefix, data, err := nip19.Decode(pubkey) if err != nil || prefix != "npub" { return "" } - return data.(string) + hex, ok := data.(string) + if !ok { + return "" + } + return hex } return pubkey }
269-282: Errors from gzip and json operations are silently ignored.While silent failure is often acceptable in crash reporting code, ignoring
gz.Writeandjson.Marshalerrors could mask data corruption. Consider at minimum checking the gzip write error.Minimal error handling suggestion
var buf bytes.Buffer gz := gzip.NewWriter(&buf) - gz.Write([]byte(plaintext)) - gz.Close() + if _, err := gz.Write([]byte(plaintext)); err != nil { + return plaintext // fallback to uncompressed + } + if err := gz.Close(); err != nil { + return plaintext + }
187-194: Empty error handling block is a code smell.The
if sendErr != nilblock is empty. Either remove the error check entirely or use_assignment to make the intentional discard explicit.Cleaner silent discard
go func() { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - if sendErr := sendToNostr(ctx, payload); sendErr != nil { - // Silent failure - don't crash the app due to reporting - } + _ = sendToNostr(ctx, payload) // Silent failure - don't crash the app }()react-native/src/index.ts (2)
222-225: Confusing fallback logic inbeforeSendhandling.The
finalPayload || payloadfallback on line 225 is confusing. IfbeforeSendreturns a valid payload, it should be used directly. The|| payloadfallback only triggers iffinalPayloadis falsy (e.g., empty object), which shouldn't happen given thenullcheck on line 223.Clearer logic
- const finalPayload = config.beforeSend === undefined ? payload : config.beforeSend(payload); - if (finalPayload === null) return; - - await sendToNostr(finalPayload || payload); + const finalPayload = config.beforeSend ? config.beforeSend(payload) : payload; + if (finalPayload === null) return; + + await sendToNostr(finalPayload);
243-251:ErrorUtilsis untyped and may not exist in all environments.
ErrorUtilsis a React Native internal API that isn't typed. Consider adding a type declaration or defensive check.Add defensive check and type declaration
+// React Native global error handler +declare const ErrorUtils: { + getGlobalHandler(): (error: Error, isFatal?: boolean) => void; + setGlobalHandler(handler: (error: Error, isFatal?: boolean) => void): void; +} | undefined; // Install global error handler +if (typeof ErrorUtils !== 'undefined') { const originalHandler = ErrorUtils.getGlobalHandler(); ErrorUtils.setGlobalHandler((error: Error, isFatal?: boolean) => { captureException(error); if (originalHandler) { originalHandler(error, isFatal); } }); +}python/bugstr/__init__.py (1)
383-385: Silent exception swallowing could hinder debugging.While silent failure is appropriate for crash reporting (avoid meta-crashes), consider adding optional debug logging or at least a more specific exception type.
Optional: Add debug logging capability
+import logging + +_logger = logging.getLogger(__name__) except Exception: # Silent failure - don't crash the app - pass + _logger.debug("Failed to send crash report", exc_info=True)The static analysis hint about
try-except-pass(S110) is valid for production code, though the intentional silent failure here is documented.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
go/go.sumis excluded by!**/*.sum
📒 Files selected for processing (13)
README.mdgo/README.mdgo/bugstr.gogo/go.modpython/.gitignorepython/README.mdpython/bugstr/__init__.pypython/pyproject.tomlreact-native/.gitignorereact-native/README.mdreact-native/package.jsonreact-native/src/index.tsreact-native/tsconfig.json
🧰 Additional context used
🧬 Code graph analysis (2)
python/bugstr/__init__.py (1)
test-vectors/validate.js (1)
serialized(149-156)
react-native/src/index.ts (2)
android/src/main/java/com/bugstr/BugstrAnrWatcher.kt (1)
message(82-82)android/bugstr-nostr-crypto/src/main/kotlin/com/bugstr/nostr/crypto/QuartzAdapters.kt (1)
nip44(11-27)
🪛 OSV Scanner (2.3.1)
go/go.mod
[CRITICAL] 1-1: golang.org/x/crypto 0.28.0: Misuse of connection.serverAuthenticate may cause authorization bypass in golang.org/x/crypto
(GO-2024-3321)
[CRITICAL] 1-1: golang.org/x/crypto 0.28.0: Potential denial of service in golang.org/x/crypto
(GO-2025-3487)
[CRITICAL] 1-1: golang.org/x/crypto 0.28.0: Potential denial of service in golang.org/x/crypto/ssh/agent
(GO-2025-4116)
[CRITICAL] 1-1: golang.org/x/crypto 0.28.0: Unbounded memory consumption in golang.org/x/crypto/ssh
(GO-2025-4134)
[CRITICAL] 1-1: golang.org/x/crypto 0.28.0: Malformed constraint may cause denial of service in golang.org/x/crypto/ssh/agent
(GO-2025-4135)
[CRITICAL] 1-1: golang.org/x/crypto 0.28.0: golang.org/x/crypto/ssh/agent vulnerable to panic if message is malformed due to out of bounds read
[CRITICAL] 1-1: golang.org/x/crypto 0.28.0: golang.org/x/crypto Vulnerable to Denial of Service (DoS) via Slow or Incomplete Key Exchange
[CRITICAL] 1-1: golang.org/x/crypto 0.28.0: golang.org/x/crypto/ssh allows an attacker to cause unbounded memory consumption
[CRITICAL] 1-1: golang.org/x/crypto 0.28.0: Misuse of ServerConfig.PublicKeyCallback may cause authorization bypass in golang.org/x/crypto
🪛 Ruff (0.14.11)
python/bugstr/__init__.py
44-51: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
152-152: Avoid specifying long messages outside the exception class
(TRY003)
171-171: Avoid specifying long messages outside the exception class
(TRY003)
246-246: Do not catch blind exception: Exception
(BLE001)
277-277: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
376-377: try-except-pass detected, consider logging the exception
(S110)
376-376: Do not catch blind exception: Exception
(BLE001)
383-385: try-except-pass detected, consider logging the exception
(S110)
383-383: Do not catch blind exception: Exception
(BLE001)
🔇 Additional comments (20)
python/.gitignore (1)
1-6: LGTM! Standard Python ignore patterns.The .gitignore file includes appropriate patterns for Python development artifacts (cache, bytecode, packaging, and build outputs).
python/README.md (1)
1-121: Excellent documentation for the Python SDK.The README is comprehensive and well-organized, covering installation, multiple usage patterns (basic, manual, server mode, confirmation), framework integrations (Django, Flask), features, and configuration. The examples are clear and idiomatic.
go/README.md (1)
1-102: Well-structured documentation for the Go SDK.The README effectively covers installation, usage patterns (including Go-specific goroutine recovery), manual capture, server modes, and configuration. The examples are idiomatic and the structure mirrors the Python SDK documentation for consistency.
README.md (3)
3-3: Clear and concise tagline update.The updated tagline effectively emphasizes the zero-infrastructure and no-SaaS-cost value proposition.
5-5: Simplified and clearer description.The reworded description better explains the NIP-17 encrypted messaging and user consent flow without unnecessary jargon.
16-19: Platform expansion reflects new SDK additions.The platform table correctly documents the new Rust, Go, Python, and React Native SDKs introduced in this PR.
go/go.mod (1)
1-25: Updatego 1.23.1to match the development environment.The
go.moddeclaresgo 1.23.1, but your current environment runsgo 1.25.1. Update the module directive togo 1.25.1to reflect the actual toolchain in use. Additionally, ensure your CI/CD workflows explicitly specify the Go version to prevent consistency issues across environments.react-native/.gitignore (1)
1-3: LGTM!The essential ignores are covered. Optionally, you could add
.DS_Store,coverage/, and*.tsbuildinfofor more complete coverage, but these basics are sufficient.react-native/README.md (1)
1-128: LGTM!The documentation is comprehensive and well-structured, covering installation, usage patterns, configuration options, and payload format. The code examples are clear and follow good practices.
python/pyproject.toml (1)
22-25: Update nostr-sdk constraint to a more recent baseline version.
nostr-sdk>=0.32.0allows versions from 0.32.0 onwards, but the latest available is 0.44.0. The lower bound constraint (0.32.0) is 12 minor versions behind current, indicating the baseline hasn't been updated. Consider updating to at least>=0.40.0or higher if compatible with the implementation.
secp256k1>=0.14.0is already current (0.14.0 is the latest release).Verify compatibility with newer nostr-sdk releases before updating the constraint.
react-native/package.json (1)
43-45: No issues found. Version2.10.0ofnostr-toolsexists on npm and supports both NIP-17 and NIP-44 (NIP-17 was added in v2.9.x, and v2.10.0 switched to NIP-44 for encryption).go/bugstr.go (3)
309-320: Rumor ID computation follows NIP-01 correctly.The serialization format
[0, pubkey, created_at, kind, tags, content]aligns with the NIP-01 specification and matches the pattern intest-vectors/validate.js.
362-378: Relay publishing logic looks correct.The pattern of attempting each relay, returning on first success, and tracking the last error is appropriate for best-effort delivery.
257-262: No action needed—Go 1.23.1 automatically seeds math/rand.This function is safe as-is. Go 1.20 introduced automatic seeding of
math/rand, so explicit seeding is not required. The project targets Go 1.23.1, which is well after that change.react-native/src/index.ts (2)
80-89: NIP-19 decoding implementation is correct.The use of
nip19.decodewith type checking for'npub'is the proper approach.
303-327: Error Boundary implementation is correct.The component properly implements
getDerivedStateFromErrorandcomponentDidCatch, integrates withcaptureException, and supports flexible fallback rendering.python/bugstr/__init__.py (4)
337-346: Rumor ID computation correctly uses compact JSON serialization.The use of
json.dumps(..., separators=(",", ":"))produces the compact JSON format required by NIP-01, matching the pattern intest-vectors/validate.js.
238-248: NIP-19 decoding usingPublicKey.from_bech32is correct.This is the appropriate nostr-sdk method for decoding npub bech32 strings. The broad exception catch is acceptable here as invalid pubkeys should fail gracefully.
273-278: Use ofrandom.randintis acceptable for timestamp fuzzing.The static analysis warning (S311) flags this as unsuitable for cryptographic purposes, but timestamp obfuscation for privacy is not a cryptographic operation. The current usage is appropriate.
371-381: Client relay publishing pattern is reasonable.The connect/send/disconnect pattern wrapped in the outer try-except provides adequate error handling for best-effort crash report delivery.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
|
@coderabbitai review please |
|
🧠 Learnings used✅ Actions performedReview triggered.
|
- Panic hook for automatic crash capture - NIP-17 gift wrap encryption with NIP-44 - Gzip compression for payloads over 1KB - Configurable relays, redaction patterns, consent hooks Closes #6 Signed-off-by: alltheseas <alltheseas@users.noreply.github.com> Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Global sys.excepthook integration - NIP-17 gift wrap encryption with NIP-44 - Gzip compression for payloads over 1KB - Configurable relays, redaction patterns, before_send/confirm_send hooks Closes #7 Signed-off-by: alltheseas <alltheseas@users.noreply.github.com> Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- ErrorBoundary component for declarative error handling - Global ErrorUtils handler integration - Native Alert consent dialog (configurable) - NIP-17 gift wrap encryption with proper NIP-01 rumor id - tsconfig.build.json for react-native-builder-bob Closes #8 Signed-off-by: alltheseas <alltheseas@users.noreply.github.com> Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Go, Python, React Native to platforms table - Document size limits and compression threshold (1KB) - Document gzip envelope format for large payloads - Add compression efficiency table (70-90% reduction) Signed-off-by: alltheseas <alltheseas@users.noreply.github.com> Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
8928ab8 to
0950697
Compare
- Add relay.primal.net (1MB limit) as secondary relay - Document default relays with max message sizes in README - Add relay size compatibility table (64KB=99%, 128KB=90%) - Document 60KB practical limit for universal delivery - Update all SDKs to use: damus (1MB), primal (1MB), nos.lol (128KB) Signed-off-by: alltheseas <alltheseas@users.noreply.github.com> Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Android/Kotlin tested with Zapstore integration (PR #272) - Other platforms marked as "Guinea pigs needed" Signed-off-by: alltheseas <alltheseas@users.noreply.github.com> Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@go/bugstr.go`:
- Around line 201-213: In decodePubkey, the unchecked assertion data.(string)
can panic if nip19.Decode returns a non-string; change the code to perform a
safe type assertion (e.g., s, ok := data.(string)) after calling nip19.Decode
and only return s when ok is true, otherwise return an empty string or handle
the error path; update the branch that checks prefix == "npub" and the result of
nip19.Decode accordingly to avoid panics.
In `@react-native/src/index.ts`:
- Around line 215-236: The confirmation is showing the original payload because
config.beforeSend is currently applied after confirmSend/nativeConfirm; update
maybeSend so it first calls config.beforeSend (awaiting it and handling a null
return to abort) and uses the potentially modified payload to build the
BugstrSummary and pass into config.confirmSend/nativeConfirm, then call
sendToNostr with that same modified payload (or abort if beforeSend returned
null); reference maybeSend, config.beforeSend, config.confirmSend,
nativeConfirm, and sendToNostr to locate the changes.
- Around line 159-170: The nip44.encrypt function is synchronous (returns a
string), so remove the erroneous await operators where it's called: change the
call that assigns sealContent (currently awaiting
nip44.encrypt(JSON.stringify(unsignedKind14), conversationKey)) to a direct
call, and likewise remove await for the call that assigns giftWrapContent
(currently awaiting nip44.encrypt(JSON.stringify(seal), wrapKey)); keep all
other logic (conversationKey, wrapKey, unsignedKind14, seal) unchanged.
In `@README.md`:
- Around line 33-43: The "Default Relays" table in README.md contains incorrect
max message sizes; update the entries for `wss://relay.damus.io` and
`wss://relay.primal.net` to reflect strfry defaults (events.maxEventSize = 65536
bytes and relay.maxWebsocketPayloadSize = 131072 bytes) — i.e. document the
practical limit as ~64–128 KB rather than 1 MB — keep `wss://nos.lol` as 128 KB,
and adjust the Notes column to mention these strfry defaults and that actual
usable event size is typically 64 KB (with websocket payload up to 128 KB).
🧹 Nitpick comments (5)
python/bugstr/__init__.py (2)
273-278: Non-cryptographic random used for timestamp obfuscation.
random.randintis flagged by static analysis (S311) for cryptographic use. However, this is used solely for timestamp jittering to provide metadata privacy, not for cryptographic key generation. The security risk is minimal since predictable timestamps don't compromise message confidentiality.Consider documenting the intent or using
secrets.randbelowif stricter compliance is desired.
371-381: Silent failures aligned with SDK design philosophy.The broad
except Exception: passpatterns (lines 376-377 and 383-385) are intentional per the SDK's "silent failure" design to avoid crashing the host application. While static analysis flags these (S110, BLE001), they're appropriate for crash reporting infrastructure.Consider adding debug-level logging gated by an environment variable for troubleshooting relay connectivity issues.
go/bugstr.go (2)
257-262: Non-cryptographic random used for timestamp jittering.
rand.Int63nuses the defaultmath/randsource, which isn't cryptographically secure. Similar to the Python implementation, this is used for metadata privacy (timestamp obfuscation), not cryptographic purposes, so the risk is minimal.For consistency with ephemeral key generation (which uses
nostr.GeneratePrivateKey), consider usingcrypto/randif stricter requirements apply.
269-282: Ignored error from gzip.Write.Line 271 ignores the error from
gz.Write(). While gzip writing to an in-memory buffer rarely fails, ignoring errors violates Go best practices.Handle gzip write error
func maybeCompress(plaintext string) string { if len(plaintext) < 1024 { return plaintext } var buf bytes.Buffer gz := gzip.NewWriter(&buf) - gz.Write([]byte(plaintext)) - gz.Close() + if _, err := gz.Write([]byte(plaintext)); err != nil { + return plaintext // Fallback to uncompressed + } + if err := gz.Close(); err != nil { + return plaintext + } envelope := CompressedEnvelope{ V: 1, Compression: "gzip", Payload: base64.StdEncoding.EncodeToString(buf.Bytes()), } result, _ := json.Marshal(envelope) return string(result) }react-native/src/index.ts (1)
253-260: Global error handler captures errors but may not await send.The global error handler calls
captureException(error)synchronously, but the actual send is async. If the app crashes immediately after, the report may not be sent. This is a known limitation of crash reporting in JavaScript environments.Consider documenting this behavior or exploring
AppStatelisteners to flush pending reports.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
README.mdgo/bugstr.gopython/bugstr/__init__.pyreact-native/src/index.ts
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: alltheseas/bugstr PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-16T08:05:25.480Z
Learning: Applies to {android,typescript}/**/*.{kt,ts,tsx} : Rumor events in NIP-17/59 implementation must include `sig: ""` (empty string, not omitted) and computed `id` field (SHA256 of serialized event)
📚 Learning: 2026-01-16T08:05:25.480Z
Learnt from: CR
Repo: alltheseas/bugstr PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-16T08:05:25.480Z
Learning: Applies to {android,typescript,dart}/CHANGELOG.md : All user-facing changes require a CHANGELOG.md entry in the respective platform directory (android/, typescript/, dart/) following the format: sections for Added, Changed, and Fixed under [Unreleased]
Applied to files:
react-native/src/index.tsREADME.md
📚 Learning: 2026-01-16T08:05:25.480Z
Learnt from: CR
Repo: alltheseas/bugstr PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-16T08:05:25.480Z
Learning: Applies to {android,typescript}/**/*.{kt,ts,tsx} : Rumor events in NIP-17/59 implementation must include `sig: ""` (empty string, not omitted) and computed `id` field (SHA256 of serialized event)
Applied to files:
react-native/src/index.ts
📚 Learning: 2026-01-16T08:05:25.480Z
Learnt from: CR
Repo: alltheseas/bugstr PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-16T08:05:25.480Z
Learning: Applies to {android,typescript}/**/*.{kt,ts,tsx} : Event serialization for NIP-17 must follow the exact order: `[0, pubkey, created_at, kind, tags, content]` before computing SHA256 id hash
Applied to files:
react-native/src/index.ts
📚 Learning: 2026-01-16T08:05:25.480Z
Learnt from: CR
Repo: alltheseas/bugstr PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-16T08:05:25.480Z
Learning: Applies to {android,typescript}/**/*.{kt,ts,tsx} : Seal events in NIP-59 must be signed by the sender's key
Applied to files:
react-native/src/index.ts
📚 Learning: 2026-01-16T08:05:25.480Z
Learnt from: CR
Repo: alltheseas/bugstr PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-16T08:05:25.480Z
Learning: Applies to {android,typescript}/**/*.{kt,ts,tsx} : Event ID computation must return a lowercase hex string (64 characters) using SHA256 hash of the serialized event
Applied to files:
react-native/src/index.ts
📚 Learning: 2026-01-16T08:05:25.480Z
Learnt from: CR
Repo: alltheseas/bugstr PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-16T08:05:25.480Z
Learning: Applies to {android,typescript}/**/*.{kt,ts,tsx} : Gift wrap events in NIP-59 must be signed by an ephemeral key
Applied to files:
react-native/src/index.ts
🧬 Code graph analysis (1)
python/bugstr/__init__.py (5)
android/bugstr-nostr-crypto/src/main/kotlin/com/bugstr/nostr/crypto/QuartzAdapters.kt (1)
nip44(11-27)go/bugstr.go (2)
Config(38-63)Payload(66-72)android/src/main/java/com/bugstr/BugstrAnrWatcher.kt (1)
message(82-82)react-native/src/index.ts (1)
init(245-261)test-vectors/validate.js (1)
serialized(149-156)
🪛 Ruff (0.14.11)
python/bugstr/__init__.py
44-51: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
152-152: Avoid specifying long messages outside the exception class
(TRY003)
171-171: Avoid specifying long messages outside the exception class
(TRY003)
246-246: Do not catch blind exception: Exception
(BLE001)
277-277: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
376-377: try-except-pass detected, consider logging the exception
(S110)
376-376: Do not catch blind exception: Exception
(BLE001)
383-385: try-except-pass detected, consider logging the exception
(S110)
383-383: Do not catch blind exception: Exception
(BLE001)
🔇 Additional comments (13)
python/bugstr/__init__.py (5)
36-41: LGTM - Graceful degradation for missing dependency.The try/except pattern for importing
nostr_sdkwith theHAS_NOSTRflag allows the module to be imported without crashing, deferring the error to initialization time.
65-89: LGTM - Config dataclass is well-structured.The configuration mirrors the Go SDK's
Configstruct with appropriate Python idioms. Default factory patterns for mutable defaults (lists) are correctly used.
91-109: LGTM - Payload dataclass with proper serialization.The
to_dictmethod correctly omits optional fields when not present, matching the Go SDK'sjson:",omitempty"behavior.
327-346: LGTM - Rumor construction follows NIP-01/NIP-17 correctly.The rumor includes:
sig: ""(empty string, not omitted) per NIP-17 requirements- Computed
idfield via SHA-256 of[0, pubkey, created_at, kind, tags, content]with compact JSON serializationThis matches the learnings and is consistent with the Go and React Native implementations. Based on learnings, this is the correct approach.
350-357: API usage is correct for nostr-sdk>=0.32.0.The
EventBuilderAPI withcustom_created_at()chained toto_event()is valid and documented for the version specified in the project (nostr-sdk>=0.32.0). The pattern is confirmed in Python nostr-sdk examples and the method chain is properly supported.go/bugstr.go (3)
298-320: LGTM - Rumor construction follows NIP-01/NIP-17 correctly.The rumor includes:
sig: ""(empty string, not omitted) at line 306- Computed
idvia SHA-256 of[0, pubkey, created_at, kind, tags, content]at lines 309-320This correctly implements the NIP-01 event ID computation and aligns with the retrieved learnings. Based on learnings, this is the correct serialization order.
362-376: LGTM - Relay publishing with fail-fast on success.The relay iteration correctly:
- Attempts each relay sequentially
- Returns immediately on first successful publish
- Properly closes relay connections
- Tracks the last error for reporting
This is a reasonable strategy for crash reporting where delivery to any single relay suffices.
333-339: No action required—seal event signing is correct.The
Signmethod in go-nostr v0.42.0 automatically populates thePubKeyfield by deriving it from the provided private key. Callingseal.Sign(senderPrivkey)correctly sets the PubKey, ID, and signature fields. The code follows the standard pattern and complies with NIP-59 requirements for seal events.Likely an incorrect or invalid review comment.
react-native/src/index.ts (2)
141-157: LGTM - Rumor ID computation addressed correctly.The implementation now:
- Uses
getEventHash(rumorEvent)from nostr-tools to compute the rumor ID per NIP-01- Includes
sig: ''(empty string) per NIP-17 requirementsThis addresses the previous review comment and aligns with the retrieved learnings. Based on learnings, this correctly implements rumor event requirements.
313-337: LGTM - ErrorBoundary implementation is correct.The ErrorBoundary:
- Properly implements
getDerivedStateFromErrorandcomponentDidCatch- Captures errors with component stack info
- Supports both static fallback and render-prop fallback patterns
- Calls optional
onErrorcallback for custom handlingThis is a well-structured React error boundary pattern.
README.md (3)
11-19: LGTM - Platform table updated correctly.The table now includes all new SDKs (Go, Python, React Native) with appropriate status indicators and directory links. The "Guinea pigs needed" notation clearly indicates testing status.
57-60: Compression threshold matches implementation.The documentation states payloads < 1 KB are sent as plain JSON, ≥ 1 KB are compressed. This matches the
maybeCompressfunctions in both Go (line 265:len(plaintext) < 1024) and Python (line 283:len(plaintext.encode()) < 1024).
97-103: LGTM - Critical NIP-17 requirements documented.The documentation correctly specifies that rumors must include:
idcomputed as SHA256 of the serialization arraysig: ""as empty string (not omitted)This aligns with the retrieved learnings and helps future contributors avoid compliance issues. Based on learnings, this is accurate documentation.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
Upgrades the Dart SDK from skeleton to full implementation: - Add BugstrConfig with default relays (damus, primal, nos.lol) - Add CrashPayload with auto-redaction for sensitive data - Add Bugstr client with NIP-17 gift-wrapped crash reporting - Use ndk package for NIP-44 encryption and NIP-59 gift wrap - Auto-install Flutter error handlers on init() - Support beforeSend and confirmSend hooks - Random timestamps within ±2 days for privacy Signed-off-by: alltheseas Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: alltheseas Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add Go, Python, React Native, Rust to supported platforms table, project structure, and documentation format guidelines. Signed-off-by: alltheseas Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
@coderabbitai please review latest commits |
|
🧠 Learnings used✅ Actions performedReview triggered.
|
Go: - Use safe type assertion in decodePubkey to prevent panic React Native: - Remove erroneous await from synchronous nip44.encrypt calls - Apply beforeSend hook before confirmSend so confirmation shows the modified payload Docs: - Correct relay size limits to strfry defaults (64KB event, 128KB websocket) instead of incorrect 1MB values Signed-off-by: alltheseas Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
PR #5 adds three new SDKs:
Plus fixes:
Total: +1,767 lines across 15 files
All three SDKs follow the same pattern:
Summary
nip19.Decodeusage (was using non-existentnostr.DecodeBech32)Test plan
go build ./...compiles successfully🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.