feat(vault): vault register + vault login (account profile)#7
Merged
Conversation
Add the last two PRD §7.1 verbs as an account-profile flow (not the
Bitwarden personal API-key model, which stays a tracked follow-up).
register: records the account — server, lower-cased email, and a freshly
minted stable device_id — into a new [account] table in config.toml. No
agent or network; a light http(s):// check is the only validation, with
real errors surfacing at first login. Re-registering preserves the
existing device_id.
login: authenticates against the registered account (master password →
Request::Unlock) and ends on a status-backed sync summary ("logged in as
<email> · <n> items · synced <ts>", or --json). Auto-spawns the agent, so
a cold `vault login` brings everything up.
unlock: now resolves server/email from the profile too, so its flags
(and $VAULT_SERVER/$VAULT_EMAIL) are optional once registered. Precedence
is explicit flag/env → profile → error. login and unlock share one
Request::Unlock; the difference is resolution and login's verbose,
status-backed success.
Stable device id: Request::Unlock gains a serde-defaulted
device_id: Option<String>; the agent uses it as the Bitwarden
deviceIdentifier instead of minting a fresh UUID each unlock, so the
account stops accumulating a new device per session. Old Unlock frames
without the field still decode (regression-tested).
CLI-only beyond that one optional IPC field: no vault-api surface, no
agent auth split. New uuid dep on vault-cli (already in the workspace).
Tests: [account] round-trip + no-empty-table-until-set + device-id
mint/preserve + email lower-casing; resolve_account precedence
(flag → profile → error); Unlock device-id round-trip and
old-frame-decode regression. Verified live: register (lower-case +
mint), --json, non-http rejection, no-profile login error, and flag-less
unlock resolving from the profile.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A newer stable clippy than the local one flagged three lints in the register/login code: a missing-backticks doc item (`device_id`) and two `format!` appended to a String via push_str. Backtick the doc term and switch print_login_summary to write! (fmt::Write). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the last two PRD §7.1 verbs —
registerandlogin— as an account-profile flow (the Bitwarden personal API-key model stays a tracked follow-up, per the scoping decision). Beyond one optional IPC field this is CLI-only: no newvault-apisurface, no agent auth split.registerRecords the account — server, lower-cased email, and a freshly minted stable
device_id— into a new[account]table inconfig.toml. No agent or network; a lighthttp(s)://check is the only validation (real errors surface at firstlogin). Re-registering preserves the existingdevice_id.loginAuthenticates against the registered account (master password →
Request::Unlock) and ends on a status-backed sync summary (logged in as <email> · <n> items · synced <ts>, or--json). Auto-spawns the agent, so a coldvault loginbrings everything up.unlockNow resolves
server/emailfrom the profile too, so its flags (and$VAULT_SERVER/$VAULT_EMAIL) are optional once registered. Precedence: explicit flag/env → profile → error.loginandunlockshare oneRequest::Unlock— the difference is resolution andlogin's verbose, status-backed success.Stable device id
Request::Unlockgains a serde-defaulteddevice_id: Option<String>; the agent uses it as the BitwardendeviceIdentifierinstead of minting a fresh UUID each unlock, so the account stops accumulating a new device per session. OldUnlockframes without the field still decode (regression-tested).Tests
[account]round-trip + "no empty table until set" + device-id mint/preserve + email lower-casing;resolve_accountprecedence (flag → profile → error); theUnlockdevice-id round-trip and old-frame-decode regression. Workspace: 126 tests green,clippy -D warningsclean,cargo denyclean, headless build green. Verified live: register (lower-case + mint +--json), non-http rejection, no-profileloginerror (exit 2), and flag-lessunlockresolving from the profile.New dependency
uuidonvault-cli(device_id mint) — already in the workspace tree.🤖 Generated with Claude Code