Skip to content

Staging#3

Merged
AustinKelsay merged 7 commits intomasterfrom
staging
Oct 8, 2025
Merged

Staging#3
AustinKelsay merged 7 commits intomasterfrom
staging

Conversation

@AustinKelsay
Copy link
Copy Markdown
Member

@AustinKelsay AustinKelsay commented Oct 7, 2025

Summary by CodeRabbit

  • New Features

    • Echo confirmation integrated across share workflows with real-time statuses (listening/waiting, success) and credential display in saving and summary views.
    • New echo-sending utility exported for reuse; echo flow supports optional challenge generation.
    • Public API additions: a connectNode helper and an updated sendEcho signature now requiring a challenge.
  • Documentation

    • Rewritten developer guidance covering project structure, build/dev/test flows, style, testing, commits, and security; updated echo usage examples.
  • Chores

    • Bumped an internal dependency patch version.

AustinKelsay and others added 3 commits October 4, 2025 15:10
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 7, 2025

Walkthrough

Adds end-to-end echo signaling: a new sendShareEcho helper and export, a cancellable retrying useShareEchoListener hook, UI integrations to send and display echo status in ShareAdd/ShareSaver/KeysetLoad, API docs updates (connectNode and changed sendEcho signature), and a dependency bump for @frostr/igloo-core.

Changes

Cohort / File(s) Summary
Documentation
AGENTS.md
Rewrites guidance on project structure, build/dev/test commands, coding style, testing, commit/PR practices, and security; documentation-only edits.
Core API docs
llm/context/igloo-core-readme.md
Adds connectNode(node): Promise<void> and updates sendEcho signature to require challenge: string; updates examples and notes on hex challenge generation/format.
Dependency
package.json
Bumps @frostr/igloo-core from ^0.2.0 to ^0.2.3.
Echo sending API
src/keyset/echo.ts
New module exporting sendShareEcho(groupCredential, shareCredential, {relays, challenge, timeout, eventConfig}) and SendShareEchoOptions; generates 32-byte hex challenge when omitted and calls igloo-core sendEcho.
Public keyset exports
src/keyset/index.ts
Re-exports ./echo.js to expose sendShareEcho.
Echo listener hook
src/components/keyset/useShareEchoListener.ts
New exported hook useShareEchoListener(group?, share?, options?) with EchoStatus union and configurable timeout/retry/backoff; returns { status, message, retry }.
Keyset load UI
src/components/keyset/KeysetLoad.tsx
Wires useShareEchoListener to decrypted credentials and renders listening/success messages and echo details.
Share saver UI
src/components/keyset/ShareSaver.tsx
Subscribes to useShareEchoListener, adds credential display blocks and conditional echo-status UI across saving/summary/automated flows.
Share add flow
src/components/share/ShareAdd.tsx
Adds mounted-safety guards and calls sendShareEcho after successful save/import; tracks and renders pending/success/error echo states and errors.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant SA as ShareAdd (UI)
  participant KS as src/keyset/echo
  participant IC as igloo-core.sendEcho
  participant NET as Network/Relays
  participant EL as useShareEchoListener
  participant KV as KeysetLoad/ShareSaver (UI)

  User->>SA: Save / import share
  SA->>KS: sendShareEcho(groupCred, shareCred)
  KS->>KS: ensure 32-byte hex challenge
  KS->>IC: sendEcho(groupCred, shareCred, challenge, {relays, timeout})
  IC->>NET: publish echo request
  NET-->>(Receiver): deliver challenge

  KV->>EL: start listening(groupCred, shareCred)
  EL->>NET: awaitShareEcho(..., timeout)
  alt Echo received
    NET-->>EL: echo confirmation
    EL-->>KV: status = success
    KV-->>User: show "Echo confirmed"
  else Timeout / Retry
    EL-->>EL: retry with backoff (up to maxRetries)
    EL-->>KV: status = listening, message updates
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Poem

A rabbit hops with hex in paw,
I send a challenge, quiet and raw.
Listeners wait, retry, then cheer,
A green blink says the echo’s here. 🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The title “Staging” does not convey the primary changes in the pull request, which include documentation rewrites, new public APIs, and UI updates for echo functionality across multiple components. It is too generic to inform reviewers about the scope or intent of the changeset. Please update the title to clearly reflect the main change, for example “Add echo listener hook and integrate echo UI updates” or another concise summary that captures the core enhancements in this PR.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch staging

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 81d1ec8 and 8477267.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • AGENTS.md (1 hunks)
  • llm/context/igloo-core-readme.md (3 hunks)
  • package.json (1 hunks)
  • src/components/keyset/KeysetLoad.tsx (3 hunks)
  • src/components/keyset/ShareSaver.tsx (6 hunks)
  • src/components/keyset/useShareEchoListener.ts (1 hunks)
  • src/components/share/ShareAdd.tsx (6 hunks)
  • src/keyset/echo.ts (1 hunks)
  • src/keyset/index.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

All import specifiers must include .js extensions (TypeScript ESM requirement) even though source files are .ts/.tsx

Files:

  • src/keyset/index.ts
  • src/components/keyset/KeysetLoad.tsx
  • src/keyset/echo.ts
  • src/components/keyset/ShareSaver.tsx
  • src/components/keyset/useShareEchoListener.ts
  • src/components/share/ShareAdd.tsx
src/keyset/**

📄 CodeRabbit inference engine (AGENTS.md)

Place key material flow logic under src/keyset/

Files:

  • src/keyset/index.ts
  • src/keyset/echo.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Stick to TypeScript + ESM, using 2-space indentation
Use single quotes for strings
Use trailing commas where valid
Sort imports shallow-to-deep
Name utility functions with camelCase
Name constants with SCREAMING_SNAKE_CASE

Files:

  • src/keyset/index.ts
  • src/components/keyset/KeysetLoad.tsx
  • src/keyset/echo.ts
  • src/components/keyset/ShareSaver.tsx
  • src/components/keyset/useShareEchoListener.ts
  • src/components/share/ShareAdd.tsx
src/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Use Ink components (, , etc.) for terminal UI and do not use HTML elements

Files:

  • src/components/keyset/KeysetLoad.tsx
  • src/components/keyset/ShareSaver.tsx
  • src/components/share/ShareAdd.tsx
src/components/**

📄 CodeRabbit inference engine (CLAUDE.md)

All UI components should live under src/components/

Place reusable view code under src/components/

Files:

  • src/components/keyset/KeysetLoad.tsx
  • src/components/keyset/ShareSaver.tsx
  • src/components/keyset/useShareEchoListener.ts
  • src/components/share/ShareAdd.tsx
src/components/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

When adding a new command, implement it as a component under src/components/

Files:

  • src/components/keyset/KeysetLoad.tsx
  • src/components/keyset/ShareSaver.tsx
  • src/components/share/ShareAdd.tsx
src/components/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Name React/Ink components with PascalCase

Files:

  • src/components/keyset/KeysetLoad.tsx
  • src/components/keyset/ShareSaver.tsx
  • src/components/keyset/useShareEchoListener.ts
  • src/components/share/ShareAdd.tsx
llm/**

📄 CodeRabbit inference engine (AGENTS.md)

Prompts and automation cues live in llm/; update them when UX or protocol semantics change

Files:

  • llm/context/igloo-core-readme.md
🧬 Code graph analysis (3)
src/components/keyset/KeysetLoad.tsx (1)
src/components/keyset/useShareEchoListener.ts (1)
  • useShareEchoListener (44-222)
src/components/keyset/ShareSaver.tsx (1)
src/components/keyset/useShareEchoListener.ts (1)
  • useShareEchoListener (44-222)
src/components/share/ShareAdd.tsx (1)
src/keyset/echo.ts (1)
  • sendShareEcho (14-27)
🔇 Additional comments (16)
package.json (1)

26-26: LGTM!

Patch version bump to align with the new echo API signature that requires a challenge parameter.

AGENTS.md (1)

4-19: LGTM!

Documentation improvements provide clear, actionable guidance for contributors. The expanded prose better explains project structure, workflows, and best practices.

src/keyset/index.ts (1)

7-7: LGTM!

Re-exports echo functionality to extend the public API surface. Follows the established pattern and includes the required .js extension.

As per coding guidelines

src/components/keyset/KeysetLoad.tsx (3)

6-6: LGTM!

Correct import with required .js extension.

As per coding guidelines


63-68: LGTM!

Correct usage of useShareEchoListener hook. The hook accepts optional/nullable parameters and will gracefully handle the case when result is null by setting status to 'idle'.


222-234: Minor: Handle undefined shareIndex more explicitly.

Line 226 could display "share undefined" if shareIndex is undefined (though this is an edge case). Consider making the share index display optional.

Apply this diff to handle undefined shareIndex more gracefully:

           <Text color="cyan">
-            Waiting for echo confirmation{shareIndex !== undefined ? ` on share ${shareIndex}` : ''}…
+            Waiting for echo confirmation{shareIndex !== undefined ? ` on share ${shareIndex}` : ' on this share'}…
           </Text>

Likely an incorrect or invalid review comment.

llm/context/igloo-core-readme.md (1)

317-342: LGTM!

Documentation correctly reflects the updated sendEcho API signature that now requires a challenge parameter. Examples demonstrate proper cryptographically secure challenge generation using randomBytes(32).

src/keyset/echo.ts (1)

1-27: LGTM!

Solid implementation of the echo signaling feature:

  • Uses cryptographically secure randomBytes(32) for challenge generation (64 hex characters)
  • Properly integrates with the updated sendEcho API from @frostr/igloo-core@0.2.1
  • Reasonable default timeout (10 seconds)
  • Correct handling of optional parameters with sensible fallbacks

As per coding guidelines

src/components/keyset/ShareSaver.tsx (4)

18-18: LGTM!

Correct import with required .js extension.

As per coding guidelines


77-80: LGTM!

Correct usage of useShareEchoListener. The hook handles undefined for share?.credential gracefully and will set status to 'idle' when the share is not available.


82-94: LGTM!

Well-structured UI blocks and echo status rendering:

  • Credential blocks are reusable and consistently formatted
  • renderEchoStatus properly checks if share exists before accessing share.index (line 215)
  • Conditional rendering based on echoStatus is clear and comprehensive

Also applies to: 214-236


317-319: LGTM!

Echo status UI is properly integrated into all relevant flows (saving, done, and main view). Consistent use of credential blocks improves code reusability and maintainability.

Also applies to: 329-331, 348-350

src/components/share/ShareAdd.tsx (4)

1-1: LGTM!

Correct imports with required .js extension for ESM.

As per coding guidelines

Also applies to: 20-20


84-85: LGTM!

Proper state management for echo lifecycle:

  • echoStatus tracks the lifecycle stages ('idle' | 'pending' | 'success' | 'error')
  • isMountedRef pattern prevents memory leaks by guarding state updates after unmount

Also applies to: 92-98


309-310: LGTM!

Solid echo lifecycle implementation:

  • Echo state is properly reset before starting the save flow
  • Asynchronous echo send after successful save is appropriate
  • Mounted checks (lines 359, 364) prevent state updates after unmount
  • Error handling captures and surfaces failures gracefully

Also applies to: 354-370


530-540: LGTM!

Echo status UI provides clear feedback for all states (pending, success, error). Error messages include details when available, improving debuggability.

@AustinKelsay
Copy link
Copy Markdown
Member Author

@CodeRabbit full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 7, 2025

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
llm/context/igloo-core-readme.md (1)

338-363: Document the breaking change and provide migration guidance.

Adding a required challenge parameter to sendEcho is a breaking API change. Consider:

  1. Adding a migration section explaining how to update existing code
  2. Documenting the security purpose of the challenge parameter
  3. Mentioning the version where this change was introduced
  4. Providing guidance on challenge generation best practices (e.g., why 32 bytes, entropy requirements)

Example migration note:

**Breaking Change in v0.2.0**: `sendEcho` now requires a `challenge` parameter for replay attack prevention. Update your code:

```diff
- await sendEcho(groupCredential, shareCredential, { relays });
+ const challenge = randomBytes(32).toString('hex');
+ await sendEcho(groupCredential, shareCredential, challenge, { relays });

</blockquote></details>

</blockquote></details>
🧹 Nitpick comments (1)
src/components/keyset/useShareEchoListener.ts (1)

35-42: Consider stricter relay validation.

The type guard allows empty strings to slip through the typeof item === 'string' check before failing on item.length > 0. While the function correctly returns undefined in this case, consider validating relay URL format (e.g., starts with wss:// or ws://) for more robust error detection.

 function extractRelays(decoded: unknown): string[] | undefined {
   const obj = decoded as DecodedGroup;
   const candidate = obj?.relays ?? obj?.relayUrls ?? obj?.relay_urls;
-  if (Array.isArray(candidate) && candidate.every(item => typeof item === 'string' && item.length > 0)) {
+  if (Array.isArray(candidate) && candidate.every(item => 
+    typeof item === 'string' && 
+    item.length > 0 && 
+    (item.startsWith('wss://') || item.startsWith('ws://'))
+  )) {
     return candidate;
   }
   return undefined;
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8477267 and 5cc705c.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • llm/context/igloo-core-readme.md (5 hunks)
  • package.json (1 hunks)
  • src/components/keyset/useShareEchoListener.ts (1 hunks)
  • src/keyset/echo.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • package.json
  • src/keyset/echo.ts
🧰 Additional context used
📓 Path-based instructions (5)
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

All import specifiers must include .js extensions (TypeScript ESM requirement) even though source files are .ts/.tsx

Files:

  • src/components/keyset/useShareEchoListener.ts
src/components/**

📄 CodeRabbit inference engine (CLAUDE.md)

All UI components should live under src/components/

Place reusable view code under src/components/

Files:

  • src/components/keyset/useShareEchoListener.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Stick to TypeScript + ESM, using 2-space indentation
Use single quotes for strings
Use trailing commas where valid
Sort imports shallow-to-deep
Name utility functions with camelCase
Name constants with SCREAMING_SNAKE_CASE

Files:

  • src/components/keyset/useShareEchoListener.ts
src/components/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Name React/Ink components with PascalCase

Files:

  • src/components/keyset/useShareEchoListener.ts
llm/**

📄 CodeRabbit inference engine (AGENTS.md)

Prompts and automation cues live in llm/; update them when UX or protocol semantics change

Files:

  • llm/context/igloo-core-readme.md
🔇 Additional comments (7)
llm/context/igloo-core-readme.md (2)

260-277: LGTM!

The documentation clearly explains the purpose and usage of connectNode, including proper error handling with NodeError. The example demonstrates the recommended pattern.


1028-1028: LGTM!

The API reference correctly reflects the updated sendEcho signature with the challenge parameter.

src/components/keyset/useShareEchoListener.ts (5)

1-2: LGTM!

Imports correctly include .js extensions as required by TypeScript ESM.


81-98: LGTM!

The clearPending callback properly cleans up all resources (controller, retry timeout, warning timeout, fallback timeout), preventing memory leaks.


217-223: LGTM!

The effect properly manages the listening lifecycle with cleanup on unmount. The trigger dependency enables the retry mechanism.


44-230: Overall hook structure is solid, but critical upstream bug needs attention.

The hook demonstrates good React patterns:

  • ✅ Proper use of useCallback, useMemo, and useEffect
  • ✅ Thorough resource cleanup
  • ✅ Clear TypeScript typing
  • ✅ Addresses previous review feedback about preserving fallback warning

However, the fallback workaround for the awaitShareEcho bug (lines 142-153) should be temporary. This critical library bug needs to be resolved upstream rather than worked around in application code.


133-173: Verify awaitShareEcho upstream bug documentation

We found no references in the codebase indicating this “doesn’t resolve” bug. Please confirm:

  • Is the issue documented in the @frostr/igloo-core issue tracker?
  • Is there an open fix or upcoming release that addresses it?
  • Should we plan to remove this fallback once the library is patched?

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/components/keyset/useShareEchoListener.ts (2)

2-2: Remove unused imports.

The imports createAndConnectNode and cleanupBifrostNode are not used anywhere in this file.

Apply this diff:

-import {awaitShareEcho, decodeGroup, createAndConnectNode, cleanupBifrostNode} from '@frostr/igloo-core';
+import {awaitShareEcho, decodeGroup} from '@frostr/igloo-core';

224-224: Add trailing comma for consistency.

Per the coding guidelines, trailing commas should be used where valid.

As per coding guidelines.

Apply this diff:

-    relays
+    relays,
+    maxBackoffMs,
   ]);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5cc705c and fa75733.

📒 Files selected for processing (1)
  • src/components/keyset/useShareEchoListener.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

All import specifiers must include .js extensions (TypeScript ESM requirement) even though source files are .ts/.tsx

Files:

  • src/components/keyset/useShareEchoListener.ts
src/components/**

📄 CodeRabbit inference engine (CLAUDE.md)

All UI components should live under src/components/

Place reusable view code under src/components/

Files:

  • src/components/keyset/useShareEchoListener.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Stick to TypeScript + ESM, using 2-space indentation
Use single quotes for strings
Use trailing commas where valid
Sort imports shallow-to-deep
Name utility functions with camelCase
Name constants with SCREAMING_SNAKE_CASE

Files:

  • src/components/keyset/useShareEchoListener.ts
src/components/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Name React/Ink components with PascalCase

Files:

  • src/components/keyset/useShareEchoListener.ts
🔇 Additional comments (8)
src/components/keyset/useShareEchoListener.ts (8)

4-37: LGTM! Type definitions are clear and well-documented.

The type definitions are clean, well-structured, and thoroughly documented. The flexible DecodedGroup type appropriately handles various relay field naming conventions.


39-46: LGTM! Robust relay extraction with multiple fallbacks.

The helper correctly handles various relay field naming conventions and includes proper type guards to ensure all items are non-empty strings.


48-72: LGTM! Clean hook signature and comprehensive state management.

The hook signature is well-typed with sensible defaults. The state management includes all necessary refs for controlling the listening lifecycle, timeouts, and retry logic. The fallbackTriggeredRef properly addresses the previous review feedback.


73-84: LGTM! Proper memoization with safe error handling.

The relays extraction is correctly memoized and gracefully handles decode failures with a silent fallback to undefined.


86-103: LGTM! Comprehensive cleanup logic.

The clearPending callback properly cancels the controller and clears all timeout references, ensuring no leaked timers or operations.


227-233: LGTM! Proper effect lifecycle management.

The effect correctly starts listening when dependencies change and ensures cleanup on unmount. The trigger dependency enables the manual retry mechanism.


235-237: LGTM! Simple and correct retry mechanism.

The retry callback correctly uses a functional state update to increment the trigger, which forces the listening effect to restart.


239-239: LGTM! Return value matches signature.

The hook correctly returns the expected interface with status, message, and retry function.

@FROSTR-ORG FROSTR-ORG deleted a comment from coderabbitai bot Oct 8, 2025
@FROSTR-ORG FROSTR-ORG deleted a comment from coderabbitai bot Oct 8, 2025
@AustinKelsay
Copy link
Copy Markdown
Member Author

@CodeRabbit full review

@FROSTR-ORG FROSTR-ORG deleted a comment from coderabbitai bot Oct 8, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 8, 2025

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/components/keyset/useShareEchoListener.ts (3)

2-2: Remove unused imports.

createAndConnectNode and cleanupBifrostNode are imported but never used in this file.

Apply this diff:

-import {awaitShareEcho, decodeGroup, createAndConnectNode, cleanupBifrostNode} from '@frostr/igloo-core';
+import {awaitShareEcho, decodeGroup} from '@frostr/igloo-core';

120-124: Consider resetting retry counter on manual retry.

When a user explicitly calls retry(), the retryCountRef counter is not reset unless the share credential changes. If the maximum retry limit has been reached (line 184), a manual retry will start a new attempt but immediately give up on the first failure since the counter is still at the limit.

This may be confusing for users who expect retry() to provide a fresh start. Consider resetting the counter when retry() is called.

Apply this diff to reset the counter on manual retry:

   const retry = useCallback(() => {
+    retryCountRef.current = 0;
     setTrigger(current => current + 1);
   }, []);

Also applies to: 236-238


147-157: Consider making the fallback timeout configurable.

The 15-second fallback timeout is hardcoded (line 157) to work around the awaitShareEcho resolution issue. While this is pragmatic, making it configurable (like timeoutMs, warningAfterMs, etc.) would provide more flexibility and consistency with other timeout options.

Example implementation:

Add to UseShareEchoListenerOptions:

/**
 * Fallback timeout when awaitShareEcho doesn't resolve.
 */
fallbackTimeoutMs?: number;

Add to function signature:

{
  timeoutMs = 5 * 60_000,
  retryDelayMs = 5_000,
  warningAfterMs = 60_000,
  maxRetries = 5,
  maxBackoffMs = 2 * 60_000,
  fallbackTimeoutMs = 15_000
}: UseShareEchoListenerOptions = {}

Then use the parameter on line 157:

}, fallbackTimeoutMs);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 81d1ec8 and 5e2fc62.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • AGENTS.md (1 hunks)
  • llm/context/igloo-core-readme.md (5 hunks)
  • package.json (1 hunks)
  • src/components/keyset/KeysetLoad.tsx (3 hunks)
  • src/components/keyset/ShareSaver.tsx (6 hunks)
  • src/components/keyset/useShareEchoListener.ts (1 hunks)
  • src/components/share/ShareAdd.tsx (6 hunks)
  • src/keyset/echo.ts (1 hunks)
  • src/keyset/index.ts (1 hunks)
🔇 Additional comments (26)
package.json (1)

26-26: LGTM! Dependency version aligns with new echo functionality.

The upgrade to @frostr/igloo-core@^0.2.3 is appropriate for the echo signaling features introduced in this PR. Based on learnings, v0.2.3 is the latest release (Oct 7, 2025) and includes the new connectNode API and updated sendEcho signature used throughout this PR.

src/keyset/index.ts (1)

7-7: LGTM! Public API extension for echo functionality.

The re-export of ./echo.js appropriately extends the keyset module's public API to include the new echo signaling capabilities (sendShareEcho and SendShareEchoOptions).

src/components/keyset/KeysetLoad.tsx (3)

6-6: LGTM! Proper import of the echo listener hook.

The import correctly brings in the useShareEchoListener hook for integration with the decrypted credentials.


63-68: LGTM! Correct hook integration with decrypted credentials.

The hook is properly invoked with the decrypted group and share credentials. The null-safe extraction pattern ensures the hook receives appropriate values even when result is not yet available.


222-234: LGTM! Clear echo status feedback in the UI.

The conditional rendering appropriately displays:

  • "Waiting for echo confirmation..." during listening state with optional warning messages
  • "Echo confirmed by the receiving device" on success

The UX clearly communicates echo state to the user.

src/components/keyset/ShareSaver.tsx (4)

77-80: LGTM! Proper hook integration with current share.

The useShareEchoListener hook is correctly invoked with the group credential and the current share's credential, enabling real-time echo status tracking for the share being saved.


82-94: LGTM! Reusable UI blocks for consistent credential display.

The shareCredentialBlock and groupCredentialBlock components promote consistency across the various phases (saving, done, main view) and reduce duplication.


214-236: LGTM! Clear echo status rendering with appropriate styling.

The renderEchoStatus function:

  • Safely handles the case when share is null
  • Displays "listening" state with share index and optional warning messages
  • Shows success confirmation with a checkmark and bold green text

The UX clearly communicates echo state to the user.


317-320: LGTM! Consistent integration across all phases.

The credential blocks and echo status are consistently rendered in:

  • The saving phase (lines 317-320)
  • The done phase (lines 329-331)
  • The main flow (lines 348-350)

This ensures users always see credentials and echo status regardless of which path they're in.

Also applies to: 329-331, 348-350

src/keyset/echo.ts (5)

1-2: LGTM! Correct imports from igloo-core.

The imports correctly bring in sendEcho, DEFAULT_ECHO_RELAYS, and NodeEventConfig from @frostr/igloo-core, aligning with the API documented in the PR's igloo-core README updates.


4-9: LGTM! Well-structured options type.

The SendShareEchoOptions type appropriately provides optional configuration for relays, challenge, timeout, and event config, giving callers flexibility in how they invoke the echo signaling.


21-21: LGTM! Cryptographically secure challenge generation.

Using randomBytes(32) from Node.js's crypto module provides a cryptographically secure 32-byte (64 hex character) challenge, which is appropriate for echo signaling.


24-31: LGTM! Proper default handling and event config.

The function correctly:

  • Falls back to DEFAULT_ECHO_RELAYS when relays are not provided
  • Applies the timeout parameter
  • Merges the provided eventConfig with a default that disables logging, allowing callers to override if needed

11-32: Update API version reference and verify sendEcho signature

  • Change the doc comment to reference @frostr/igloo-core@0.2.3 instead of 0.2.1.
  • Ensure the sendEcho(groupCredential, shareCredential, challenge, options?) signature in the installed @frostr/igloo-core v0.2.3 matches this call to avoid runtime errors.
AGENTS.md (1)

1-19: LGTM! Documentation improvements for developer guidance.

The rewrites consolidate guidance sections into clearer prose, updating references to project structure, build commands, coding style, testing, commits, and security practices. These changes improve readability without altering functional logic.

src/components/share/ShareAdd.tsx (6)

1-1: LGTM! Proper imports for echo lifecycle and memory safety.

The imports correctly bring in:

  • useRef for tracking component mount state
  • sendShareEcho for triggering the echo signal after save

Also applies to: 19-20


84-85: LGTM! Clear echo state tracking.

The echo state variables (echoStatus and echoError) provide fine-grained tracking of the echo lifecycle with four states: 'idle', 'pending', 'success', and 'error'.


92-98: LGTM! Proper memory safety pattern with isMountedRef.

The isMountedRef pattern correctly:

  • Initializes to true on mount
  • Sets to false on unmount via cleanup function
  • Enables guarding state updates in async operations to prevent updates after unmount

309-310: LGTM! Proper echo state reset before save.

Resetting echoStatus to 'idle' and clearing echoError ensures a clean slate before starting the save operation and subsequent echo signaling.


354-370: LGTM! Memory-safe async echo sending with error handling.

The async echo sending:

  • Sets status to 'pending' before starting
  • Guards state updates with isMountedRef.current checks to prevent updates after unmount
  • Handles both success and error cases
  • Captures error messages for user feedback

This pattern prevents the common React anti-pattern of updating state after component unmount.


530-540: LGTM! Clear echo status feedback in the done phase.

The UI appropriately displays:

  • "Sending echo confirmation..." during pending state
  • "Echo confirmation sent to the originating device" on success
  • Error message with details on failure

The feedback keeps users informed about the echo signaling process.

llm/context/igloo-core-readme.md (4)

260-277: LGTM! Clear documentation for the new connectNode helper.

The documentation accurately describes connectNode as:

  • A safe wrapper around BifrostNode.connect()
  • Surfacing handshake failures as NodeError instances
  • Awaiting the underlying connection promise
  • Enabling proper error handling in CLI/UI code

The code example demonstrates proper usage with try-catch for NodeError.


290-290: LGTM! Helpful closeNode behavior clarification.

The note clarifies that closeNode now monitors Nostr shutdown and emits appropriate events for unexpected relay disconnects while silencing routine teardown cases. This helps developers understand the improved error handling.


338-363: LGTM! Accurate documentation for the updated sendEcho signature.

The documentation correctly reflects the API change:

  • The challenge parameter is now required (not optional)
  • Example shows generating a 32-byte (64 hex char) challenge using randomBytes(32)
  • The note on line 363 specifies the challenge must be an even-length hexadecimal string with a 32-byte/64-char recommendation

This aligns with the usage in src/keyset/echo.ts.


1028-1028: Documentation matches implementation in echo.ts.

Line 1028 correctly documents the new sendEcho signature with the required challenge parameter, matching the usage in src/keyset/echo.ts (line 24).

src/components/keyset/useShareEchoListener.ts (1)

1-241: All past review comments have been addressed!

The implementation now correctly:

  • Preserves the fallback warning message using fallbackTriggeredRef (lines 72, 118, 153, 172-176)
  • Caps exponential backoff at maxBackoffMs (lines 193-194)
  • Clears existing retry timeouts before scheduling new ones (lines 195-198)
  • Includes maxBackoffMs in the dependency array (line 224)

Great work addressing the previous feedback!

@AustinKelsay AustinKelsay merged commit fd8941d into master Oct 8, 2025
1 check passed
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