Skip to content

echo implementation in keyset create flow, update igloo-core to latest version to support#2

Merged
AustinKelsay merged 2 commits intostagingfrom
feature/echo
Oct 4, 2025
Merged

echo implementation in keyset create flow, update igloo-core to latest version to support#2
AustinKelsay merged 2 commits intostagingfrom
feature/echo

Conversation

@AustinKelsay
Copy link
Copy Markdown
Member

@AustinKelsay AustinKelsay commented Oct 4, 2025

Summary by CodeRabbit

  • New Features

    • Added echo confirmation workflow for share operations with real-time status (waiting, messages, success) and retry behavior.
    • UI now surfaces per-share and group credential blocks during saving, completion, and summary views.
  • Documentation

    • Updated contributor and usage guides (structure, commands, style, testing, commits, security).
    • Revised echo API docs: sendEcho now requires a 64-hex-character challenge and includes examples.
  • Chores

    • Bumped core dependency to the latest patch release.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 4, 2025

Walkthrough

Adds share-echo functionality: a sendShareEcho utility and export, a useShareEchoListener React hook (with retry/backoff/warnings), UI integrations in KeysetLoad, ShareSaver, and ShareAdd to show echo status, updates igloo-core sendEcho docs/signature, bumps @frostr/igloo-core, and revises AGENTS.md.

Changes

Cohort / File(s) Summary
Docs: Guidelines and Core API
AGENTS.md, llm/context/igloo-core-readme.md
Revised contributor/guidance text and build/test commands; updated sendEcho signature/examples to require a 64-hex challenge and note even‑length hex constraint.
Dependency
package.json
Bumps @frostr/igloo-core from ^0.2.0 to ^0.2.1.
Echo Listener Hook
src/components/keyset/useShareEchoListener.ts
New hook to listen for share echoes with decode-of-relays, timeout, warning, retry/backoff, cancellation, and exports EchoStatus, UseShareEchoListenerOptions, useShareEchoListener.
Keyset UI: Load & Save Integrations
src/components/keyset/KeysetLoad.tsx, src/components/keyset/ShareSaver.tsx
Integrates hook and renders echo status/messages and credential blocks across saving/done/summary views.
Share Flow: Send Echo after Save
src/components/share/ShareAdd.tsx
Calls sendShareEcho after saving a share; tracks pending/success/error echo states and guards updates on unmount.
Keyset Echo API
src/keyset/echo.ts, src/keyset/index.ts
Adds sendShareEcho(groupCredential, shareCredential, { relays, challenge, timeout }) which generates a 64‑hex challenge if absent; re-exports from index.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User
  participant C as Component (KeysetLoad/ShareSaver)
  participant H as useShareEchoListener
  participant D as igloo-core
  participant R as Relays

  U->>C: Open load/save view
  C->>H: useShareEchoListener(groupCredential, shareCredential)
  H->>H: Decode group to infer relays (optional)
  H->>D: awaitShareEcho(shareCredential, { relays?, timeout })
  D-->>R: Subscribe for echo
  Note over H,D: Status = listening (warning timer may fire)
  R-->>D: Echo confirmation
  D-->>H: Success
  H-->>C: status = success, message = null
  C-->>U: Show "Echo confirmed"
  alt Timeout / transient error
    H->>H: Backoff and retry (maxRetries)
  end
Loading
sequenceDiagram
  autonumber
  actor U as User
  participant S as ShareAdd
  participant K as sendShareEcho
  participant D as igloo-core
  participant R as Relays

  U->>S: Save share
  S->>S: On success, reset echo state
  S->>K: sendShareEcho(groupCredential, shareCredential, opts)
  alt No challenge provided
    K->>K: Generate 64-hex challenge
  end
  K->>D: sendEcho(groupCredential, shareCredential, challenge, { relays, timeout })
  D-->>R: Publish echo
  R-->>D: Ack/confirmation
  D-->>S: Promise resolved
  S-->>U: Show echo success (or error)
  Note over K: Challenge must be even-length hex (64 hex chars typical)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

I tapped the keys with whiskered grace,
An echo hopped across the space—
A hex-charmed note, a secret ping,
The relays hummed and gave a ring.
Now green lights bloom where carrots gleam,
Our shares confirmed—what a quiet stream! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
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.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly describes the primary change of adding echo support in the keyset creation flow and notes the necessary igloo-core version bump, matching the pull request objectives without including extraneous details.
✨ 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 feature/echo

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.

@AustinKelsay
Copy link
Copy Markdown
Member Author

@CodeRabbit full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 4, 2025

✅ Actions performed

Full review triggered.

1 similar comment
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 4, 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: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c79c226 and 6fcd244.

⛔ 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
🪛 Biome (2.1.2)
src/components/keyset/ShareSaver.tsx

[error] 209-209: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.

Hooks should not be called after an early return.

For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level

(lint/correctness/useHookAtTopLevel)

🔇 Additional comments (11)
src/components/share/ShareAdd.tsx (3)

1-1: LGTM: Echo state and unmount guard correctly implemented.

The imports, state declarations, and isMountedRef pattern are appropriate for preventing state updates after component unmount. The echo status tracking states (echoStatus and echoError) are well-typed and initialized correctly.

Also applies to: 20-20, 84-85, 92-98


301-376: LGTM: Fire-and-forget echo pattern correctly implemented.

The echo logic is properly integrated:

  • State is reset at the start of save (lines 309-310)
  • Echo is sent asynchronously after successful save without blocking the UI transition to 'done' mode
  • isMountedRef guards prevent state updates after unmount
  • Error handling captures the message appropriately

The fire-and-forget pattern (void IIFE) is intentional and allows the save flow to complete immediately while echo status updates asynchronously in the background.


530-540: LGTM: Clear and informative echo status UI.

The echo status rendering is well-implemented with:

  • Clear, concise status messages
  • Appropriate color coding (cyan for pending, green for success, yellow for error)
  • Conditional error details when available
src/components/keyset/KeysetLoad.tsx (2)

63-68: LGTM: Echo listener hook correctly integrated.

The useShareEchoListener hook is properly invoked at the top level with the decrypted credentials. The hook correctly handles null inputs when result is not yet available.


222-234: LGTM: Echo status UI is clear and informative.

The echo status rendering provides helpful feedback:

  • Waiting state with optional share index context
  • Success confirmation message
  • Warning messages displayed when provided by the listener
src/keyset/echo.ts (1)

1-8: LGTM: Clean imports and type definition.

The imports and SendShareEchoOptions type are well-structured, providing a flexible API with all optional parameters.

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

18-18: LGTM!

The import of useShareEchoListener is correctly placed and enables the echo functionality integration.


77-89: LGTM!

The credential display blocks improve readability by breaking out the share and group credentials into dedicated, consistently styled sections. This makes the UI clearer across all phases.


214-236: LGTM!

The renderEchoStatus helper cleanly handles the three echo states (idle, listening, success) and provides clear user feedback at each stage.


238-311: Verify whether automated flow should display echo status.

The automated flow (when autoPassword is provided) saves all shares in a batch but does not integrate or display echo status. This differs from the manual flow, which shows echo feedback.

Is this intentional, or should the automated flow also listen for and display echo confirmations? If echo feedback is needed, consider integrating renderEchoStatus() in the automated flow's UI sections (lines 294-310).


313-322: LGTM!

The integration of credential blocks and echo status rendering across all manual flow phases ('saving', 'done', and main password prompt) provides consistent, informative feedback to users about share transmission status.

Also applies to: 324-343, 345-373

@AustinKelsay
Copy link
Copy Markdown
Member Author

@CodeRabbit full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 4, 2025

✅ Actions performed

Full review triggered.

@AustinKelsay
Copy link
Copy Markdown
Member Author

@CodeRabbit full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 4, 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

♻️ Duplicate comments (1)
src/keyset/echo.ts (1)

10-27: Verify sendEcho API signature matches igloo-core implementation.

The code calls sendEcho with challenge as a separate third parameter (line 23), but according to previous reviews and available package documentation, the actual signature is sendEcho(groupCredential, shareCredential, options?) where challenge would be inside the options object, not a separate parameter.

This issue was previously flagged. Please verify the actual API signature:

#!/bin/bash
# Check the actual sendEcho signature in installed package

echo "=== Checking installed @frostr/igloo-core version ==="
npm list @frostr/igloo-core

echo -e "\n=== Looking for sendEcho signature in type definitions ==="
fd -t f -e ts -e d.ts . node_modules/@frostr/igloo-core -x cat {} \; | grep -A10 "sendEcho"

echo -e "\n=== Searching for sendEcho in source files ==="
fd -t f -e js -e ts . node_modules/@frostr/igloo-core/dist node_modules/@frostr/igloo-core/src 2>/dev/null -x grep -l "sendEcho" {} \; | head -5 | xargs cat

If the API has changed in 0.2.1, update the call to match. If not, move challenge into the options object.

Based on learnings

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

131-196: Echo listener implementation with workaround for upstream bug.

The implementation uses a race condition between awaitShareEcho and a 15-second fallback timer as a workaround for a bug where awaitShareEcho doesn't resolve. The fallback timer is properly tracked (line 143), nulled immediately (line 144), and cleaned up in multiple paths:

  • Success path (lines 158-161)
  • Finally block (lines 188-191)
  • clearPending (lines 93-96)

The retry logic with exponential backoff (line 181) and max retries check (lines 172-176) is well-implemented.

Do you want me to generate a verification script to check if there are any remaining references to the awaitShareEcho bug or if the upstream issue has been resolved in the new igloo-core version?

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

322-343: Clarify challenge generation for browser consumers.

The example now imports randomBytes from Node’s crypto module, which breaks in browser builds (the CLI targets React flows too). Let's drop in a short note or alternate snippet using crypto.getRandomValues so web clients aren’t left with an unresolved module error.

 import { sendEcho } from '@frostr/igloo-core';
-import { randomBytes } from 'crypto';
+// Node.js example:
+import { randomBytes } from 'crypto';
+
+// Browser example:
+// const challengeBytes = crypto.getRandomValues(new Uint8Array(32));
+// const challenge = Buffer.from(challengeBytes).toString('hex');
 
 try {
-  const challenge = randomBytes(32).toString('hex'); // 32-byte (64 hex char) challenge
+  const challenge = randomBytes(32).toString('hex'); // 32-byte (64 hex char) challenge

Also consider adding a sentence below noting either approach is fine as long as the final challenge is an even-length hex string.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c79c226 and 577136c.

⛔ 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 comments (23)
src/components/keyset/useShareEchoListener.ts (5)

1-42: LGTM! Clean type definitions and relay extraction.

The imports, type definitions, and relay extraction logic are well-structured. The extractRelays helper correctly handles multiple relay field naming conventions (relays, relayUrls, relay_urls) with proper validation.


44-78: LGTM! Well-designed hook initialization.

The hook signature, default values, and relay extraction logic are well-thought-out. The graceful handling of decode failures for relay extraction (lines 71-76) prevents the hook from breaking when group credentials are malformed.


80-97: LGTM! Proper cleanup implementation.

The clearPending function correctly cleans up all three timeout refs (retry, warning, and fallback) and cancels the controller. This addresses the previous review concern about the fallback timer cleanup.


99-130: LGTM! Solid initialization and warning logic.

The initialization sequence is well-structured with proper credential validation, controller setup, and warning timeout configuration. The cancellation check on line 122 correctly prevents state updates after cleanup.


198-222: LGTM! Clean effect and return.

The effect properly manages the listener lifecycle with cleanup on unmount. The trigger-based retry mechanism (lines 217-219) is elegant and avoids recreating the startListening callback unnecessarily.

src/keyset/echo.ts (1)

1-8: LGTM! Clean imports and type definition.

The type SendShareEchoOptions is well-structured with sensible optional parameters for relay configuration, challenge, and timeout.

AGENTS.md (4)

4-4: LGTM! Clear project structure guidance.

The updated structure documentation clearly outlines the organization with specific file locations and the 150-line split guideline. The reminder to keep llm/ prompts updated with UX/protocol changes is valuable for maintaining consistency.


7-7: LGTM! Comprehensive development workflow guidance.

The build, test, and development commands section provides clear instructions with the important "release blocker" policy for test failures.


10-10: LGTM! Thorough coding style conventions.

The style guide covers essential conventions with clear examples. The emphasis on annotating "non-obvious flows with concise comments, especially around key lifecycle management" (line 10) is particularly valuable for this security-focused codebase.


13-19: LGTM! Essential testing, PR, and security guidelines.

The remaining sections provide critical guidance:

  • Testing prioritizes type coverage with manual validation documentation
  • PR guidelines appropriately flag llm/ and cryptographic changes for thorough review
  • Security tips emphasize the importance of never committing secrets and removing generated keys

These are all appropriate for a security-focused CLI tool handling cryptographic material.

src/keyset/index.ts (1)

7-7: LGTM! Clean public API extension.

The re-export from ./echo.js follows the established pattern and properly exposes the new echo functionality (SendShareEchoOptions and sendShareEcho) to consumers.

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

1-68: LGTM! Proper hook integration.

The useShareEchoListener hook is correctly imported (line 6) and called unconditionally at the top level (lines 65-68), following React's Rules of Hooks. The hook gracefully handles null credentials when no result is available yet.


222-234: LGTM! Clear echo status UI.

The echo status rendering provides good user feedback:

  • "Listening" state shows a helpful waiting message with optional share index (lines 225-227)
  • Warning messages are displayed in yellow (line 228)
  • Success state confirms echo reception (lines 231-233)

The conditional rendering ensures the UI only appears when relevant.


70-236: Well-integrated echo feature in load flow.

The echo status is appropriately displayed only in the result phase (lines 222-234), after successful share decryption. The component maintains clean phase separation while adding the new echo monitoring capability.

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

1-98: LGTM! Proper state and lifecycle management.

The additions are well-structured:

  • useRef import (line 1) and sendShareEcho import (line 20)
  • Echo state tracking with echoStatus and echoError (lines 84-85)
  • Mounted ref pattern (lines 92-98) correctly prevents state updates after unmount

301-370: LGTM! Proper async echo handling with stale state prevention.

The echo integration in handleSave is well-implemented:

  • Echo state reset before save (lines 309-310)
  • Pending status set before mode transition (line 354)
  • Async IIFE with void keyword (line 356) correctly indicates fire-and-forget
  • Mounted checks (lines 359-361, 364-366) prevent state updates after unmount
  • Proper error capture (lines 367-368)

517-540: LGTM! Comprehensive echo status feedback.

The echo UI in the "done" mode provides clear feedback for all states:

  • Pending: informative message (lines 530-532)
  • Success: positive confirmation (lines 533-535)
  • Error: warning with optional detail (lines 536-540)

67-640: Well-integrated echo feature in share add flow.

The echo functionality is properly integrated:

  • Triggered only after successful save (line 356)
  • Doesn't block or interfere with the main save flow
  • Status displayed appropriately in the "done" phase
  • Clean separation from core save logic
src/components/keyset/ShareSaver.tsx (4)

1-95: LGTM! Hook violation issue resolved.

The useShareEchoListener hook is now correctly called unconditionally at the top level (lines 77-80), before any early returns. This resolves the previous critical issue about violating React's Rules of Hooks.

The credential blocks (lines 82-94) are cleanly defined as reusable JSX elements.


214-236: LGTM! Clear echo status rendering.

The renderEchoStatus function provides helpful feedback:

  • Guards against missing share (lines 215-217)
  • Listening state with optional message (lines 218-226)
  • Success state with visual indicator (lines 228-234)

The bold checkmark on success (line 231) is a nice UX touch.


313-372: LGTM! Consistent echo status placement.

The echo status is consistently rendered across all phases:

  • During saving (line 319)
  • After completion (line 331)
  • During password entry (line 350)

The consistent placement after credential blocks provides a predictable user experience.


39-374: Echo listener properly integrated for multi-share flow.

The component correctly passes share?.credential (line 79) to the hook, which means the echo listener will restart for each share as currentIndex changes. This is appropriate behavior for tracking echo status per-share in a multi-share saving workflow.

package.json (1)

26-26: Dependency bump valid: @frostr/igloo-core@0.2.1 exists on npm and is the latest version.

@AustinKelsay AustinKelsay merged commit 8477267 into staging Oct 4, 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