Skip to content

Conversation

@AndreaDiazCorreia
Copy link
Member

@AndreaDiazCorreia AndreaDiazCorreia commented Nov 22, 2025

This PR fixes an issue where the NSEC_PRIVKEY environment variable was required for all users, even when executing regular trading commands. The changes make admin credentials optional and only load them when admin commands are executed. Additionally, the variable has been renamed from NSEC_PRIVKEY to ADMIN_NSEC to better reflect its purpose.

Changes include:

  • Made context_keys optional in the Context struct
  • Added is_admin_command() helper to detect admin-only commands
  • ADMIN_NSEC is now only required for admin commands (AdmCancel, AdmSettle, AdmListDisputes, AdmAddSolver, AdmTakeDispute, AdmSendDm, GetAdminDm)
  • Updated all admin command handlers to properly handle optional admin keys
  • Updated .env-sample and README.md to reflect the new variable name and optional nature
  • Regular users can now run the CLI with only MOSTRO_PUBKEY, RELAYS, and POW configured

Summary by CodeRabbit

  • Documentation

    • Clarified install instructions to specify MOSTRO_PUBKEY, RELAYS, POW, and ADMIN_NSEC; updated sample .env with improved formatting and commented examples.
  • Improvements

    • Admin commands now load the admin key only when needed and present a clear error if the admin private key is not configured, preventing unexpected failures.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 22, 2025

Warning

Rate limit exceeded

@AndreaDiazCorreia has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 12 minutes and 11 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

📥 Commits

Reviewing files that changed from the base of the PR and between d8f1d66 and a94d0b1.

📒 Files selected for processing (1)
  • src/cli/take_dispute.rs (8 hunks)

Walkthrough

Context.context_keys was made optional (Option); ADMIN_NSEC is loaded only for admin commands. Admin-related call sites now guard for missing admin keys and use as_ref() where needed. README and .env-sample were updated with env var guidance and formatting.

Changes

Cohort / File(s) Summary
Documentation & Config
\.env-sample, README.md
.env-sample adds a trailing newline and a commented ADMIN_NSEC example; README.md clarifies required env vars and documents MOSTRO_PUBKEY, RELAYS, POW, and ADMIN_NSEC.
Core CLI Context Refactor
src/cli.rs
Context.context_keys changed from Keys to Option<Keys>; added is_admin_command() and conditional loading of ADMIN_NSEC; context construction updated to carry optional keys.
Admin DM / Dispute Commands
src/cli/adm_send_dm.rs, src/cli/take_dispute.rs
Call sites now retrieve admin_keys via ctx.context_keys.as_ref() and return an error if missing; replaced direct ctx.context_keys usage with guarded admin_keys and adjusted calls to pass admin keys.
Utilities (events & storage)
src/util/events.rs, src/util/storage.rs
Admin-related flows now guard retrieval of admin keys (as_ref().ok_or_else(...)) and pass Some(admin_keys) to DM/send helpers instead of unguarded context key references.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI Init
    participant Checker as is_admin_command()
    participant Env as Env (ADMIN_NSEC)
    participant Context as Context{context_keys}
    participant Handler as Admin Handler

    CLI->>Checker: Is command admin?
    alt admin
        Checker-->>CLI: true
        CLI->>Env: read ADMIN_NSEC
        Env-->>Context: Some(Keys)
    else non-admin
        Checker-->>CLI: false
        CLI->>Context: None
    end

    Context->>Handler: execute command with Optional Keys
    alt Keys present
        Handler->>Handler: use admin_keys (as_ref)
        Handler-->>CLI: success
    else Keys missing
        Handler-->>CLI: error ("admin keys not available")
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Review all call sites that previously used ctx.context_keys to ensure no remaining unwraps.
  • Verify is_admin_command() covers every admin variant and that error messages are consistent.
  • Check DM/send helper call signatures to confirm they accept Option<&Keys> or &Keys as expected.

Possibly related PRs

Suggested reviewers

  • grunch
  • Catrya

Poem

🐰 A nibble, a hop, a guarded key,
I fetch the secret only when asked of me.
For admin tasks I peek and find,
Else skip the vault and stay aligned.
— your friendly rabbit, secure and spry 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 accurately summarizes the main changes: renaming NSEC_PRIVKEY to ADMIN_NSEC and making it optional for non-admin commands.

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
Contributor

@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 (1)
src/cli/take_dispute.rs (1)

66-68: Minor: Inconsistent logging label.

Line 68 uses "Admin PubKey" while lines 102 and 139 use "Admin Keys". Consider using consistent terminology across all admin functions for better UX.

Apply this diff for consistency:

-    println!("🔑 Admin PubKey: {}", admin_keys.public_key);
+    println!("🔑 Admin Keys: {}", admin_keys.public_key);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7ff07f3 and c828ea5.

📒 Files selected for processing (7)
  • .env-sample (1 hunks)
  • README.md (1 hunks)
  • src/cli.rs (3 hunks)
  • src/cli/adm_send_dm.rs (2 hunks)
  • src/cli/take_dispute.rs (4 hunks)
  • src/util/events.rs (1 hunks)
  • src/util/storage.rs (1 hunks)
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli.rs:301-306
Timestamp: 2025-09-12T20:02:14.291Z
Learning: The mostro-cli is designed as a test client that allows users to test both regular user operations and admin operations from the terminal. Therefore, MOSTRO_PUBKEY should always be required regardless of whether NSEC_PRIVKEY is present, as both user and admin operations need to know which Mostro instance to interact with.
📚 Learning: 2025-09-12T20:02:14.291Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli.rs:301-306
Timestamp: 2025-09-12T20:02:14.291Z
Learning: The mostro-cli is designed as a test client that allows users to test both regular user operations and admin operations from the terminal. Therefore, MOSTRO_PUBKEY should always be required regardless of whether NSEC_PRIVKEY is present, as both user and admin operations need to know which Mostro instance to interact with.

Applied to files:

  • .env-sample
  • README.md
  • src/cli.rs
📚 Learning: 2025-09-13T20:48:31.581Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli/send_msg.rs:89-110
Timestamp: 2025-09-13T20:48:31.581Z
Learning: In mostro-cli's send_msg.rs, tokio::spawn with async move is valid for sending DMs when PublicKey implements Copy, and arkanoider confirmed this approach works without memory issues or compilation errors.

Applied to files:

  • src/cli/take_dispute.rs
  • src/cli/adm_send_dm.rs
  • src/util/storage.rs
📚 Learning: 2025-09-13T20:48:31.581Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli/send_msg.rs:89-110
Timestamp: 2025-09-13T20:48:31.581Z
Learning: In mostro-cli's send_msg.rs, arkanoider confirmed that tokio::spawn with async move is correct and compiles without errors when using PublicKey (which implements Copy). The spawning approach is acceptable for DM sending in this context.

Applied to files:

  • src/cli/take_dispute.rs
  • src/cli/adm_send_dm.rs
  • src/util/storage.rs
📚 Learning: 2025-10-18T11:48:11.944Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 146
File: src/cli/dm_to_user.rs:25-32
Timestamp: 2025-10-18T11:48:11.944Z
Learning: In mostro-cli's DM functionality (dm_to_user.rs and similar), message content consists of ephemeral public keys that change every time and contains no sensitive personal data. Logging message content to stdout is acceptable and not a privacy concern.

Applied to files:

  • src/cli/take_dispute.rs
  • src/cli/adm_send_dm.rs
  • src/util/storage.rs
📚 Learning: 2025-09-13T10:31:42.313Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli/get_dm.rs:24-29
Timestamp: 2025-09-13T10:31:42.313Z
Learning: In mostro-cli's get_dm.rs, the message filtering is intentional: non-admin users should only receive DirectMessage from users, while messages from Mostro are only fetched when the admin flag is true. Don't include GiftWrap messages for non-admin users.

Applied to files:

  • src/cli/take_dispute.rs
  • src/cli/adm_send_dm.rs
  • src/util/events.rs
  • src/util/storage.rs
📚 Learning: 2025-10-18T09:38:00.449Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 146
File: src/cli/restore.rs:61-66
Timestamp: 2025-10-18T09:38:00.449Z
Learning: In src/cli/restore.rs, the restore session request to Mostro will only receive GiftWrap messages as responses, not PrivateDirectMessage. The wait_for_dm subscription filtering for GiftWrap only is intentional and correct for this endpoint.

Applied to files:

  • src/cli/take_dispute.rs
  • src/cli/adm_send_dm.rs
📚 Learning: 2025-09-09T19:07:29.834Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli/add_invoice.rs:57-79
Timestamp: 2025-09-09T19:07:29.834Z
Learning: In Nostr direct message flows, explicit subscriptions before sending DMs are not needed because the server will route responses using the correct key, and wait_for_dm likely handles subscription logic internally.

Applied to files:

  • src/cli/take_dispute.rs
📚 Learning: 2025-09-13T20:40:51.992Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli/get_dm_user.rs:38-40
Timestamp: 2025-09-13T20:40:51.992Z
Learning: The get_direct_messages_from_trade_keys function in src/util.rs already handles the `since` parameter through manual filtering after fetching events: it uses a hardcoded 2880-minute window in the Nostr filter, then manually filters results with `if event.created_at.as_u64() < since as u64 { continue; }`.

Applied to files:

  • src/util/events.rs
📚 Learning: 2025-09-13T20:40:51.992Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli/get_dm_user.rs:38-40
Timestamp: 2025-09-13T20:40:51.992Z
Learning: The get_direct_messages_from_trade_keys function in src/util.rs already handles the `since` parameter properly by creating filters with `since(Timestamp::from(since))`, so no additional local filtering is needed in CLI functions that call it.

Applied to files:

  • src/util/events.rs
📚 Learning: 2025-09-13T10:31:42.313Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli/get_dm.rs:24-29
Timestamp: 2025-09-13T10:31:42.313Z
Learning: In mostro-cli, index 0 represents the master key and should be skipped when iterating through trade keys. The loop should start from index 1 when fetching user trade keys in get_dm.rs.

Applied to files:

  • src/cli.rs
🧬 Code graph analysis (5)
src/cli/take_dispute.rs (2)
src/util/messaging.rs (2)
  • send_dm (186-238)
  • wait_for_dm (69-112)
src/parser/dms.rs (1)
  • parse_dm_events (744-839)
src/cli/adm_send_dm.rs (2)
src/parser/common.rs (3)
  • create_standard_table (49-55)
  • create_field_value_header (58-67)
  • create_emoji_field_row (94-99)
src/util/messaging.rs (1)
  • send_admin_gift_wrap_dm (14-21)
src/util/events.rs (1)
src/parser/dms.rs (1)
  • parse_dm_events (744-839)
src/cli.rs (1)
src/util/messaging.rs (2)
  • var (199-201)
  • None (51-51)
src/util/storage.rs (1)
src/util/messaging.rs (1)
  • send_dm (186-238)
🔇 Additional comments (15)
.env-sample (1)

5-8: LGTM! Clear documentation for optional admin key.

The comment clearly indicates that ADMIN_NSEC is only required for admin commands, which aligns with the implementation changes in the codebase.

README.md (2)

23-23: LGTM! Documentation accurately reflects the changes.

The documentation now clearly states that the admin private key is only needed for admin commands, which matches the implementation.


29-30: LGTM! Clear setup instructions.

The instructions clearly guide users to set ADMIN_NSEC only for admin commands, making the optional nature of the admin key explicit.

src/cli.rs (3)

57-57: LGTM! Type change enables conditional admin key loading.

Changing context_keys from Keys to Option<Keys> is the correct approach for making admin credentials optional. This aligns with the PR objective of requiring admin keys only for admin-specific commands.


394-405: LGTM! Clear and correct conditional loading logic.

The conditional loading of admin keys is well-implemented:

  • Only loads ADMIN_NSEC when is_admin_command returns true
  • Provides clear error message indicating the requirement for admin commands
  • Returns None for non-admin commands, allowing regular users to run the CLI without admin credentials

427-438: Function is complete; no missing admin commands.

Verification confirms all admin command variants from the Commands enum (7 total: AdmCancel, AdmSettle, AdmListDisputes, AdmAddSolver, AdmTakeDispute, AdmSendDm, and GetAdminDm) are correctly included in the is_admin_command function. The code is accurate and complete.

src/util/storage.rs (2)

47-48: LGTM! Proper guard for admin key availability.

The admin key retrieval correctly:

  • Uses as_ref() to avoid moving the value
  • Provides a clear error message when admin keys are not available
  • Aligns with the pattern used throughout the codebase

51-51: LGTM! Correct passing of admin keys.

The change from Some(&ctx.context_keys) to Some(admin_keys) correctly adapts to the new optional admin key structure.

src/cli/adm_send_dm.rs (3)

10-11: LGTM! Consistent admin key guard.

The admin key retrieval follows the same pattern used throughout the codebase, with a clear error message.


20-20: LGTM! Correct usage of admin keys.

The change from ctx.context_keys.public_key() to admin_keys.public_key() correctly uses the locally retrieved admin keys.


31-31: LGTM! Correct parameter passing.

The change correctly passes admin_keys (which is &Keys) to the function, adapting to the new optional admin key structure.

src/util/events.rs (2)

90-92: LGTM! Correct admin key retrieval for admin DM path.

The admin key retrieval is correctly scoped to the DirectMessagesAdmin path and uses a consistent error message.


98-98: LGTM! Correct parameter passing.

The change correctly passes admin_keys to parse_dm_events, adapting to the new optional admin key structure.

src/cli/take_dispute.rs (2)

100-102: LGTM! Proper admin key guard.

The admin key retrieval is consistent with other functions and provides clear error messaging.


137-156: LGTM! Correct admin key usage throughout the dispute flow.

The changes correctly:

  • Retrieve admin keys with proper error handling
  • Pass admin keys to send_dm, wait_for_dm, and parse_dm_events
  • Maintain the expected dispute handling flow

Copy link
Contributor

@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 (1)
src/cli/take_dispute.rs (1)

12-41: Add consistent admin keys validation for better error messages.

Unlike the other admin commands in this file (execute_admin_cancel_dispute, execute_admin_settle_dispute, execute_take_dispute), this function doesn't explicitly validate that admin keys are available before proceeding. While admin_send_dm will eventually fail if admin keys are missing, adding an explicit check here would provide a clearer error message and maintain consistency across all admin commands.

Apply this diff to add the admin keys check:

 pub async fn execute_admin_add_solver(npubkey: &str, ctx: &Context) -> Result<()> {
     println!("👑 Admin Add Solver");
     println!("═══════════════════════════════════════");
     let mut table = create_standard_table();
     table.set_header(create_field_value_header());
     table.add_row(create_emoji_field_row("🔑 ", "Solver PubKey", npubkey));
     table.add_row(create_emoji_field_row(
         "🎯 ",
         "Mostro PubKey",
         &ctx.mostro_pubkey.to_string(),
     ));
     println!("{table}");
     println!("💡 Adding new solver to Mostro...\n");
+
+    let admin_keys = ctx.context_keys.as_ref()
+        .ok_or_else(|| anyhow::anyhow!("Admin keys not available. ADMIN_NSEC must be set for admin commands."))?;
+    println!("🔑 Admin Keys: {}", admin_keys.public_key());
+
     // Create takebuy message
     let take_dispute_message = Message::new_dispute(
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c828ea5 and eb52d70.

📒 Files selected for processing (1)
  • src/cli/take_dispute.rs (4 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli.rs:301-306
Timestamp: 2025-09-12T20:02:14.291Z
Learning: The mostro-cli is designed as a test client that allows users to test both regular user operations and admin operations from the terminal. Therefore, MOSTRO_PUBKEY should always be required regardless of whether NSEC_PRIVKEY is present, as both user and admin operations need to know which Mostro instance to interact with.
📚 Learning: 2025-09-13T20:48:31.581Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli/send_msg.rs:89-110
Timestamp: 2025-09-13T20:48:31.581Z
Learning: In mostro-cli's send_msg.rs, tokio::spawn with async move is valid for sending DMs when PublicKey implements Copy, and arkanoider confirmed this approach works without memory issues or compilation errors.

Applied to files:

  • src/cli/take_dispute.rs
📚 Learning: 2025-09-13T20:48:31.581Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli/send_msg.rs:89-110
Timestamp: 2025-09-13T20:48:31.581Z
Learning: In mostro-cli's send_msg.rs, arkanoider confirmed that tokio::spawn with async move is correct and compiles without errors when using PublicKey (which implements Copy). The spawning approach is acceptable for DM sending in this context.

Applied to files:

  • src/cli/take_dispute.rs
📚 Learning: 2025-10-18T11:48:11.944Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 146
File: src/cli/dm_to_user.rs:25-32
Timestamp: 2025-10-18T11:48:11.944Z
Learning: In mostro-cli's DM functionality (dm_to_user.rs and similar), message content consists of ephemeral public keys that change every time and contains no sensitive personal data. Logging message content to stdout is acceptable and not a privacy concern.

Applied to files:

  • src/cli/take_dispute.rs
📚 Learning: 2025-09-13T10:31:42.313Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli/get_dm.rs:24-29
Timestamp: 2025-09-13T10:31:42.313Z
Learning: In mostro-cli's get_dm.rs, the message filtering is intentional: non-admin users should only receive DirectMessage from users, while messages from Mostro are only fetched when the admin flag is true. Don't include GiftWrap messages for non-admin users.

Applied to files:

  • src/cli/take_dispute.rs
📚 Learning: 2025-10-18T09:38:00.449Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 146
File: src/cli/restore.rs:61-66
Timestamp: 2025-10-18T09:38:00.449Z
Learning: In src/cli/restore.rs, the restore session request to Mostro will only receive GiftWrap messages as responses, not PrivateDirectMessage. The wait_for_dm subscription filtering for GiftWrap only is intentional and correct for this endpoint.

Applied to files:

  • src/cli/take_dispute.rs
📚 Learning: 2025-09-09T19:07:29.834Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli/add_invoice.rs:57-79
Timestamp: 2025-09-09T19:07:29.834Z
Learning: In Nostr direct message flows, explicit subscriptions before sending DMs are not needed because the server will route responses using the correct key, and wait_for_dm likely handles subscription logic internally.

Applied to files:

  • src/cli/take_dispute.rs
🧬 Code graph analysis (1)
src/cli/take_dispute.rs (2)
src/util/messaging.rs (2)
  • send_dm (186-238)
  • wait_for_dm (69-112)
src/parser/dms.rs (1)
  • parse_dm_events (744-839)
🔇 Additional comments (4)
src/cli/take_dispute.rs (4)

144-144: LGTM: Correct propagation of admin keys through DM operations.

The admin keys are correctly passed to the DM operation chain:

  • send_dm receives Some(admin_keys) for the identity_keys parameter
  • wait_for_dm receives Some(admin_keys) for the order_trade_keys parameter
  • parse_dm_events receives admin_keys for the pubkey parameter

All parameter types match their function signatures (Option<&Keys> or &Keys as expected).

Also applies to: 153-153, 156-156


137-139: Fix method call syntax for public_key().

Line 139 is missing parentheses when calling the public_key() method. In the nostr_sdk crate, public_key() is a method, not a field, so it requires parentheses.

Apply this diff to fix the syntax error:

     let admin_keys = ctx.context_keys.as_ref()
         .ok_or_else(|| anyhow::anyhow!("Admin keys not available. ADMIN_NSEC must be set for admin commands."))?;
-    println!("🔑 Admin Keys: {}", admin_keys.public_key);
+    println!("🔑 Admin Keys: {}", admin_keys.public_key());
⛔ Skipped due to learnings
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/util.rs:614-619
Timestamp: 2025-09-14T14:01:01.728Z
Learning: In the mostro-cli codebase, the user arkanoider indicated that accessing `public_key` without parentheses (as a field) is valid, even though most of the codebase uses `public_key()` method calls. This suggests there may be `Deref` implementation or other Rust features that allow both syntaxes to work.

66-68: Fix method call syntax for public_key().

Line 68 is missing parentheses when calling the public_key() method. In the nostr_sdk crate, public_key() is a method, not a field, so it requires parentheses.

Apply this diff to fix the syntax error:

     let admin_keys = ctx.context_keys.as_ref()
         .ok_or_else(|| anyhow::anyhow!("Admin keys not available. ADMIN_NSEC must be set for admin commands."))?;
-    println!("🔑 Admin Keys: {}", admin_keys.public_key);
+    println!("🔑 Admin Keys: {}", admin_keys.public_key());
⛔ Skipped due to learnings
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/util.rs:614-619
Timestamp: 2025-09-14T14:01:01.728Z
Learning: In the mostro-cli codebase, the user arkanoider indicated that accessing `public_key` without parentheses (as a field) is valid, even though most of the codebase uses `public_key()` method calls. This suggests there may be `Deref` implementation or other Rust features that allow both syntaxes to work.

100-102: Fix method call syntax for public_key().

Line 102 is missing parentheses when calling the public_key() method. In the nostr_sdk crate, public_key() is a method, not a field, so it requires parentheses.

Apply this diff to fix the syntax error:

     let admin_keys = ctx.context_keys.as_ref()
         .ok_or_else(|| anyhow::anyhow!("Admin keys not available. ADMIN_NSEC must be set for admin commands."))?;
-    println!("🔑 Admin Keys: {}", admin_keys.public_key);
+    println!("🔑 Admin Keys: {}", admin_keys.public_key());
     admin_send_dm(ctx, take_dispute_message).await?;
⛔ Skipped due to learnings
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/util.rs:614-619
Timestamp: 2025-09-14T14:01:01.728Z
Learning: In the mostro-cli codebase, the user arkanoider indicated that accessing `public_key` without parentheses (as a field) is valid, even though most of the codebase uses `public_key()` method calls. This suggests there may be `Deref` implementation or other Rust features that allow both syntaxes to work.

Copy link
Contributor

@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 (2)
src/cli/take_dispute.rs (2)

26-28: Consider extracting the admin key retrieval pattern to reduce duplication.

The same pattern for retrieving admin keys and logging the public key is repeated across all four admin command functions. Consider extracting this into a helper function to improve maintainability.

Example:

fn get_admin_keys(ctx: &Context) -> Result<&Keys> {
    let admin_keys = ctx.context_keys.as_ref()
        .ok_or_else(|| anyhow::anyhow!("Admin keys not available. ADMIN_NSEC must be set for admin commands."))?;
    println!("🔑 Admin Keys: {}", admin_keys.public_key);
    Ok(admin_keys)
}

Then replace the duplicated blocks with:

let admin_keys = get_admin_keys(ctx)?;

Also applies to: 71-73, 105-107, 142-144


28-28: Consider if logging admin public keys is necessary.

All admin command functions now log the admin public key to stdout. While public keys are not secret, this additional logging might be unnecessary noise in production usage. Consider either removing these logs or gating them behind a verbose/debug flag.

Also applies to: 73-73, 107-107, 144-144

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eb52d70 and d8f1d66.

📒 Files selected for processing (1)
  • src/cli/take_dispute.rs (5 hunks)
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli.rs:301-306
Timestamp: 2025-09-12T20:02:14.291Z
Learning: The mostro-cli is designed as a test client that allows users to test both regular user operations and admin operations from the terminal. Therefore, MOSTRO_PUBKEY should always be required regardless of whether NSEC_PRIVKEY is present, as both user and admin operations need to know which Mostro instance to interact with.
📚 Learning: 2025-09-13T20:48:31.581Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli/send_msg.rs:89-110
Timestamp: 2025-09-13T20:48:31.581Z
Learning: In mostro-cli's send_msg.rs, tokio::spawn with async move is valid for sending DMs when PublicKey implements Copy, and arkanoider confirmed this approach works without memory issues or compilation errors.

Applied to files:

  • src/cli/take_dispute.rs
📚 Learning: 2025-09-13T20:48:31.581Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli/send_msg.rs:89-110
Timestamp: 2025-09-13T20:48:31.581Z
Learning: In mostro-cli's send_msg.rs, arkanoider confirmed that tokio::spawn with async move is correct and compiles without errors when using PublicKey (which implements Copy). The spawning approach is acceptable for DM sending in this context.

Applied to files:

  • src/cli/take_dispute.rs
📚 Learning: 2025-10-18T11:48:11.944Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 146
File: src/cli/dm_to_user.rs:25-32
Timestamp: 2025-10-18T11:48:11.944Z
Learning: In mostro-cli's DM functionality (dm_to_user.rs and similar), message content consists of ephemeral public keys that change every time and contains no sensitive personal data. Logging message content to stdout is acceptable and not a privacy concern.

Applied to files:

  • src/cli/take_dispute.rs
📚 Learning: 2025-09-13T10:31:42.313Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli/get_dm.rs:24-29
Timestamp: 2025-09-13T10:31:42.313Z
Learning: In mostro-cli's get_dm.rs, the message filtering is intentional: non-admin users should only receive DirectMessage from users, while messages from Mostro are only fetched when the admin flag is true. Don't include GiftWrap messages for non-admin users.

Applied to files:

  • src/cli/take_dispute.rs
📚 Learning: 2025-10-18T09:38:00.449Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 146
File: src/cli/restore.rs:61-66
Timestamp: 2025-10-18T09:38:00.449Z
Learning: In src/cli/restore.rs, the restore session request to Mostro will only receive GiftWrap messages as responses, not PrivateDirectMessage. The wait_for_dm subscription filtering for GiftWrap only is intentional and correct for this endpoint.

Applied to files:

  • src/cli/take_dispute.rs
📚 Learning: 2025-09-09T19:07:29.834Z
Learnt from: arkanoider
Repo: MostroP2P/mostro-cli PR: 135
File: src/cli/add_invoice.rs:57-79
Timestamp: 2025-09-09T19:07:29.834Z
Learning: In Nostr direct message flows, explicit subscriptions before sending DMs are not needed because the server will route responses using the correct key, and wait_for_dm likely handles subscription logic internally.

Applied to files:

  • src/cli/take_dispute.rs
🧬 Code graph analysis (1)
src/cli/take_dispute.rs (2)
src/util/messaging.rs (2)
  • send_dm (186-238)
  • wait_for_dm (69-112)
src/parser/dms.rs (1)
  • parse_dm_events (744-839)
🔇 Additional comments (2)
src/cli/take_dispute.rs (2)

142-161: LGTM! Admin key handling in execute_take_dispute is correct.

The explicit passing of admin_keys to send_dm, wait_for_dm, and parse_dm_events is type-correct and properly handles the optional admin keys pattern. The changes ensure admin messages are sent and processed with the correct admin credentials.


41-41: ****

The original review comment is based on a false premise. The admin_send_dm function (src/util/storage.rs:46-56) properly handles optional admin keys by internally extracting ctx.context_keys and validating availability with the same error handling as the calling functions. This is intentional design—the wrapper function abstracts key extraction from the context, allowing callers to pass only the context. The early validation in calling functions provides user feedback before attempting the operation, while admin_send_dm performs its own validation. This pattern is consistent and correct.

Likely an incorrect or invalid review comment.

@arkanoider
Copy link
Collaborator

@AndreaDiazCorreia I like it! Var name is more meaningful and logic is correct! If you can I would only use your nice helper:

/// Helper function to retrieve and validate admin keys from context
fn get_admin_keys(ctx: &Context) -> Result<&Keys> {
    let admin_keys = ctx.context_keys.as_ref()
        .ok_or_else(|| anyhow::anyhow!("Admin keys not available. ADMIN_NSEC must be set for admin commands."))?;
    
    // Only log admin public key in verbose mode
    if std::env::var("RUST_LOG").is_ok() {
        println!("🔑 Admin Keys: {}", admin_keys.public_key);
    }
    
    Ok(admin_keys)
}

in all the other files that are using that check, maybe we can move the helper in util/messaging.rs and export it in other required place! What do you think?

@arkanoider
Copy link
Collaborator

arkanoider commented Nov 23, 2025

Another point, probably admlistdisputes command can be changed just to listdisputes, and remove it from admin commands, everyone can see disputes state.
Do you agree @grunch ?

@arkanoider
Copy link
Collaborator

LGTM!

@arkanoider arkanoider merged commit 1e7a687 into MostroP2P:main Nov 24, 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.

2 participants