Skip to content

feat(auth): durable vault-unlock secret to stop repeated password prompts (Phase 1)#187

Merged
LiranCohen merged 2 commits into
fix/install-wrapper-symlink-clobberfrom
feat/auth-session-core
Jun 24, 2026
Merged

feat(auth): durable vault-unlock secret to stop repeated password prompts (Phase 1)#187
LiranCohen merged 2 commits into
fix/install-wrapper-symlink-clobberfrom
feat/auth-session-core

Conversation

@LiranCohen

Copy link
Copy Markdown
Contributor

Phase 1 of the auth/session/server redesign (#186). Stacked on #185 (fix/install-wrapper-symlink-clobber), which contains the session/helper subsystem being reworked.

What & why

gitd asked for the vault password on essentially every command because each one unlocked its own agent via an ad-hoc getPassword() (env → TTY prompt) with no durable cache. This PR introduces a single resolution path and a durable per-profile secret store, so after the first unlock the session is restored without re-prompting — the first concrete fix for "asked for the vault password repeatedly" and a session that survives across separate processes.

Changes

  • src/auth/secret-store.ts — durable per-profile secret store: OS keychain (macOS security, Linux secret-tool) when available, otherwise a machine-keyed AES-256-GCM encrypted file under ~/.enbox/secrets/ (mode 0600). GITD_SECRET_BACKEND=keychain|file|none pins/disables the backend.
  • src/auth/vault-password.ts — one resolution path: explicit → GITD_PASSWORD → hidden public-reader secret → durable store → interactive prompt (TTY raw / piped), tracking the source. rememberVaultSecret caches only freshly entered (tty/explicit) secrets — never env. forgetVaultSecret clears them.
  • src/cli/main.ts — both connect sites resolve via the new path and cache on a verified unlock; a rejected cached secret is cleared automatically so a stale secret can't lock you out. (Removes the old inline getPassword.)
  • src/cli/commands/auth.tsauth login caches the new secret; auth logout / auth reset drop it.
  • src/cli/identity-wizard.ts — first-run wizard caches the secret too.

Behavior / compatibility

  • GITD_PASSWORD still wins for CI/non-interactive use and is not persisted.
  • The public-reader (no-identity) path is unchanged.
  • No daemon, credential-helper, or wallet changes in this PR (later phases).

Verification

  • bun run build — clean (zero TS errors)
  • bun run lint — clean (--max-warnings 0)
  • bun test .spec.ts1802 pass, 8 skip, 0 fail (incl. 17 new tests in tests/secret-store.spec.ts and tests/vault-password.spec.ts covering round-trip, encryption-at-rest, resolution precedence, cache-only-fresh-secrets, and forget)

🤖 Generated with Claude Code

LiranCohen and others added 2 commits June 24, 2026 02:31
…mpts

Resolve the vault password through one path (explicit -> GITD_PASSWORD ->
public-reader -> durable secret store -> prompt) and persist a freshly entered
secret per profile in a durable store: the OS keychain (macOS security, Linux
secret-tool) when available, otherwise a machine-keyed AES-256-GCM encrypted
file under ~/.enbox/secrets/. After the first unlock, commands restore the
session without re-prompting for the vault password.

GITD_SECRET_BACKEND=keychain|file|none pins or disables the backend. A cached
secret that is later rejected is cleared automatically to avoid lock-out;
gitd auth logout / reset drop the stored secret.

Part of #186 (Phase 1).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@LiranCohen
LiranCohen merged commit 2981f47 into fix/install-wrapper-symlink-clobber Jun 24, 2026
@LiranCohen
LiranCohen deleted the feat/auth-session-core branch June 24, 2026 02:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant