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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions