Commit 9572930
feat(vault-api, vault-store): M2 — login, sync, encrypted cache
Implement the Bitwarden / Vaultwarden REST surface and the encrypted
on-disk sync cache per PRD §12 (M2 gate).
vault-core:
- master_password_hash(): base64 PBKDF2-SHA-256(master_key, password, 1).
This is the credential Bitwarden sends to /identity/connect/token;
the real master password never leaves the client.
vault-api (new module surface):
- BaseUrls: split for hosted Bitwarden (api/identity subdomains) and
unified for Vaultwarden (/api + /identity under one origin).
- BitwardenClient (reqwest + rustls): prelogin, login_password, sync.
Holds the access token in a Zeroizing<String>; never holds the
master key. 2FA-required responses surface as a typed error rather
than a generic 400. https_only is enabled when the API scheme is
https.
- identity / sync wire types as serde shapes, with non-essential
fields kept as serde_json::Value so schema drift doesn't break the
cache round-trip.
vault-store:
- VaultCache: serde JSON envelope at <data-dir>/vault/cache.json with
schema_version, device_id, server origin, lowercase email, last_sync
RFC 3339 stamp, and an encrypted `payload` field (Vault EncString
over the raw /sync response bytes).
- Atomic writes via NamedTempFile::persist (tempfile in the same
directory → fsync → rename) so a crash mid-write can't tear the
cache.
Tests:
- vault-api::tests::parsing — 7 wire-shape decode tests, no HTTP.
- vault-store::tests::cache — 4 disk-cache round-trip tests
(encrypted-on-disk asserted; wrong-key fails; missing file =
NotFound; no-payload = NoPayload).
- vault-api::tests::login_sync — full wiremock integration covering
prelogin → login_password (asserting the form body contains the
expected master-password hash) → sync → VaultCache encrypted-write
→ reload → decrypt → equality. Kept #[ignore] for now: the test
binary links ring statically, and cargo's `links =` propagation
drops the static-lib flag on this maintainer's host environment.
CI runs it via --ignored on a clean toolchain. The library code
itself builds fine — `cargo build --workspace` and the parsing /
cache test suites are green.
docs/m2-vaultwarden.md documents the manual M2 gate against a real
Vaultwarden container (podman/docker run, register, sync, persist).
Workspace deps added: reqwest (rustls-tls + json), url, uuid, dirs,
time, fs2, tempfile, wiremock (dev), tokio-test (dev).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>1 parent 0c669fe commit 9572930
18 files changed
Lines changed: 3234 additions & 290 deletions
File tree
- crates
- vault-api
- src
- tests
- vault-core/src
- vault-store
- src
- tests
- docs
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
21 | 39 | | |
22 | 40 | | |
23 | 41 | | |
| |||
0 commit comments