keystore

package
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 6, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package keystore resolves the Typesafe API key from a fixed chain of sources, first hit wins, and reports which source won.

Resolution order:

  1. env JEVKIT_API_KEY, then TYPESAFE_API_KEY
  2. env-file <workspace>/.env, parsed (never sourced) for the key line only
  3. command a stored command whose stdout is the key
  4. keychain the OS keychain (service "jevkit", account "TYPESAFE_API_KEY")
  5. file a 0600 plaintext file in the config dir (last resort)

A configured backend that fails does not fall through to a later one, with one exception: an unavailable keychain is skipped silently. Backend selection lives in jev-credentials.json (0600) in the config dir. Keys are never written under the workspace.

Index

Constants

View Source
const (
	// KeychainService and KeychainAccount identify the keychain entry.
	KeychainService = "jevkit"
	KeychainAccount = "TYPESAFE_API_KEY"
)

Variables

View Source
var ErrKeyringNotFound = errors.New("keystore: keychain entry not found")

ErrKeyringNotFound is returned by a Keyring when the entry does not exist. Any other Keyring error means the keychain is unavailable and is skipped.

View Source
var ErrNoKey = errors.New("keystore: no API key configured")

ErrNoKey means no source produced a key.

Functions

func ConfigDir

func ConfigDir(getenv func(string) string) string

ConfigDir returns $JEVKIT_CONFIG_HOME, else $XDG_CONFIG_HOME/jevkit, else the platform default user config dir plus "jevkit".

func ReadKey

func ReadKey(r io.Reader) (string, error)

ReadKey reads a key from r (typically stdin), dropping one trailing newline. Keys are taken from a reader so they never appear in argv or shell history.

Types

type Keyring

type Keyring interface {
	Get(service, account string) (string, error)
	Set(service, account, secret string) error
	Delete(service, account string) error
}

Keyring is the OS keychain surface the store needs.

type OSKeyring

type OSKeyring struct{}

OSKeyring is the Keyring backed by zalando/go-keyring.

func (OSKeyring) Delete

func (OSKeyring) Delete(service, account string) error

Delete implements Keyring.

func (OSKeyring) Get

func (OSKeyring) Get(service, account string) (string, error)

Get implements Keyring.

func (OSKeyring) Set

func (OSKeyring) Set(service, account, secret string) error

Set implements Keyring.

type Source

type Source string

Source names the backend that supplied (or would supply) the key.

const (
	SourceEnv      Source = "env"
	SourceEnvFile  Source = "env-file"
	SourceCommand  Source = "command"
	SourceKeychain Source = "keychain"
	SourceFile     Source = "file"
	SourceNone     Source = "none"
)

Sources, in resolution order.

type Store

type Store struct {
	// Getenv reads the environment; defaults to os.Getenv.
	Getenv func(string) string
	// Workspace is the workspace root whose .env is consulted.
	Workspace string
	// ConfigDir holds jev-credentials.json and the plaintext key file.
	ConfigDir string
	// Keyring is the keychain backend; defaults to OSKeyring.
	Keyring Keyring
	// Timeout bounds the stored command; JEVKIT_KEY_TIMEOUT_MS overrides the
	// 4s default when Timeout is zero.
	Timeout time.Duration
	// Warn receives the plaintext-storage warning; defaults to os.Stderr.
	Warn io.Writer
}

Store resolves and stores the API key. The zero value is not usable; use New.

func New

func New(workspace string) *Store

New returns a Store for the given workspace root using the process environment, the default config dir and the OS keychain.

func (*Store) Clear

func (s *Store) Clear() error

Clear removes every stored backend: keychain entry, key file and selection.

func (*Store) EnvFilePath

func (s *Store) EnvFilePath() string

EnvFilePath is the workspace dotenv path consulted by the env-file source.

func (*Store) Resolve

func (s *Store) Resolve(ctx context.Context) (string, Source, error)

Resolve returns the key and the source that supplied it. When a configured backend fails, the source is still reported alongside the error so callers can say which backend to fix; with nothing configured the error is ErrNoKey.

func (*Store) SetCommand

func (s *Store) SetCommand(command string) error

SetCommand stores a command whose stdout is the key. No secret is stored.

func (*Store) SetFile

func (s *Store) SetFile(key string) error

SetFile stores key in a 0600 plaintext file and selects that backend, warning that the key is stored in plaintext.

func (*Store) SetKeychain

func (s *Store) SetKeychain(key string) error

SetKeychain stores key in the OS keychain and selects that backend.

func (*Store) Source

func (s *Store) Source(ctx context.Context) Source

Source reports which backend would supply the key without running the stored command. The key is never returned.

func (*Store) Status

func (s *Store) Status(ctx context.Context) string

Status describes where the key comes from. It never includes the key.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL