pwstore: generic csvManager for 8 password-manager CSV adapters

One data-driven csvManager (layout = header + record func) covers
edge/brave (chrome layout), safari, lastpass, dashlane, protonpass,
nordpass, roboform, and read/guide-only enpass — replacing 8 near-identical
files. Export is header-name driven (parseLoginCSV + new aliases); import
stages a per-manager-layout CSV on tmpfs and shreds it, gated by --allow-csv.
Notes now round-trip through Meta. Reimporter exposes per-manager re-import
hints. Column layouts are MOCK-ONLY (unit-validated) on the same LIVE-VM
staging machinery; recorded as DATA in BROWSER-ROTATION.md §8.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
leetcrypt
2026-06-20 11:31:28 -07:00
parent 6bd6aefbe8
commit 4f5939a3e3
6 changed files with 467 additions and 21 deletions
+28 -6
View File
@@ -5,10 +5,12 @@ non-technical user has reused across dozens of sites and saved in a browser or p
manager. It extends the same safe spine as the developer-credential drivers (discover →
custody → **mandatory backup** → rotate/verify/commit → guide) — it is *not* a new product.
Status: **Phase B (propagation engine) — built.** `pwgen` + `pwstore` (all five adapters) +
the sealed staged-list + the `incredigo passwords scan|plan|guide|commit` surface are
implemented and tested (bitwarden + keepassxc + chrome/firefox staging are LIVE-VM proven;
only 1password is still MOCK-ONLY — see §8). Phases
Status: **Phase B (propagation engine) — built.** `pwgen` + `pwstore` (CLI adapters +
the generic `csvManager` covering chrome/firefox/edge/brave/safari/lastpass/dashlane/
protonpass/nordpass/roboform/enpass) + the sealed staged-list + the
`incredigo passwords scan|plan|guide|commit` surface are implemented and tested
(bitwarden + keepassxc + chrome/firefox staging are LIVE-VM proven; 1password and the
CSV-manager column layouts are MOCK-ONLY — see §8). Phases
A-tier-1 / A-tier-2 (site automation) are specified here but **not yet built**. Nothing in this
doc changes a password **at a website** automatically — the human still performs the site
change + MFA; incredigo only propagates the new value into the *manager* afterward.
@@ -183,8 +185,11 @@ incredigo passwords guide # interactive (TTY): per account → link + reveal
incredigo passwords commit # headless: open sealed --stage-in, re-verify backup, commit --verified <1,2,…|all>
```
Shared flags: `--manager bitwarden|1password|keepassxc|chrome|firefox` selects the backend;
`--export-path <csv>` feeds chrome/firefox; `--kdbx <db>` feeds keepassxc (passphrase from
Shared flags: `--manager` selects the backend — in-place CLI managers
`bitwarden|1password|keepassxc`, or CSV import/export stores
`chrome|firefox|edge|brave|safari|lastpass|dashlane|protonpass|nordpass|roboform|enpass`
(all share one generic `csvManager`, differing only by import column layout);
`--export-path <csv>` feeds every CSV manager; `--kdbx <db>` feeds keepassxc (passphrase from
`$INCREDIGO_KDBX_PASSPHRASE` or a no-echo prompt); `--allow-csv` is the loud opt-in required
for the browser-CSV plaintext path; `--length/--exclude-ambiguous/--symbols` tune the generator;
`$INCREDIGO_PASSPHRASE` enables the headless (no-TTY) backup/seal flows.
@@ -230,6 +235,15 @@ via real registration crypto). **keepassxc is LIVE-VM** — proven end to end ag
`lab-provision-browsercsv.sh`; only the final human re-import is unproven (see note ²). All in
the `incredigo-sbx` sandbox VM.
The **CSV-manager family** (edge/brave/safari/lastpass/dashlane/protonpass/nordpass/roboform/
enpass) shares the chrome/firefox staging machinery via one generic `csvManager`, so its
security-critical path (tmpfs + correct per-manager import layout + shred, `--allow-csv` gated)
is the *same proven code*; what is **MOCK-ONLY** for each is the per-manager column mapping,
validated by unit tests (`csvmanagers_test.go`) against representative real-world export/import
headers — there is no LIVE-VM round-trip into the actual managers yet. `enpass` imports via JSON
(not CSV) so it is **read/guide-only**: it parses an export for the worklist but refuses
`ImportStaged`, pointing the human at `incredigo passwords guide`.
| Adapter | Write shape | Secret path off-argv? | Validated against |
|-----------|------------------------|-----------------------|-------------------|
| bitwarden | `bw edit item` (stdin) | **yes** — base64 on stdin | **real bw 2026.5.0 + Vaultwarden 1.36 (LIVE-VM)** |
@@ -237,6 +251,14 @@ the `incredigo-sbx` sandbox VM.
| 1password | `op item edit pw=…` | **no** — argv assignment¹ | fake `op` (MOCK-ONLY) |
| chrome | tmpfs CSV → human re-import | n/a (no live secret to a child) | **real /dev/shm + shred (LIVE-VM²)** |
| firefox | tmpfs CSV → human re-import | n/a | **real /dev/shm + shred (LIVE-VM²)** |
| edge / brave | tmpfs CSV (chrome layout) → re-import | n/a | shared staging code (LIVE-VM²); layout MOCK-ONLY (unit) |
| safari | tmpfs CSV (macOS Passwords layout) → re-import | n/a | shared staging code (LIVE-VM²); layout MOCK-ONLY (unit) |
| lastpass | tmpfs CSV (Generic CSV layout) → re-import | n/a | shared staging code (LIVE-VM²); layout MOCK-ONLY (unit) |
| dashlane | tmpfs CSV (Dashlane layout) → re-import | n/a | shared staging code (LIVE-VM²); layout MOCK-ONLY (unit) |
| protonpass| tmpfs CSV (Proton layout) → re-import | n/a | shared staging code (LIVE-VM²); layout MOCK-ONLY (unit) |
| nordpass | tmpfs CSV (NordPass layout) → re-import | n/a | shared staging code (LIVE-VM²); layout MOCK-ONLY (unit) |
| roboform | tmpfs CSV (RoboForm layout) → re-import | n/a | shared staging code (LIVE-VM²); layout MOCK-ONLY (unit) |
| enpass | read/guide-only (JSON import, no CSV) | n/a | export parse only (unit); `ImportStaged` refuses |
² **chrome/firefox LIVE-VM scope:** there is no real browser to re-import into, so what is
proven LIVE-VM (`lab-provision-browsercsv.sh` + `csv-commit-probe.py`) is the security-critical