Implement the in-process structured entry editor

Closes #21
This commit is contained in:
Hermes Agent
2026-08-10 07:22:55 +00:00
parent cf7a6216ac
commit b503de8b2e
14 changed files with 1547 additions and 37 deletions

View File

@@ -238,11 +238,12 @@ fn atomic_save_creates_updates_and_rejects_stale_documents() -> TestResult {
let stale_password = stale.password().expect("password").id();
stale.update(stale_password, EntryFieldDraft::line(b"stale".to_vec())?)?;
assert!(matches!(
service.save(stale, None, &mut committer),
service.save_recoverable(&stale, None, &mut committer),
Err(DocumentError::Write(
WriteError::ConcurrentModification { .. }
))
));
assert_eq!(stale.serialize().expose(), b"stale\nusername: alice");
assert_eq!(
repository.read_entry(&EntryPath::parse("documents/new")?)?,
winner
@@ -253,9 +254,31 @@ fn atomic_save_creates_updates_and_rejects_stale_documents() -> TestResult {
rollback.update(password, EntryFieldDraft::line(b"must roll back".to_vec())?)?;
committer.fail = true;
assert!(matches!(
service.save(rollback, None, &mut committer),
service.save_recoverable(&rollback, None, &mut committer),
Err(DocumentError::Write(WriteError::Commit(_)))
));
assert!(
rollback
.serialize()
.expose()
.starts_with(b"must roll back\n")
);
assert_eq!(
repository.read_entry(&EntryPath::parse("documents/new")?)?,
winner
);
committer.fail = false;
std::fs::write(
store.path().join(".gpg-id"),
b"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n",
)?;
let retained = rollback.serialize();
assert!(
service
.save_recoverable(&rollback, None, &mut committer)
.is_err()
);
assert_eq!(rollback.serialize().expose(), retained.expose());
assert_eq!(
repository.read_entry(&EntryPath::parse("documents/new")?)?,
winner

View File

@@ -131,6 +131,21 @@ fn deterministic_generation_uses_only_requested_characters_and_length() -> TestR
Ok(())
}
#[test]
fn in_process_generation_returns_a_zeroizing_unstored_secret() -> TestResult {
let config = GeneratorConfig::new(12, "abc123")?;
let generated = config.generate_secret(NonZeroUsize::new(48), false)?;
assert_eq!(generated.expose().len(), 48);
assert!(
generated
.expose()
.iter()
.all(|byte| b"abc123".contains(byte))
);
assert!(!format!("{generated:?}").contains(std::str::from_utf8(generated.expose())?));
Ok(())
}
#[test]
fn default_no_symbols_and_presentation_actions_are_typed() -> TestResult {
let fixture = FixtureSet::load()?;