Skip to content

refactor(client): split the vault and prefs into leaf packages - #60

Merged
naliyi merged 2 commits into
mainfrom
worktree-vault-leaf-package
Sep 23, 2026
Merged

naliyi merged 2 commits into
mainfrom
worktree-vault-leaf-package

Conversation

@naliyi

@naliyi naliyi commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Closes #59.

The vault moves to client/vault and the prefs store to client/prefs, both leaf packages. client re-exports every previous name, so no existing call site changes — all ~149 of them still compile untouched.

Measured result

Module closure a consumer inherits, which is what the issue was actually about:

importing modules packages third-party packages
client (before, and still) 38 365 170
client/vault (new) 10 226 50

28 modules dropped, including rivo/tview, gdamore/tcell, spf13/viper, go.etcd.io/bbolt, spf13/cobra, spf13/afero, pelletier/go-toml, fsnotify, sourcegraph/conc and gorilla/websocket.

go list -deps ./client/vault | grep -cE 'tview|tcell|viper|bbolt|terminfo|afero|mapstructure' → 0.

Three couplings the issue didn't account for

The issue read client/vault.go's import block, which understates what the file actually uses:

  1. AppConfigDir → new leaf appdir. It was already stdlib-only, but Go compiles a package wholesale, so importing cli/common for it dragged viper and zerolog in regardless. cli/common re-exports it, so the CLI is unchanged.
  2. LoadPrefs/SavePrefs/VaultIdentityRef — the vault reads and writes its own keypair reference through prefs. That pulled the whole Prefs type along, since methods must live with their type. TargetsFromPrefs/TargetsFromRelayList stay in client: they return a TargetsSpec, which is what bbolt hangs off.
  3. ResolveRelayURL — prefs needs it to validate relay entries, but it lived in the bbolt-heavy spec.go. It now sits with the relay list it validates; its tests (including the unexported looksLikeRelayHost) moved with it.

Answering the issue's two questions

  • Package name: client/vault as suggested, with de-stuttered members — vault.Exists, vault.Path, vault.Entry, vault.FindEntry, vault.CreateIdentity, vault.Unlock.
  • Aliases: kept permanently, not deprecated. Types are aliases (=) not definitions, so *client.VaultEntry and *vault.Entry are the same type and can be mixed freely.

GenerateIdentity and Identity moved too, as the issue suggested — generating a key and saving it are now reachable together without the streaming stack.

One thing still outstanding, upstream

zerolog remains in the leaf closure via nmilat/utils, which imports it. Nothing ncli can do from this side; worth an upstream issue if the 10 is to become 9.

Verification

  • gofmt, go build ./..., go vet ./..., go mod tidy (no diff), go test -short -race ./..., golangci-lint v2.13.2 → 0 issues.
  • The pre-existing client/vault_test.go was left in package client on purpose: it exercises the vault entirely through the re-exported names, so it now doubles as proof the aliases are transparent.

Importing client for programmatic vault access meant inheriting its whole
closure -- tview/tcell and the terminfo database, viper and zerolog via
cli/common, and bbolt -- to read a YAML file. The cost isn't binary size,
which the linker handles, but the module graph a consumer carries.

The vault now lives in client/vault and the prefs store in client/prefs,
both leaves. A consumer importing them pulls 10 modules instead of 38,
dropping tview, tcell, viper, bbolt, cobra, afero and 22 others.

Three things had to move that the issue didn't account for:

- AppConfigDir, into a new leaf appdir. It was already stdlib-only, but
  Go compiles a package wholesale, so importing cli/common for it dragged
  in viper and zerolog anyway. cli/common re-exports it.
- LoadPrefs/SavePrefs/VaultIdentityRef, which the vault needs to read and
  write its own keypair reference. That pulled the rest of the Prefs type
  with it, since methods live with their type. TargetsFromPrefs and
  TargetsFromRelayList stay behind -- they return a TargetsSpec, which is
  what bbolt hangs off.
- ResolveRelayURL, which prefs needs to validate relay entries. It now
  sits with the relay list it validates, and its tests moved with it.

client re-exports every previous name, permanently: types as aliases, so
a *client.VaultEntry and a *vault.Entry are the same type. No call site
changed -- the existing client/vault_test.go now doubles as a test that
the aliases really are transparent.

zerolog is still in the leaf closure, via nmilat/utils. That one is
upstream's to fix.

Closes #59
@naliyi
naliyi merged commit ea21b7d into main Sep 23, 2026
4 checks passed
@naliyi
naliyi deleted the worktree-vault-leaf-package branch September 23, 2026 15: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.

Split the vault helpers into a leaf package so library consumers don't inherit the TUI + viper stack

1 participant