Commitment
Submit an upstream PR to ByteNess/keyring adding an opt-out build tag that excludes the 1Password backends at compile time. Decided 2026-06-11 during #55 execution; #55 documents the trade-off in working-with-secrets.md §1.10 in the meantime. We have read-only access to the upstream repo, so this is a fork-and-PR; ByteNess has historically been responsive.
Why
The keyring root package imports its 1Password openers unconditionally, so credstore → byteness/keyring → onepassword-sdk-go (pre-1.0) → extism/go-sdk → wazero (plus connect-sdk-go → jaeger-client-go, archived upstream) compiles into every consumer binary. Measured on slck (2026-06-11, keyring v1.9.3):
- 63 packages from these trees in
go list -deps ./credstore
- 5,393 surviving symbols in the shipped binary — no dead-code elimination (init-registered openers)
- ~10.6 MB of attributable symbol bytes (
go tool nm -size)
This is a credential library carrying a WASM runtime and a beta SDK on every consumer's security-audit surface, for backends our standard already declines to expose (working-with-secrets.md §1.10).
PR design (validated against v1.9.3 source)
The library uses a self-registration pattern: each backend file's init() adds itself to supportedBackends (keyring.go:54). The five op files (opcommon.go, opstandard.go, opconnect.go, opdesktop.go, opsrvaccount.go) are the only importers of the 1Password SDKs and already carry //go:build !freebsd. The PR:
- Changes those files' constraint (plus
_test.go siblings) to //go:build !freebsd && !keyring_no1password (final tag name at upstream's discretion — but it must be opt-out polarity so default builds are byte-for-byte unchanged).
- Adds a CI smoke leg:
go build -tags keyring_no1password ./... + go vet, so the gated variant can't rot.
- README note documenting the tag.
Behavior under the tag: the op init()s never run, supportedBackends never gets the op entries, and requesting an op backend hits the existing "unsupported backend" error path — same as wincred-on-Linux today. The OPBackend constants and Config.OP* fields live in ungated files with no SDK imports, so there is no API change.
Generalization (optional, raise in the PR discussion)
Surveyed v1.9.3: the op trio is the only heavy tree. pass/passage shell out (stdlib only); kwallet/secret-service share the small dbus lib; wincred/keyctl are trivial. So a single keyring_no1password tag captures ~all the win today. If upstream prefers generality, a per-backend tag family (keyring_no<backend>) is the natural shape — worth offering as an alternative in the PR description, not worth building unprompted.
Known limits
- The tag removes compiled surface (binary size,
govulncheck-reachable findings). The modules stay in the module graph / go.sum, so module-level dependabot alerts can still fire; only an upstream repo/module split would remove those.
After upstream merges
Refs: #55 (quantification + interim documentation), #54 (standards review that surfaced this).
Commitment
Submit an upstream PR to
ByteNess/keyringadding an opt-out build tag that excludes the 1Password backends at compile time. Decided 2026-06-11 during #55 execution; #55 documents the trade-off inworking-with-secrets.md§1.10 in the meantime. We have read-only access to the upstream repo, so this is a fork-and-PR; ByteNess has historically been responsive.Why
The keyring root package imports its 1Password openers unconditionally, so
credstore → byteness/keyring → onepassword-sdk-go (pre-1.0) → extism/go-sdk → wazero(plusconnect-sdk-go → jaeger-client-go, archived upstream) compiles into every consumer binary. Measured onslck(2026-06-11, keyring v1.9.3):go list -deps ./credstorego tool nm -size)This is a credential library carrying a WASM runtime and a beta SDK on every consumer's security-audit surface, for backends our standard already declines to expose (
working-with-secrets.md§1.10).PR design (validated against v1.9.3 source)
The library uses a self-registration pattern: each backend file's
init()adds itself tosupportedBackends(keyring.go:54). The five op files (opcommon.go,opstandard.go,opconnect.go,opdesktop.go,opsrvaccount.go) are the only importers of the 1Password SDKs and already carry//go:build !freebsd. The PR:_test.gosiblings) to//go:build !freebsd && !keyring_no1password(final tag name at upstream's discretion — but it must be opt-out polarity so default builds are byte-for-byte unchanged).go build -tags keyring_no1password ./...+go vet, so the gated variant can't rot.Behavior under the tag: the op
init()s never run,supportedBackendsnever gets the op entries, and requesting an op backend hits the existing "unsupported backend" error path — same as wincred-on-Linux today. TheOPBackendconstants andConfig.OP*fields live in ungated files with no SDK imports, so there is no API change.Generalization (optional, raise in the PR discussion)
Surveyed v1.9.3: the op trio is the only heavy tree.
pass/passageshell out (stdlib only);kwallet/secret-serviceshare the small dbus lib;wincred/keyctlare trivial. So a singlekeyring_no1passwordtag captures ~all the win today. If upstream prefers generality, a per-backend tag family (keyring_no<backend>) is the natural shape — worth offering as an alternative in the PR description, not worth building unprompted.Known limits
govulncheck-reachable findings). The modules stay in the module graph /go.sum, so module-level dependabot alerts can still fire; only an upstream repo/module split would remove those.After upstream merges
byteness/keyringin cli-common.goreleaserflags:(rides the next repin train; update the §1.10 note inworking-with-secrets.mdto reflect the tag as the standard build configuration)Refs: #55 (quantification + interim documentation), #54 (standards review that surfaced this).