Skip to content

chore: upstream opt-out build tag to ByteNess/keyring for the 1Password backends #57

Description

@rianjs

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:

  1. 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).
  2. Adds a CI smoke leg: go build -tags keyring_no1password ./... + go vet, so the gated variant can't rot.
  3. 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

  • Repin byteness/keyring in cli-common
  • Add the tag to cli-common's CI build/test invocations
  • Add the tag to each consumer CLI's Makefile, ci.yml, and .goreleaser flags: (rides the next repin train; update the §1.10 note in working-with-secrets.md to reflect the tag as the standard build configuration)

Refs: #55 (quantification + interim documentation), #54 (standards review that surfaced this).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions