feat(cli): bare homelab vault help command

This commit is contained in:
Viktor Barzin 2026-06-24 10:29:32 +00:00
parent 772aed5370
commit 15643d1f44
2 changed files with 39 additions and 0 deletions

View file

@ -32,9 +32,30 @@ func vaultCommands() []Command {
Summary: "current TOTP code for an item: vault code <name>", Run: vaultCode}, Summary: "current TOTP code for an item: vault code <name>", Run: vaultCode},
{Path: []string{"vault", "lock"}, Tier: TierWrite, {Path: []string{"vault", "lock"}, Tier: TierWrite,
Summary: "lock/log out the local bw session", Run: vaultLock}, Summary: "lock/log out the local bw session", Run: vaultLock},
{Path: []string{"vault"}, Tier: TierRead,
Summary: "Vaultwarden access for your own vault (run `homelab vault` for help)",
Run: func([]string) error { fmt.Print(vaultHelp()); return nil }},
} }
} }
// vaultHelp is shown for bare `homelab vault`.
func vaultHelp() string {
return `homelab vault read YOUR OWN Vaultwarden logins (no-HITL after one-time setup)
homelab vault setup one-time: store your master password + API key in your Vault path
homelab vault status configured / unlocked / reachable (no secrets)
homelab vault list [--search Q] list your item names (no secrets)
homelab vault get <name> [--field password|username|uri|notes|totp] [--json]
TTY clipboard (auto-clears); piped stdout
homelab vault code <name> current TOTP code
homelab vault lock lock / log out the local bw session
Creds live only in your own Vault path; the admin never sees them. Identity is
your unix UID. Security model: docs/superpowers/specs/2026-06-24-homelab-vault-design.md
(note: anything running as your user can decrypt your vault the accepted no-HITL trade).
`
}
const vwUserPathPrefix = "secret/workstation/claude-users/" const vwUserPathPrefix = "secret/workstation/claude-users/"
// vwCreds is one user's Vaultwarden auth material, read from their Vault path. // vwCreds is one user's Vaultwarden auth material, read from their Vault path.

View file

@ -331,6 +331,24 @@ func TestBwNeedsLogin(t *testing.T) {
} }
} }
func TestVaultHelpMentionsSecurity(t *testing.T) {
h := vaultHelp()
for _, want := range []string{"homelab vault get", "no-HITL", "your own", "setup"} {
if !strings.Contains(h, want) {
t.Errorf("vault help missing %q", want)
}
}
}
func TestVaultBareGroupRegistered(t *testing.T) {
for _, c := range vaultCommands() {
if len(c.Path) == 1 && c.Path[0] == "vault" {
return
}
}
t.Fatal("bare `vault` help command not registered")
}
// getValue is the testable core: given a runner + opts, returns the secret value. // getValue is the testable core: given a runner + opts, returns the secret value.
func TestGetValueFlow(t *testing.T) { func TestGetValueFlow(t *testing.T) {
f := &fakeRunner{out: map[string]string{ f := &fakeRunner{out: map[string]string{