Skip to content

Conversation

@wksantiago
Copy link
Contributor

@wksantiago wksantiago commented Jan 15, 2026

Summary

  • Add CLI integration test framework
  • Test complete workflows: init, generate, list, export, delete
  • Test FROST generate and sign
  • Test hidden volume operations
  • Test error cases

Test plan

  • CI passes
  • Tests run with cargo test -p keep-cli

Summary by CodeRabbit

  • New Features

    • Frost signing accepts either a group identifier or a named local group.
    • Vault creation supports configurable key-derivation parameters (e.g., testing/custom KDF).
    • CLI can read hidden passwords and secret keys from environment variables for non-interactive use.
  • Tests

    • Added comprehensive end-to-end CLI integration tests covering init, generate, list, export/import, multi-key flows, Frost signing, hidden volumes, and password validation.
  • Chores

    • Added dev-time cryptography utilities as development dependencies.

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

@coderabbitai
Copy link

coderabbitai bot commented Jan 15, 2026

Walkthrough

Adds dev-only crypto deps and a comprehensive CLI integration test suite; introduces env-driven nsec/hidden-password input; parameterizes Argon2 KDF through Keep/HiddenStorage creation APIs; and updates FROST signing to accept either an npub1... or a named local group with optional warden policy checks.

Changes

Cohort / File(s) Summary
Dev dependencies
keep-cli/Cargo.toml
Add dev-dependencies sha2 = "0.10" and hex = "0.4".
Integration tests
keep-cli/tests/cli_integration.rs
Add a new end-to-end CLI integration test suite and KeepCmd test helper exercising init/generate/list/export/import/delete, FROST signing, hidden volumes, password edge cases, and CLI flags.
FROST signing (CLI)
keep-cli/src/commands/frost.rs
Rename group_npubgroup_id; resolve group_pubkey from either a direct npub1... string or by looking up a local group name in stored shares; use group_id for logging and warden policy checks; update error paths.
CLI helpers
keep-cli/src/commands/mod.rs
Add pub fn get_hidden_password(prompt: &str) -> Result<SecretString> and pub fn get_nsec(prompt: &str) -> Result<SecretString> to read KEEP_HIDDEN_PASSWORD/KEEP_NSEC or prompt interactively.
Vault / KDF parameterization
keep-cli/src/commands/vault.rs, keep-core/src/hidden/volume.rs, keep-core/src/lib.rs
Introduce Argon2Params propagation: HiddenStorage::create(...) and Keep::create_with_params(...) accept params; creation/unlock flows use provided/header Argon2Params; existing Keep::create delegates to create_with_params with default params; tests updated to use Argon2Params::TESTING.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as keep-cli (user)
  participant Keep as Keep library
  participant Storage as Local Storage (shares)
  participant Warden as Warden (optional)
  participant Signer as Local partial signer

  CLI->>Keep: cmd_frost_sign(group_id, message_hex)
  alt group_id starts with "npub1"
    Keep->>Signer: parse npub → group_pubkey
  else group_id is name
    Keep->>Storage: lookup group by name
    Storage-->>Keep: group_pubkey (or not found)
  end
  alt warden_url provided
    Keep->>Warden: policy-check(group_pubkey)
    Warden-->>Keep: allow / deny
  end
  Keep->>Signer: perform FROST signing with resolved group_pubkey
  Signer-->>CLI: signature or error
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • kwsantiago

Poem

🐰
I hopped through code and found a key,
New tests and params beneath a tree,
From npub paths to hidden ground,
Signs and vaults in loops unbound,
A carrot cheer for builds set free 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 51.85% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately summarizes the main change: adding end-to-end CLI integration tests. This directly corresponds to the primary file addition (cli_integration.rs with 448 new lines of tests) and the PR's stated objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings


📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 05292e8 and 876af39.

📒 Files selected for processing (2)
  • keep-cli/src/commands/mod.rs
  • keep-cli/src/commands/vault.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (10)
keep-cli/src/commands/mod.rs (2)

28-38: LGTM!

The function correctly mirrors the existing get_password pattern and provides env-var override for non-interactive testing scenarios.


64-75: LGTM!

The function follows the established pattern and appropriately uses the Password widget to mask nsec input.

keep-cli/src/commands/vault.rs (8)

79-84: Verify KEEP_TESTING_MODE cannot be accidentally enabled in production.

Using a testing mode that weakens Argon2 parameters is a standard pattern for CI speed. However, ensure that production deployment scripts, containers, or environments never set this variable, as it significantly reduces key-derivation security.


86-97: LGTM!

The params argument is correctly propagated to both HiddenStorage::create and Keep::create_with_params, enabling configurable KDF parameters for testing.


191-191: LGTM!

Correctly uses get_hidden_password for hidden volume operations, enabling env-var override for testing.


239-239: LGTM!

Using get_nsec enables non-interactive nsec input via the KEEP_NSEC env var for integration tests.


305-311: LGTM!

The hidden import flow correctly uses get_hidden_password and get_nsec for their respective inputs.


433-433: LGTM!

Correctly uses get_hidden_password for the hidden volume list operation.


557-557: LGTM!

Correctly uses get_hidden_password for the hidden volume export operation.


672-672: LGTM!

Correctly uses get_hidden_password for the hidden volume delete operation. All hidden-related commands now consistently use the dedicated helper.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@wksantiago wksantiago requested a review from kwsantiago January 15, 2026 15:28
@wksantiago wksantiago self-assigned this Jan 15, 2026
@wksantiago wksantiago linked an issue Jan 15, 2026 that may be closed by this pull request
Copy link

@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

Caution

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

⚠️ Outside diff range comments (1)
keep-cli/src/commands/frost.rs (1)

357-362: Move group_id resolution before warden policy check to pass the resolved npub.

The warden policy check receives group_id directly, which can be a group name rather than an npub. The function parameter is named group_npub, indicating it expects an npub format. However, group name-to-pubkey resolution happens later (lines 381–390), after the policy check. If the user provides a group name instead of an npub, the warden service receives the name string instead of the resolved public key, likely causing the policy check to fail.

Resolve the group identifier before the warden check to ensure the service receives the correct npub format. This requires moving the group lookup logic before the policy check and passing the resolved npub to check_warden_policy.

🧹 Nitpick comments (2)
keep-cli/tests/cli_integration.rs (1)

10-32: Consider using env!("CARGO_BIN_EXE_keep") for binary discovery.

The current binary discovery logic traverses multiple paths. Cargo provides env!("CARGO_BIN_EXE_<name>") at compile time for integration tests, which is more reliable.

However, the current approach works and handles edge cases where the macro might not be available. This is acceptable as-is.

Alternative approach using Cargo's built-in macro
fn keep_binary() -> Option<PathBuf> {
    // Try Cargo's compile-time path first
    let cargo_path = option_env!("CARGO_BIN_EXE_keep");
    if let Some(p) = cargo_path {
        let path = PathBuf::from(p);
        if path.exists() {
            return Some(path);
        }
    }
    // Fall back to current discovery logic
    // ... existing code ...
}
keep-cli/src/commands/vault.rs (1)

253-333: Consider extracting common patterns to reduce duplication.

The import functions (cmd_import, cmd_import_outer, cmd_import_hidden) share significant structural similarity—open storage, unlock, get nsec, create keypair, encrypt and store. The same pattern appears in generate, export, and delete operations.

A helper or trait-based abstraction could reduce this duplication while maintaining the distinct unlock semantics for each volume type. This is not urgent but could improve long-term maintainability.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1c1da79 and 05292e8.

📒 Files selected for processing (6)
  • keep-cli/src/commands/frost.rs
  • keep-cli/src/commands/mod.rs
  • keep-cli/src/commands/vault.rs
  • keep-cli/tests/cli_integration.rs
  • keep-core/src/hidden/volume.rs
  • keep-core/src/lib.rs
🧰 Additional context used
🧬 Code graph analysis (3)
keep-core/src/lib.rs (1)
keep-core/src/storage.rs (2)
  • path (334-336)
  • create (122-165)
keep-core/src/hidden/volume.rs (3)
keep-core/src/hidden/header.rs (2)
  • new (35-52)
  • new (182-198)
keep-core/src/crypto.rs (5)
  • new (30-46)
  • new (101-115)
  • new (159-166)
  • new (218-225)
  • derive_key (264-285)
keep-core/src/storage.rs (3)
  • new (38-51)
  • create (122-165)
  • path (334-336)
keep-cli/src/commands/frost.rs (2)
keep-frost-net/src/node.rs (1)
  • group_pubkey (236-238)
keep-core/src/keys.rs (1)
  • npub_to_bytes (148-162)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (14)
keep-cli/src/commands/mod.rs (1)

52-63: LGTM!

The get_nsec function follows the established pattern of get_password and correctly handles both environment variable and interactive input paths. Using Password prompt ensures the nsec is not displayed during input.

keep-core/src/lib.rs (1)

39-51: LGTM!

Good refactoring that introduces create_with_params while preserving backward compatibility. The delegation pattern keeps create() unchanged for existing callers while enabling parameterized creation for tests and special use cases.

keep-cli/tests/cli_integration.rs (4)

84-99: Polling loop is functional but could use wait_timeout if available.

The busy-wait polling with 100ms sleep works, but std::process::Child doesn't have a native wait_timeout. The current implementation is acceptable for integration tests.


124-153: LGTM!

Comprehensive workflow test covering the full lifecycle of init → generate → list → export. Good use of assertion helpers.


252-306: LGTM!

Good FROST signing test. The message hash using SHA-256 is appropriate, and the signature validation correctly checks for a 64-byte hex-encoded output (128 characters).


308-350: LGTM!

Excellent test for hidden volume isolation. Verifies that outer and hidden volumes maintain separate key spaces and that keys in one volume are not visible in the other.

keep-cli/src/commands/frost.rs (1)

379-392: LGTM - Good UX improvement for group identification.

The dual-mode resolution (npub or name) improves usability. The npub1 prefix check correctly identifies bech32-encoded public keys.

keep-core/src/hidden/volume.rs (3)

68-75: LGTM - Good API extension for parameterized creation.

Adding Argon2Params to the create signature enables testing with lightweight parameters while maintaining production-strength defaults through the caller.


301-305: Design note: Hidden volume inherits Argon2 params from outer header.

The hidden unlock path uses self.outer_header.argon2_params(). This is consistent with the creation flow where both volumes are created with the same params argument. The design ensures both volumes have matching security parameters.


651-677: LGTM!

Test correctly updated to use Argon2Params::TESTING for faster execution while maintaining the same test coverage.

keep-cli/src/commands/vault.rs (4)

8-8: LGTM!

Import additions are appropriate for the new parameterized Argon2 support and centralized nsec input handling.

Also applies to: 15-15


76-81: Appropriate test configuration pattern.

Using environment-based Argon2 parameter selection is a reasonable approach for integration tests. The debug log provides useful visibility when lightweight parameters are active.

Minor note: Consider documenting in the README or contributing guide that KEEP_TESTING_MODE must never be set in production environments, as Argon2Params::TESTING significantly weakens key derivation security.


83-94: LGTM!

The params argument is correctly propagated to both HiddenStorage::create and Keep::create_with_params, ensuring consistent Argon2 parameter usage across hidden and regular vault creation paths.


236-236: LGTM!

Consistent use of get_nsec across all import flows (cmd_import, cmd_import_outer, cmd_import_hidden) improves maintainability and likely enables environment-based nsec input for integration testing.

Also applies to: 267-267, 308-308

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

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.

Add end-to-end CLI integration test suite

2 participants