Files
nexus/internal/secrets/keychain.go
T
Andy DixonandClaude Sonnet 5 1a380a0e99 Rebrand: Nexus Terminal → Alchementary Link
Renames the product across the codebase: Go module path, config/data
paths, keychain service name, export file extension, build tooling,
docs, and UI text. Sidebar brand mark now reads ">_ AlchementaryLink"
with "Alchementary" in the connection-group gold accent colour, and
the window title is "Alchementary Link".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019T8bJS8BCtY5GeSG2HBj1n
2026-09-03 16:41:23 +01:00

67 lines
2.2 KiB
Go

package secrets
import (
"fmt"
"github.com/zalando/go-keyring"
)
// KeychainStore attempts to use the OS keychain for secret storage.
// On macOS this uses the Keychain, on Linux it uses the Secret Service API,
// and on Windows it uses the Credential Manager.
//
// This is the preferred storage method when available. Falls back to
// the encrypted file-based SecretStore when the keychain is not accessible.
type KeychainStore struct {
serviceName string
}
// NewKeychainStore creates a KeychainStore that stores credentials under the
// given service name in the operating system's native keychain.
func NewKeychainStore(serviceName string) *KeychainStore {
return &KeychainStore{serviceName: serviceName}
}
// Available checks whether the OS keychain is accessible by performing a
// harmless write-then-delete probe. Returns true if the keychain responded
// without error.
func (k *KeychainStore) Available() bool {
// Attempt a round-trip to verify the keychain is usable.
probeKey := "__link_keychain_probe__"
probeVal := "probe"
if err := keyring.Set(k.serviceName, probeKey, probeVal); err != nil {
return false
}
_ = keyring.Delete(k.serviceName, probeKey)
return true
}
// SetSecret stores a secret in the OS keychain under the configured service
// name with the given key.
func (k *KeychainStore) SetSecret(key, value string) error {
if err := keyring.Set(k.serviceName, key, value); err != nil {
return fmt.Errorf("keychain: failed to store secret %q: %w", key, err)
}
return nil
}
// GetSecret retrieves a secret from the OS keychain. Returns an error if the
// key does not exist or the keychain is inaccessible.
func (k *KeychainStore) GetSecret(key string) (string, error) {
val, err := keyring.Get(k.serviceName, key)
if err != nil {
return "", fmt.Errorf("keychain: failed to retrieve secret %q: %w", key, err)
}
return val, nil
}
// DeleteSecret removes a secret from the OS keychain. Returns an error if the
// key does not exist or the keychain is inaccessible.
func (k *KeychainStore) DeleteSecret(key string) error {
if err := keyring.Delete(k.serviceName, key); err != nil {
return fmt.Errorf("keychain: failed to delete secret %q: %w", key, err)
}
return nil
}