Skip to content

fix(deps): update keepass to 0.12 and migrate provider to new API#494

Merged
jdx merged 2 commits into
mainfrom
fix/keepass-0.12-migration
May 17, 2026
Merged

fix(deps): update keepass to 0.12 and migrate provider to new API#494
jdx merged 2 commits into
mainfrom
fix/keepass-0.12-migration

Conversation

@jdx
Copy link
Copy Markdown
Owner

@jdx jdx commented May 17, 2026

Summary

Supersedes #469 (Renovate's blind 0.10 → 0.12 bump which doesn't compile). Includes Renovate's Cargo.toml/Cargo.lock bump plus the matching provider rewrite for the new encapsulated keepass API.

What changed in keepass 0.12

  • Group.groups, Group.entries, Database.root, Entry::new, and Group::new are now pub(crate).
  • Public access is via accessor methods: Database::root() / root_mut(), GroupRef::groups() / entries(), GroupMut::add_group() / add_entry().
  • Database::new() is zero-arg now (was Database::new(DatabaseConfig::default())).

Provider migration

  • Entry lookup now returns EntryId, then resolves to EntryRef / EntryMut via Database::entry / entry_mut. This sidesteps the lifetime issues of recursive GroupRef borrows.
  • Write path navigates and creates groups segment-by-segment via group_mut/add_group, then updates an existing entry or calls add_entry on the target group.
  • Field writes use the new set_protected / set_unprotected helpers — same "Password is protected, everything else is unprotected" behavior.

No behavior change

The lookup semantics are preserved: path segments before the last name exact-named subgroups to navigate into; the final segment is searched recursively by entry title.

Test plan

  • cargo build — clean
  • cargo clippy --workspace --all-targets — clean
  • cargo test -p fnox-core keepass --lib — 4 passed
  • KEEPASS_PASSWORD=test mise run test:bats -- test/keepass.bats23/23 passed
  • CI green across all targets

🤖 Generated with Claude Code


Note

Medium Risk
Updates a secrets-storage dependency and rewrites the KeePass provider’s read/write traversal and mutation logic, which could affect entry lookup and database writes. Changes are localized but touch persistent secret data handling.

Overview
Updates the keepass crate to 0.12 (and refreshes Cargo.lock, including a quick-xml bump) and migrates the KeePass provider to the new encapsulated API.

The provider now resolves entries via EntryId/GroupId and GroupRef accessors, adds group creation via group_mut().add_group(), and writes fields using set_protected/set_unprotected (keeping Password protected semantics). Database creation is updated to the new Database::new() signature, while lookup semantics are preserved by recursively searching for entry titles under the target group.

Reviewed by Cursor Bugbot for commit cdaebc4. Bugbot is set up for automated code reviews on this repo. Configure here.

renovate Bot and others added 2 commits May 17, 2026 16:54
The 0.12 release made the database model encapsulated: `Group.groups`,
`Group.entries`, `Database.root`, and `Entry::new`/`Group::new` are now
private. Public access goes through `Database::root()` / `root_mut()`,
`GroupRef::groups()` / `entries()`, and `GroupMut::add_group()` /
`add_entry()`.

- Switch entry lookup to id-based traversal that returns `EntryId`,
  then resolve to `EntryRef`/`EntryMut` via `Database::entry` /
  `entry_mut`, which sidesteps the lifetime issues that come with
  recursive `GroupRef` borrows.
- Rewrite the write path: navigate or create groups segment-by-segment
  via `group_mut`/`add_group`, then either update an existing entry's
  field via `entry_mut` or call `add_entry` on the target group.
- Use the new `set_protected` / `set_unprotected` helpers instead of
  poking the deprecated `fields` map; this preserves the previous
  "Password is protected, everything else is unprotected" behavior.
- Replace the now-removed `Database::new(DatabaseConfig::default())`
  with the zero-arg `Database::new()`.

All 23 KeePass bats tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 17, 2026

Greptile Summary

This PR upgrades keepass from 0.10 to 0.12 and rewrites the KeePass provider to use the new encapsulated API, replacing direct struct field access (group.entries, group.groups) with accessor methods and an EntryId/GroupId indirection layer.

  • The read path splits into walk_group (direct-child group navigation) and find_entry_id_by_title (recursive title search within the navigated group), exactly mirroring the old find_entry logic and preserving lookup semantics.
  • The write path in find_or_create_entry extracts the target group via navigate_or_create_group_path, then searches for an existing entry recursively within that group (same as the old find_entry_by_title_mut behaviour) before either updating or creating; set_protected/set_unprotected replace the former Value::protected/Value::Unprotected construction.
  • Database::new() is now zero-arg per the 0.12 contract, and immutable/mutable borrow splits are handled correctly throughout via owned EntryId/GroupId values.

Confidence Score: 5/5

Safe to merge — the rewrite faithfully reproduces the pre-0.12 lookup and write semantics, and the test suite (unit tests + 23/23 bats) confirms end-to-end behaviour is preserved.

The migration is mechanically straightforward: every changed code path has a clear counterpart in the old implementation, read and write paths are consistent in their recursive-title-search behaviour, and the borrow-splitting strategy (owned IDs eliminating lifetime conflicts) is clean and correct. No logic changes relative to the old provider, no dropped error cases, no new failure modes.

No files require special attention.

Important Files Changed

Filename Overview
crates/fnox-core/src/providers/keepass.rs Full provider rewrite for keepass 0.12: replaces direct struct field access with accessor methods, introduces EntryId/GroupId indirection for lookups, and uses set_protected/set_unprotected for writes. Read and write paths remain behaviourally consistent with the pre-0.12 implementation.
Cargo.toml Bumps keepass dependency from 0.10 to 0.12, preserving the save_kdbx4 feature flag.
Cargo.lock Lock file updated for keepass 0.10.6 → 0.12.9 and the transitive quick-xml 0.39.4 → 0.40.1 bump; checksums look consistent with the Cargo.toml version pin.

Reviews (1): Last reviewed commit: "fix(keepass): migrate provider to keepas..." | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the keepass dependency from version 0.10 to 0.12, which involves a significant refactor of the KeePass provider to accommodate the new ID-based API. The changes replace direct group and entry manipulation with lookups using EntryId and GroupId, and introduce new helper methods for recursive searching and path navigation. A critical issue was identified in the group creation logic where a direct string assignment to a mutable reference field would cause a compilation error, requiring a dereference.

None => {
let mut group_mut = db.group_mut(current_id).expect("current group exists");
let mut new_group = group_mut.add_group();
new_group.name = (*name).to_string();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

In keepass 0.12, GroupMut is a wrapper where the name field is a &mut String. Assigning a String directly to this field will result in a type mismatch compilation error. You need to dereference the field to update the underlying string value.

Suggested change
new_group.name = (*name).to_string();
*new_group.name = (*name).to_string();

@jdx jdx merged commit ca3eb8f into main May 17, 2026
13 checks passed
@jdx jdx deleted the fix/keepass-0.12-migration branch May 17, 2026 17:12
This was referenced May 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant