Skip to content

Commit 10bd3e7

Browse files
Merge pull request #33 from Spacecraft-Software/card-cardholder-field
feat(vault): card-cardholder read selector (+ TUI prefill)
2 parents 20b999d + c8dedb8 commit 10bd3e7

7 files changed

Lines changed: 30 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ range may break in any release.
1010

1111
### Added
1212

13+
- **`card-cardholder` field selector.** `vault get <card> --field card-cardholder`
14+
now returns the cardholder name, and the TUI detail pane shows a `Holder` line
15+
— which also lets the TUI card **edit** form prefill the cardholder (it
16+
previously started blank, as there was no read selector). Closes the
17+
card edit-prefill gap from the card-write / TUI-card slices.
18+
1319
- **`mlock` the user keys (no swap exposure).** The agent's unwrapped user keys
1420
(`user_enc`/`user_mac`) are now wrapped in a `SealedKey` newtype that boxes the
1521
bytes for a stable address and `mlock`s their page(s) so they can't be paged to

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ Card (type 3) and identity (type 4) ciphers are readable from the CLI via
9999
`--field`:
100100

101101
```sh
102-
vault get visa --field card-number # also: card-brand, card-expiry, card-code
102+
vault get visa --field card-number # also: card-cardholder, card-brand, card-expiry, card-code
103103
vault get me --field identity-email # also: identity-name, identity-phone, identity-address
104104
```
105105

crates/vault-agent/src/state.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -772,12 +772,14 @@ impl AgentState {
772772
primary_uri: true,
773773
..DecryptOptions::default()
774774
},
775-
Field::CardNumber | Field::CardBrand | Field::CardExpiry | Field::CardCode => {
776-
DecryptOptions {
777-
card: true,
778-
..DecryptOptions::default()
779-
}
780-
}
775+
Field::CardCardholder
776+
| Field::CardNumber
777+
| Field::CardBrand
778+
| Field::CardExpiry
779+
| Field::CardCode => DecryptOptions {
780+
card: true,
781+
..DecryptOptions::default()
782+
},
781783
Field::IdentityName
782784
| Field::IdentityEmail
783785
| Field::IdentityPhone
@@ -803,6 +805,7 @@ impl AgentState {
803805
},
804806
Field::Notes => plain.notes.clone(),
805807
Field::Uri => plain.primary_uri.clone(),
808+
Field::CardCardholder => plain.card.as_ref().and_then(|c| c.cardholder_name.clone()),
806809
Field::CardNumber => plain.card.as_ref().and_then(|c| c.number.clone()),
807810
Field::CardBrand => plain.card.as_ref().and_then(|c| c.brand.clone()),
808811
Field::CardCode => plain.card.as_ref().and_then(|c| c.code.clone()),

crates/vault-cli/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ enum FieldArg {
446446
Totp,
447447
Notes,
448448
Uri,
449+
CardCardholder,
449450
CardNumber,
450451
CardBrand,
451452
CardExpiry,
@@ -464,6 +465,7 @@ impl From<FieldArg> for Field {
464465
FieldArg::Totp => Self::Totp,
465466
FieldArg::Notes => Self::Notes,
466467
FieldArg::Uri => Self::Uri,
468+
FieldArg::CardCardholder => Self::CardCardholder,
467469
FieldArg::CardNumber => Self::CardNumber,
468470
FieldArg::CardBrand => Self::CardBrand,
469471
FieldArg::CardExpiry => Self::CardExpiry,

crates/vault-ipc/src/proto.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,8 @@ pub enum Field {
533533
Notes,
534534
/// First `Login.Uris[].Uri`.
535535
Uri,
536+
/// `Card.CardholderName`.
537+
CardCardholder,
536538
/// `Card.Number`.
537539
CardNumber,
538540
/// `Card.Brand`.

crates/vault-tui/src/app.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -682,9 +682,8 @@ impl FormState {
682682

683683
/// An edit form for `entry`, prefilled with the metadata the list already
684684
/// carries (name / username / folder). For a card, `detail` (the pane's
685-
/// on-select fetch) prefills `Brand`/`Expiry`. Secrets stay blank — blank
686-
/// means "leave unchanged" on submit (so does the un-prefilled cardholder,
687-
/// which has no fetch selector yet).
685+
/// on-select fetch) prefills `Holder`/`Brand`/`Expiry`. Secrets stay blank —
686+
/// blank means "leave unchanged" on submit.
688687
#[must_use]
689688
pub fn new_edit(entry: &ListEntry, detail: Option<&DetailView>) -> Self {
690689
let mut fields = Self::blank_fields();
@@ -705,6 +704,7 @@ impl FormState {
705704
// pane's `Person`/`Address` are composites that can't be split
706705
// back, so those rows start blank = leave-unchanged.
707706
match (entry.cipher_type, label.as_str()) {
707+
(3, "Holder") => prefill(F_CARDHOLDER, value),
708708
(3, "Brand") => prefill(F_BRAND, value),
709709
(3, "Exp") => prefill(F_EXPIRY, value),
710710
(4, "Email") => prefill(F_EMAIL, value),
@@ -2526,6 +2526,7 @@ mod tests {
25262526
app.detail = Some(DetailView {
25272527
id: "id-visa".to_owned(),
25282528
lines: vec![
2529+
("Holder".to_owned(), "A. Cardholder".to_owned()),
25292530
("Brand".to_owned(), "Visa".to_owned()),
25302531
("Exp".to_owned(), "04/2030".to_owned()),
25312532
],
@@ -2540,6 +2541,7 @@ mod tests {
25402541
.map(|r| r.value.to_owned())
25412542
.expect("row exists")
25422543
};
2544+
assert_eq!(value_of("Holder"), "A. Cardholder");
25432545
assert_eq!(value_of("Brand"), "Visa");
25442546
assert_eq!(value_of("Expiry"), "04/2030");
25452547
assert_eq!(value_of("Number"), "", "secrets are never prefilled");

crates/vault-tui/src/main.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,11 @@ async fn ensure_detail(state: &mut App, socket: &Path) {
762762
return; // already cached for this item
763763
}
764764
let specs: &[(&str, Field)] = match sel.cipher_type {
765-
3 => &[("Brand", Field::CardBrand), ("Exp", Field::CardExpiry)],
765+
3 => &[
766+
("Holder", Field::CardCardholder),
767+
("Brand", Field::CardBrand),
768+
("Exp", Field::CardExpiry),
769+
],
766770
4 => &[
767771
("Person", Field::IdentityName),
768772
("Email", Field::IdentityEmail),

0 commit comments

Comments
 (0)