cred: keep typed secret entry configuration valid

This commit is contained in:
2026-11-06 20:16:24 +00:00
parent 091f679905
commit 30dcd4c2ca
2 changed files with 55 additions and 0 deletions
+1
View File
@@ -295,6 +295,7 @@ impl Cred {
config.fields[index].needs_value = false;
config.fields[index].field_type = kind;
config.fields[index].key_type = key_type;
validate(&config)?;
tx.execute(
"INSERT INTO versions(item,created,config) VALUES(?1,unixepoch(),?2)",
params![item, previous],
+54
View File
@@ -218,8 +218,61 @@ fn deleted_item_revert_preserves_identity_but_never_restores_secrets() {
assert_eq!(restored.fields[0].field_id, item.fields[0].field_id);
}
#[test]
fn secret_entry_keeps_oauth_cardinality_and_rolls_back_ciphertext() {
let (dir, cred, caller, item) = fixture();
let input = FieldInput {
value: "opaque",
field_type: Some(types::FieldType::Oauth2RefreshToken),
key_type: None,
};
cred.set_field_input(&item.id, &item.fields[0].field_id, &input, &caller, "pk")
.unwrap();
cred.set_field(&item.id, &item.fields[1].field_id, "opaque", &caller, "pk")
.unwrap();
let current = cred.item_get(&item.id).unwrap();
let history = cred.item_versions(&item.id).unwrap().len();
let audit = cred.audit_list().unwrap().len();
let db = rusqlite::Connection::open(dir.path().join("cred.sqlite")).unwrap();
let cipher = || {
db.query_row(
"SELECT ciphertext FROM fields WHERE item=?1 AND id=?2",
rusqlite::params![item.id, item.fields[1].field_id],
|r| r.get::<_, Vec<u8>>(0),
)
.unwrap()
};
let before = cipher();
assert_eq!(
cred.set_field_input(&item.id, &item.fields[1].field_id, &input, &caller, "pk")
.err()
.unwrap()
.0,
"invalid_params"
);
assert!(cipher() == before);
assert_eq!(cred.item_get(&item.id).unwrap().version, current.version);
assert_eq!(cred.item_versions(&item.id).unwrap().len(), history);
assert_eq!(cred.audit_list().unwrap().len(), audit);
}
#[test]
fn typed_secret_entry_and_bundle_normalization() {
let (_dir, cred, caller, item) = fixture();
let mut metadata = item.clone();
metadata.fields[0].field_type = types::FieldType::SshPrivateKey;
metadata.fields[0].key_type = Some("es256".into());
let id = cred
.file_edit_request(
&caller,
"metadata",
Edit {
item: item.id.clone(),
base_version: item.version,
config: metadata,
},
)
.unwrap();
cred.approve(&id, "yes", Overrides::default(), Some("pk"))
.unwrap();
let input = FieldInput {
value: "two\nlines",
field_type: Some(types::FieldType::Note),
@@ -229,6 +282,7 @@ fn typed_secret_entry_and_bundle_normalization() {
.unwrap();
let current = cred.item_get(&item.id).unwrap();
assert_eq!(current.fields[0].field_type, types::FieldType::Note);
assert!(current.fields[0].key_type.is_none());
assert!(current.fields[0].value.is_none());
assert_eq!(
cred.item_versions(&item.id).unwrap()[0].config.fields[0].field_type,