Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
Rite is early-stage and the design is still evolving.
Pull requests are welcome, but opening an issue to discuss the change first is strongly preferred, it avoids wasted effort on both sides.

CLI behavior conventions are documented in `docs/cli-conventions.md`.

## Local checks

Run these before pushing.
Expand Down
20 changes: 17 additions & 3 deletions crates/rite-cli/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,15 @@ pub fn build_inputs(

for s in params {
let (key, value) = parse_key_value(s)?;
input_params.insert(key, serde_json::Value::String(value));
input_params.insert(key.to_lowercase(), serde_json::Value::String(value));
}
for s in roles {
let (key, value) = parse_key_value(s)?;
input_roles.insert(key, value);
input_roles.insert(key.to_lowercase(), value);
}
for s in materials {
let (key, value) = parse_key_value(s)?;
input_materials.insert(key, parse_material_value(&value));
input_materials.insert(key.to_lowercase(), parse_material_value(&value));
}

Ok(CeremonyInputs {
Expand Down Expand Up @@ -213,4 +213,18 @@ mod tests {
matches!(source, MaterialSource::Identifier { identifier } if identifier == "my-identifier")
);
}

#[test]
fn build_inputs_normalizes_cli_keys_to_lowercase() {
let inputs = build_inputs(
&["Param_Name=value".to_string()],
&["Role_ID=Alice".to_string()],
&["Material_ID=@file.pem".to_string()],
)
.expect("inputs build");

assert!(inputs.parameters.contains_key("param_name"));
assert!(inputs.roles.contains_key("role_id"));
assert!(inputs.materials.contains_key("material_id"));
}
}
8 changes: 8 additions & 0 deletions crates/rite-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@ mod verify;
use clap::{CommandFactory, Parser, Subcommand};
use clap_complete::{Shell, generate};

const TOP_LEVEL_AFTER_HELP: &str = "\
Lifecycle:
rite check ceremony.rite.yaml
rite run ceremony.rite.yaml
rite verify <output-dir-or-transcript.jsonl>
";

#[derive(Parser)]
#[command(name = "rite")]
#[command(version)]
#[command(about = "A CLI for cryptographic key ceremonies", long_about = None)]
#[command(after_help = TOP_LEVEL_AFTER_HELP)]
struct Cli {
#[command(subcommand)]
command: Commands,
Expand Down
4 changes: 2 additions & 2 deletions crates/rite-cli/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ pub fn run(args: Args) {

match executor.execute(&resolved, backend_registry) {
Ok(_) => {
eprintln!("\nOutput directory: {}", output_dir.display());
println!("Output directory: {}", output_dir.display());
std::process::exit(0);
}
Err(e) => {
eprintln!("\nCeremony failed: {e}");
eprintln!("Ceremony failed: {e}");
std::process::exit(1);
}
}
Expand Down
2 changes: 2 additions & 0 deletions crates/rite-cli/src/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ pub fn run(args: Args) {
status,
events_count,
} => {
// TODO: Revisit exit-code policy for Incomplete; currently uses 2 as a
// special-case status distinct from generic verification failure.
eprintln!("Incomplete transcript (no final fingerprint).");
eprintln!(" Status: {status:?}");
eprintln!(" Events recorded: {events_count}");
Expand Down
24 changes: 24 additions & 0 deletions docs/cli-conventions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# CLI Conventions

Scope: `crates/rite-cli`.

## Exit codes

- `0`: success
- `1`: command/domain/runtime failure
- `2`: CLI usage and argument parsing errors

## Output channels

- `stdout`: successful user-consumable command output
- `stderr`: diagnostics, warnings, errors, and progress/status messages

## Input key normalization

- User-provided input keys should be normalized consistently across all input sources.
- This includes CLI flags (`--param`, `--role`, `--material`) and environment variables (`RITE_PARAM_*`, `RITE_ROLE_*`, `RITE_MATERIAL_*`).

## Interactive prompting

- Interactive prompts are enabled by default for interactive commands.
- Commands may provide explicit flags to disable prompting (for example `--no-prompt`).