feat(store): consolidate config + data + identity into encrypted SQLite (VA-68) #74

Merged
David merged 2 commits from feat/VA-68-encrypted-sqlite-store into main 2026-06-27 23:16:30 +02:00
Member

Replace the sled data store and the whole-file .vss settings blob with two SQLCipher (encrypted SQLite) databases, both unlocked by the VERVAIN_DB_KEY environment variable set in the service unit at install time.

  • crates/vervain-agent/src/store.rs: the data Store is now an encrypted SQLite key-value table (rusqlite + bundled-sqlcipher-vendored-openssl). Store::open(path, key) runs PRAGMA key then touches a page, so a missing/wrong key surfaces as an error (unreadable DB). Adds put_enrolled_identity / enrolled_identity (cert + key + server CA) for the enrollment flow (VA-67), and an EnrolledIdentity type.
  • crates/vervain-agent-config: strip the .vss encryption surface. Delete store.rs (InstallSecret + ChaCha20-Poly1305) and drop ring/zeroize/data-encoding; SettingsMap keeps its deterministic serialize/deserialize and the migrate-gated .vagent reader, now used to import a plaintext seed into the encrypted config DB.
  • crates/vervain-agent/src/settings.rs: resolve two XDG dirs via the directories crate (config in ~/.config/vervain-agent, data in ~/.local/share/vervain-agent), read the SQLCipher key from VERVAIN_DB_KEY, persist the SettingsMap as one blob in the encrypted config.db, and bootstrap a fresh DB by importing a co-located vervain-agent.vagent seed. No migration from the old stores.
  • main.rs: drop --secret-file; thread the DB key into the config + data stores; config seal becomes config import.
  • install.rs / install_windows.rs: generate a fresh 256-bit hex VERVAIN_DB_KEY at install, import the seed into config.db, and inject the key via the systemd unit Environment= (Linux) or machine env via setx /M (Windows). Uninstall removes the encrypted DB files.
  • Docs/README/ROADMAP/justfile/compose/.gitignore updated for the SQLite model; the wrong-key-yields-unreadable-DB / re-enroll behaviour is documented in docs/local-settings-store.md.

Verified green in the dev container: fmt, clippy --workspace --all-targets --deny warnings, build, test --lib, and the x86_64-pc-windows-gnu cross-check (bundled SQLCipher + vendored OpenSSL cross-compiles via MinGW).

#VA-68

Replace the sled data store and the whole-file `.vss` settings blob with two SQLCipher (encrypted SQLite) databases, both unlocked by the `VERVAIN_DB_KEY` environment variable set in the service unit at install time. - `crates/vervain-agent/src/store.rs`: the data `Store` is now an encrypted SQLite key-value table (rusqlite + bundled-sqlcipher-vendored-openssl). `Store::open(path, key)` runs `PRAGMA key` then touches a page, so a missing/wrong key surfaces as an error (unreadable DB). Adds `put_enrolled_identity` / `enrolled_identity` (cert + key + server CA) for the enrollment flow (VA-67), and an `EnrolledIdentity` type. - `crates/vervain-agent-config`: strip the `.vss` encryption surface. Delete `store.rs` (InstallSecret + ChaCha20-Poly1305) and drop ring/zeroize/data-encoding; `SettingsMap` keeps its deterministic serialize/deserialize and the `migrate`-gated `.vagent` reader, now used to import a plaintext seed into the encrypted config DB. - `crates/vervain-agent/src/settings.rs`: resolve two XDG dirs via the `directories` crate (config in `~/.config/vervain-agent`, data in `~/.local/share/vervain-agent`), read the SQLCipher key from `VERVAIN_DB_KEY`, persist the `SettingsMap` as one blob in the encrypted `config.db`, and bootstrap a fresh DB by importing a co-located `vervain-agent.vagent` seed. No migration from the old stores. - `main.rs`: drop `--secret-file`; thread the DB key into the config + data stores; `config seal` becomes `config import`. - `install.rs` / `install_windows.rs`: generate a fresh 256-bit hex `VERVAIN_DB_KEY` at install, import the seed into `config.db`, and inject the key via the systemd unit `Environment=` (Linux) or machine env via `setx /M` (Windows). Uninstall removes the encrypted DB files. - Docs/README/ROADMAP/justfile/compose/.gitignore updated for the SQLite model; the wrong-key-yields-unreadable-DB / re-enroll behaviour is documented in `docs/local-settings-store.md`. Verified green in the dev container: fmt, clippy --workspace --all-targets --deny warnings, build, test --lib, and the x86_64-pc-windows-gnu cross-check (bundled SQLCipher + vendored OpenSSL cross-compiles via MinGW). #VA-68
feat(store): consolidate config + data + identity into encrypted SQLite (VA-68)
All checks were successful
Check / fmt + clippy + tests (pull_request) Successful in 3m48s
32f1c19331
Replace the sled data store and the whole-file `.vss` settings blob with two SQLCipher (encrypted SQLite) databases, both unlocked by the `VERVAIN_DB_KEY` environment variable set in the service unit at install time.

- `crates/vervain-agent/src/store.rs`: the data `Store` is now an encrypted SQLite key-value table (rusqlite + bundled-sqlcipher-vendored-openssl). `Store::open(path, key)` runs `PRAGMA key` then touches a page, so a missing/wrong key surfaces as an error (unreadable DB). Adds `put_enrolled_identity` / `enrolled_identity` (cert + key + server CA) for the enrollment flow (VA-67), and an `EnrolledIdentity` type.
- `crates/vervain-agent-config`: strip the `.vss` encryption surface. Delete `store.rs` (InstallSecret + ChaCha20-Poly1305) and drop ring/zeroize/data-encoding; `SettingsMap` keeps its deterministic serialize/deserialize and the `migrate`-gated `.vagent` reader, now used to import a plaintext seed into the encrypted config DB.
- `crates/vervain-agent/src/settings.rs`: resolve two XDG dirs via the `directories` crate (config in `~/.config/vervain-agent`, data in `~/.local/share/vervain-agent`), read the SQLCipher key from `VERVAIN_DB_KEY`, persist the `SettingsMap` as one blob in the encrypted `config.db`, and bootstrap a fresh DB by importing a co-located `vervain-agent.vagent` seed. No migration from the old stores.
- `main.rs`: drop `--secret-file`; thread the DB key into the config + data stores; `config seal` becomes `config import`.
- `install.rs` / `install_windows.rs`: generate a fresh 256-bit hex `VERVAIN_DB_KEY` at install, import the seed into `config.db`, and inject the key via the systemd unit `Environment=` (Linux) or machine env via `setx /M` (Windows). Uninstall removes the encrypted DB files.
- Docs/README/ROADMAP/justfile/compose/.gitignore updated for the SQLite model; the wrong-key-yields-unreadable-DB / re-enroll behaviour is documented in `docs/local-settings-store.md`.

Verified green in the dev container: fmt, clippy --workspace --all-targets --deny warnings, build, test --lib, and the x86_64-pc-windows-gnu cross-check (bundled SQLCipher + vendored OpenSSL cross-compiles via MinGW).

#VA-68
test(netprobe): use reserved address for unreachable-port probe (VA-69)
All checks were successful
Check / fmt + clippy + tests (pull_request) Successful in 5m4s
Create release / Create release from merged PR (pull_request) Has been skipped
e89e652686
The `probe_to_closed_port_returns_io_error` test bound an ephemeral loopback port, closed it, then asserted that probing it returned `ProbeError::Io`. This was non-deterministic two ways: under the parallel test runner another test could rebind the freed port before the connect (so probe returned `Ok`), and in the CI Docker build's restricted network namespace the SYN to a closed port is silently dropped rather than refused, so the connect timed out (`ProbeError::Timeout`) instead of being refused. The latter is what failed check.yml run #270.

Probe a reserved, non-routable address instead (RFC 5737 TEST-NET-1, 192.0.2.1): nothing can answer, there is no port to reuse, and the connect always fails as either `Io` (network unreachable) or `Timeout` (SYN dropped). Accept both variants and rename the test to `probe_to_unreachable_address_fails_to_connect`. The success path stays covered by `connects_to_local_listener`.

#VA-69
David merged commit 776d46a384 into main 2026-06-27 23:16:30 +02:00
David deleted branch feat/VA-68-encrypted-sqlite-store 2026-06-27 23:16:30 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/vervain-agent!74
No description provided.