feat(cli): --*-stdin secret flags for personal add (non-interactive secrets)

This commit is contained in:
adlee-was-taken
2026-06-20 17:51:15 -04:00
parent 751e4e9bb1
commit 6eb1275710
4 changed files with 88 additions and 36 deletions

View File

@@ -15,22 +15,22 @@ pub fn cmd_add(kind: AddKind) -> Result<()> {
let mut manifest = vault.load_manifest()?;
let item = match kind {
AddKind::Login { title, username, url, password_prompt, password, group, tags, favorite, totp_qr } => {
AddKind::Login { title, username, url, password_prompt, password, password_stdin, group, tags, favorite, totp_qr } => {
let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
let username = prompt_or_flag_optional(username, "Username", |s| Ok(s.to_string()))?;
let url = prompt_or_flag_optional(url, "URL", |s| Ok(s.to_string()))?;
let mut item = ib::build_login(title, username, url, password, /*password_stdin*/ false, password_prompt, totp_qr)?;
let mut item = ib::build_login(title, username, url, password, password_stdin, password_prompt, totp_qr)?;
item.group = group; item.tags = tags; item.favorite = favorite;
item
}
AddKind::SecureNote { title, body_prompt: _, group, tags } => {
// NOTE: per the v0.8.1 spec's unified secret model, a note body is a
// multiline secret that always reads stdin to EOF; the legacy single-line
// `prompt("Body")` path is retired. `false` here means "print the Ctrl-D
// hint" (interactive default). A4 replaces `--body-prompt` with `--body-stdin`
// and threads the real flag. `body_prompt` is intentionally ignored this task.
AddKind::SecureNote { title, body_stdin, group, tags } => {
// Per the v0.8.1 spec's unified secret model, a note body is a
// multiline secret that always reads stdin to EOF. `body_stdin=false`
// means "print the Ctrl-D hint" (interactive default); `true` suppresses
// the hint for non-interactive use.
// Secret-resolution rule: `commands/item_build.rs` `resolve_secret_multiline`.
let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
let mut item = ib::build_secure_note(title, None, /*body_stdin*/ false)?;
let mut item = ib::build_secure_note(title, None, body_stdin)?;
item.group = group; item.tags = tags;
item
}
@@ -40,18 +40,18 @@ pub fn cmd_add(kind: AddKind) -> Result<()> {
item.group = group; item.tags = tags;
item
}
AddKind::Card { title, holder, expiry, kind, group, tags } => {
AddKind::Card { title, holder, expiry, kind, number_stdin, cvv_stdin, pin_stdin, group, tags } => {
let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
let mut item = ib::build_card(title, holder, expiry, &kind, false, false, false)?;
let mut item = ib::build_card(title, holder, expiry, &kind, number_stdin, cvv_stdin, pin_stdin)?;
item.group = group; item.tags = tags;
item
}
AddKind::Key { title, label, algorithm, group, tags } => {
AddKind::Key { title, label, algorithm, material_stdin, group, tags } => {
// public_key is None for the personal vault: the legacy `prompt_optional`
// for it was unreachable (stdin already at EOF after the key-material read).
// Org `add key` (Dev-B) supplies it via --public-key.
let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
let mut item = ib::build_key(title, label, algorithm, None, false)?;
let mut item = ib::build_key(title, label, algorithm, None, material_stdin)?;
item.group = group; item.tags = tags;
item
}
@@ -65,9 +65,9 @@ pub fn cmd_add(kind: AddKind) -> Result<()> {
std::fs::write(att_dir.join(format!("{}.enc", enc.id.as_str())), &enc.bytes)?;
item
}
AddKind::Totp { title, issuer, label, secret, period, digits, algorithm, group, tags } => {
AddKind::Totp { title, issuer, label, secret, secret_stdin, period, digits, algorithm, group, tags } => {
let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
let mut item = ib::build_totp(title, issuer, label, secret, false, period, digits, &algorithm)?;
let mut item = ib::build_totp(title, issuer, label, secret, secret_stdin, period, digits, &algorithm)?;
item.group = group; item.tags = tags;
item
}