feat: add add-solver permission selector and payload support#58
Conversation
Improve the admin add-solver flow by introducing a read/read-write permission selector in the popup and carrying that choice through confirmation and submission. Format admin-add-solver payloads according to protocol expectations, preserve state on cancel paths, and refresh help text and tests for the new behavior. Made-with: Cursor
|
Warning Rate limit exceeded
To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing. ⌛ 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. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
WalkthroughA solver permission selector is introduced to the admin "Add Solver" UI flow. A new Changes
Sequence DiagramsequenceDiagram
participant User
participant KeyHandler as Key Handler
participant AdminState as Admin State
participant Draw as UI Renderer
participant Backend as Backend Executor
User->>KeyHandler: Enter Add Solver mode
KeyHandler->>AdminState: Create AddSolverState(key_input, permission=ReadWrite)
AdminState-->>Draw: Render permission selector popup
Draw-->>User: Display pubkey & Read/Read-Write options
loop user edits / navigates
User->>KeyHandler: Type chars / Press Left/Right
alt char input
KeyHandler->>AdminState: Append chars to key_input
else left/right
KeyHandler->>AdminState: Toggle permission (Read ⇄ ReadWrite)
end
AdminState-->>Draw: Re-render popup
end
User->>KeyHandler: Confirm (Enter)
KeyHandler->>AdminState: Transition to ConfirmAddSolver{solver_pubkey, permission}
Draw-->>User: Show confirmation with permission label
User->>KeyHandler: Confirm yes
KeyHandler->>Backend: Call execute_admin_add_solver(solver_pubkey, permission)
Backend->>Backend: Build payload (append :read if permission == Read)
Backend-->>User: Send payload to Mostro instance
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Review rate limit: 0/1 reviews remaining, refill in 41 minutes and 10 seconds.Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (4)
src/ui/key_handler/enter_handlers.rs (1)
1077-1080: Consider defaulting solver permission toReadfor safer UX.Line 1079 currently defaults to
ReadWrite; starting atReadwould better follow least-privilege and reduce accidental over-granting.Proposed tweak
- permission: crate::ui::SolverPermission::ReadWrite, + permission: crate::ui::SolverPermission::Read,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/ui/key_handler/enter_handlers.rs` around lines 1077 - 1080, The code currently sets the new AddSolver state with permission SolverPermission::ReadWrite; change this default to the least-privilege option by replacing SolverPermission::ReadWrite with SolverPermission::Read when constructing UiMode::AdminMode(AdminMode::AddSolver(crate::ui::AddSolverState { key_input: key_state, permission: ... })); ensure you only change the permission enum value in the AddSolverState construction (leave UiMode::AdminMode, AdminMode::AddSolver, and key_input as-is).src/ui/help_popup.rs (1)
241-241: Include the selection keybinding in this help text.Line 241 explains what to choose, but adding
Left/Rightwould also explain how to choose it in-popup.Suggested wording
- "Enter solver npub and choose read or read-write permission before confirming.", + "Enter solver npub, use Left/Right to choose read or read-write, then confirm.",🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/ui/help_popup.rs` at line 241, Update the help text string in src/ui/help_popup.rs (the line containing "Enter solver npub and choose read or read-write permission before confirming.") to include the selection keybinding, e.g., append "Use Left/Right to switch" or similar so users know how to toggle the read vs read-write option; modify the exact literal in the help popup rendering code where this message is defined to include "Left/Right" (or "Left/Right arrow keys") next to the instruction.src/util/order_utils/execute_admin_add_solver.rs (2)
102-114: Add a hex-input regression test for payload generation.Current tests validate npub cases only. Add one case with a 64-char hex key to verify normalization +
:readsuffix behavior, since that path is part of this new payload logic.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/util/order_utils/execute_admin_add_solver.rs` around lines 102 - 114, Add a new test that covers the hex-key normalization path: call build_solver_payload_text with a 64-character hex key string and SolverPermission::Read and assert the returned payload equals "{hex}:read" (i.e., the hex key plus ":read"); also add a complementary test that calls build_solver_payload_text with the same hex key and SolverPermission::ReadWrite and assert the payload equals the hex key unchanged. Place these tests alongside the existing add_solver_payload_* tests that use npub so the hex-input regression for build_solver_payload_text is exercised.
8-8: Consider decouplingorder_utilsfromcrate::uitypes.
src/util/order_utils/execute_admin_add_solver.rsimportingcrate::ui::SolverPermissioncouples utility/protocol code to UI state. Prefer moving this enum to a shared/domain module consumed by both layers.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/util/order_utils/execute_admin_add_solver.rs` at line 8, The file execute_admin_add_solver.rs currently imports SolverPermission from crate::ui which couples utility code to the UI; move the SolverPermission enum into a shared/domain module (e.g., crate::domain::permissions or crate::shared::types) and update execute_admin_add_solver.rs to import the enum from that new module instead of crate::ui; update any other files that reference crate::ui::SolverPermission to use the new path and run tests/compile to ensure no remaining crate::ui references remain (look for the symbol SolverPermission and the execute_admin_add_solver.rs import line).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/ui/help_popup.rs`:
- Line 241: Update the help text string in src/ui/help_popup.rs (the line
containing "Enter solver npub and choose read or read-write permission before
confirming.") to include the selection keybinding, e.g., append "Use Left/Right
to switch" or similar so users know how to toggle the read vs read-write option;
modify the exact literal in the help popup rendering code where this message is
defined to include "Left/Right" (or "Left/Right arrow keys") next to the
instruction.
In `@src/ui/key_handler/enter_handlers.rs`:
- Around line 1077-1080: The code currently sets the new AddSolver state with
permission SolverPermission::ReadWrite; change this default to the
least-privilege option by replacing SolverPermission::ReadWrite with
SolverPermission::Read when constructing
UiMode::AdminMode(AdminMode::AddSolver(crate::ui::AddSolverState { key_input:
key_state, permission: ... })); ensure you only change the permission enum value
in the AddSolverState construction (leave UiMode::AdminMode,
AdminMode::AddSolver, and key_input as-is).
In `@src/util/order_utils/execute_admin_add_solver.rs`:
- Around line 102-114: Add a new test that covers the hex-key normalization
path: call build_solver_payload_text with a 64-character hex key string and
SolverPermission::Read and assert the returned payload equals "{hex}:read"
(i.e., the hex key plus ":read"); also add a complementary test that calls
build_solver_payload_text with the same hex key and SolverPermission::ReadWrite
and assert the payload equals the hex key unchanged. Place these tests alongside
the existing add_solver_payload_* tests that use npub so the hex-input
regression for build_solver_payload_text is exercised.
- Line 8: The file execute_admin_add_solver.rs currently imports
SolverPermission from crate::ui which couples utility code to the UI; move the
SolverPermission enum into a shared/domain module (e.g.,
crate::domain::permissions or crate::shared::types) and update
execute_admin_add_solver.rs to import the enum from that new module instead of
crate::ui; update any other files that reference crate::ui::SolverPermission to
use the new path and run tests/compile to ensure no remaining crate::ui
references remain (look for the symbol SolverPermission and the
execute_admin_add_solver.rs import line).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 9d77aff7-ed9a-4f99-b58f-b114af42fb23
📒 Files selected for processing (13)
src/main.rssrc/ui/admin_state.rssrc/ui/draw.rssrc/ui/help_popup.rssrc/ui/key_handler/admin_handlers.rssrc/ui/key_handler/confirmation.rssrc/ui/key_handler/enter_handlers.rssrc/ui/key_handler/esc_handlers.rssrc/ui/key_handler/mod.rssrc/ui/key_handler/navigation.rssrc/ui/mod.rssrc/ui/state.rssrc/util/order_utils/execute_admin_add_solver.rs
There was a problem hiding this comment.
I reviewed the latest diff carefully and I do not see a blocker here.
What I checked:
- the new add-solver UI state machine, including permission selection, confirmation, and cancel paths
- keyboard handling so Left/Right toggles permission in the input popup and still behaves correctly in the confirmation popup
- payload formatting for
AdminAddSolver, especially the:readsuffix for read-only solvers and the default payload for read-write solvers - state preservation when backing out of confirmation
- help text and popup guidance
The implementation looks coherent to me:
Readmaps to<npub>:readReadWritekeeps the existing payload shape- the selected permission survives Enter, Esc, and NO/cancel paths instead of silently resetting
- the paste path in
main.rswas updated correctly for the richerAddSolverState
Checks are green too, so this looks good from my side. Nice improvement to the admin solver flow.
There was a problem hiding this comment.
🧹 Nitpick comments (3)
src/ui/key_handler/admin_handlers.rs (1)
92-110: Optional: remove extrasolver_pubkeyclone before spawn.You can move
solver_pubkeyinto the async block directly and borrow it there, avoiding the intermediate clone.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/ui/key_handler/admin_handlers.rs` around lines 92 - 110, There’s an unnecessary clone of solver_pubkey (solver_pubkey_clone) before spawning the task; instead move/own solver_pubkey into the async block and use it there to avoid the extra clone. Replace usage of solver_pubkey_clone with solver_pubkey inside the tokio::spawn closure and ensure execute_admin_add_solver is called with a reference or moved value consistent with its signature; remove the solver_pubkey_clone binding and adjust the surrounding code that prepares parameters (client_clone, result_tx, mostro_info) so they are moved/borrowed into the spawned task similarly.src/main.rs (1)
103-123: Optional: extract shared paste-append helper for admin key inputs.Line 105-123 repeats the same sanitize/append/
just_pastedpattern for two admin input states; pulling this into a small helper would reduce drift risk on future input updates.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main.rs` around lines 103 - 123, Extract the repeated paste-and-append logic into a small helper function (e.g., sanitize_and_append_paste) and replace the duplicated blocks in the UiMode::AdminMode(AdminMode::AddSolver(ref mut add_solver_state)) and UiMode::AdminMode(AdminMode::SetupAdminKey(ref mut key_state)) arms to call it; the helper should take the pasted_text and a mutable reference to the input buffer and just_pasted flag (or the state struct), perform the chars().filter(|c| !c.is_control() || *c == '\t').collect(), append the result to the target key_input (for AddSolver use add_solver_state.key_input.key_input.push_str, for SetupAdminKey use key_state.key_input.push_str), and set just_pasted = true so both add_solver_state and key_state reuse the same logic.src/ui/draw.rs (1)
460-464: Optional render-path optimization: avoid cloning solver input each draw.You can render with
&str/Cow<'_, str>instead of allocating a newStringevery frame on Line 463.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/ui/draw.rs` around lines 460 - 464, The current code always allocates a new String for input_display by cloning add_solver_state.key_input.key_input; instead use a borrowed &str or Cow<'_, str> to avoid per-frame allocation: change input_display's type to &str or Cow<'_, str> and return either a borrowed literal ("npub... / hex...") or a borrowed slice of add_solver_state.key_input.key_input (e.g., &add_solver_state.key_input.key_input) instead of calling .clone(), referencing the symbol add_solver_state.key_input.key_input and the binding input_display to locate where to update.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/main.rs`:
- Around line 103-123: Extract the repeated paste-and-append logic into a small
helper function (e.g., sanitize_and_append_paste) and replace the duplicated
blocks in the UiMode::AdminMode(AdminMode::AddSolver(ref mut add_solver_state))
and UiMode::AdminMode(AdminMode::SetupAdminKey(ref mut key_state)) arms to call
it; the helper should take the pasted_text and a mutable reference to the input
buffer and just_pasted flag (or the state struct), perform the
chars().filter(|c| !c.is_control() || *c == '\t').collect(), append the result
to the target key_input (for AddSolver use
add_solver_state.key_input.key_input.push_str, for SetupAdminKey use
key_state.key_input.push_str), and set just_pasted = true so both
add_solver_state and key_state reuse the same logic.
In `@src/ui/draw.rs`:
- Around line 460-464: The current code always allocates a new String for
input_display by cloning add_solver_state.key_input.key_input; instead use a
borrowed &str or Cow<'_, str> to avoid per-frame allocation: change
input_display's type to &str or Cow<'_, str> and return either a borrowed
literal ("npub... / hex...") or a borrowed slice of
add_solver_state.key_input.key_input (e.g.,
&add_solver_state.key_input.key_input) instead of calling .clone(), referencing
the symbol add_solver_state.key_input.key_input and the binding input_display to
locate where to update.
In `@src/ui/key_handler/admin_handlers.rs`:
- Around line 92-110: There’s an unnecessary clone of solver_pubkey
(solver_pubkey_clone) before spawning the task; instead move/own solver_pubkey
into the async block and use it there to avoid the extra clone. Replace usage of
solver_pubkey_clone with solver_pubkey inside the tokio::spawn closure and
ensure execute_admin_add_solver is called with a reference or moved value
consistent with its signature; remove the solver_pubkey_clone binding and adjust
the surrounding code that prepares parameters (client_clone, result_tx,
mostro_info) so they are moved/borrowed into the spawned task similarly.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 1050bd0a-21de-4981-8f0a-6525cd59d945
📒 Files selected for processing (12)
src/lib.rssrc/main.rssrc/shared/mod.rssrc/shared/permissions.rssrc/ui/admin_state.rssrc/ui/draw.rssrc/ui/help_popup.rssrc/ui/key_handler/admin_handlers.rssrc/ui/key_handler/enter_handlers.rssrc/ui/mod.rssrc/ui/state.rssrc/util/order_utils/execute_admin_add_solver.rs
✅ Files skipped from review due to trivial changes (4)
- src/shared/mod.rs
- src/lib.rs
- src/ui/state.rs
- src/ui/help_popup.rs
🚧 Files skipped from review as they are similar to previous changes (3)
- src/ui/mod.rs
- src/ui/key_handler/enter_handlers.rs
- src/util/order_utils/execute_admin_add_solver.rs
There was a problem hiding this comment.
Re-reviewed the follow-up commits after my earlier approval.
I only checked the new changes since f166ceed, and they look fine to me:
SolverPermissionwas moved into a shared module, which is a reasonable cleanup and does not change the behavior- the add-solver call path still passes the selected permission through correctly
- the small draw/help updates are harmless and consistent with the UI flow
- checks are green on the latest head commit
I do not see a new blocker in the follow-up commits, so my approval still stands.
Improve the admin add-solver flow by introducing a read/read-write permission selector in the popup and carrying that choice through confirmation and submission. Format admin-add-solver payloads according to protocol expectations, preserve state on cancel paths, and refresh help text and tests for the new behavior.
Summary by CodeRabbit
New Features
Improvements