secrets

package
v0.3.4 Latest Latest
Warning

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

Go to latest
Published: Aug 19, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package secrets dispatches provider API-key lookups across pluggable backends.

Keyget is invoked from Claude Code's apiKeyHelper, so it must keep the key bytes off of disk, environment, and logs: the caller (cc-fleet keyget command) writes the result to stdout exactly once and exits. Nothing in this package may log the key bytes themselves. (Round-robin rotation persists a small monotonic counter to <provider>.rotation — that integer is NOT a key, so keeping it on disk does not weaken this contract.)

Index

Constants

This section is empty.

Variables

View Source
var ErrNoEnabledKey = errors.New("no enabled API key")

ErrNoEnabledKey is returned by the file backend when a provider has no enabled API key to hand out (empty key set, or every entry disabled). keyget surfaces it without writing any key bytes.

Functions

func IsMultiKey

func IsMultiKey(provider string) (bool, error)

IsMultiKey reports whether provider is in multi-key mode (a <provider>.keys.json exists). Used to guard the CLI `edit --api-key` path, which only manages the legacy single key.

func Keyget

func Keyget(provider string) ([]byte, error)

Keyget resolves the API key for provider by looking up its providers.toml entry and delegating to the configured secret backend.

The returned bytes have trailing CR/LF stripped so the caller can write them to stdout verbatim. The key is never logged.

func MaskKey

func MaskKey(key string) string

MaskKey renders a key for display so the full secret never reaches the screen or a log. Keys of length >= 8 show the first and last 3 runes (e.g. "sk-…238"); shorter keys (including empty) are fully obscured by bullets (at least 3) so neither the middle nor any prefix/suffix leaks.

func RemoveKeySet

func RemoveKeySet(provider string) error

RemoveKeySet best-effort deletes a provider's multi-key store and rotation counter (<provider>.keys.json + <provider>.rotation). A missing file is not an error — this is idempotent cleanup invoked from userops.Remove. It returns a non-nil error only on a real removal failure (e.g. permissions).

func SafeRef

func SafeRef(ref string) error

SafeRef rejects a file-backend secret_ref that could escape SecretsDir when joined onto it. A file-backend ref must name a single flat file *inside* the secrets dir, so a path separator, a ".."/"." component, or an absolute path is refused. It is the secret_ref analogue of safeProviderName and is enforced on every file-backend read/write path (userops.writeFileSecret / removeFileSecret / Add / Edit and loadLegacyKeySet below) so a hand-edited providers.toml can never turn a ref like "../../etc/shadow" into a read or write outside the secrets dir.

It applies ONLY to the file backend: pass / 1password / vault / keyring refs legitimately contain "/" (e.g. "secret/data/x", "op://vault/item/field") and are never used to build a SecretsDir path. The error names neither the ref nor any key — the ref is a filename, not a secret, but the message is kept content-free for consistency with the no-leak discipline.

func SaveKeySet

func SaveKeySet(provider string, ks []KeyEntry) error

SaveKeySet atomically writes ks to <provider>.keys.json (0600, secrets dir 0700). Writing here is what migrates a provider from legacy single-key to multi-key mode: the caller seeds ks[0] from LoadKeySet (which returns the legacy key) and appends the new entries before saving.

A nil/empty ks is persisted as "[]" (an explicit empty store), never "null".

Types

type KeyEntry

type KeyEntry struct {
	Label   string `json:"label"`
	Key     string `json:"key"`
	Enabled bool   `json:"enabled"`
}

KeyEntry is one API key inside a provider's multi-key store. The JSON tags are the public on-disk schema: scripts/tests may hand-write keys.json.

Label is a human-readable name shown in the TUI (empty renders as "keyN"); it is NOT a secret. Key is the secret. Enabled gates per-key selection.

func LoadKeySet

func LoadKeySet(provider string) ([]KeyEntry, error)

LoadKeySet resolves a provider's key set by priority:

  1. <provider>.keys.json exists -> parse it (multi-key mode; authoritative).
  2. else the legacy secret_ref file exists -> one enabled entry from it.
  3. else -> empty set (keyget then reports "no enabled API key").

A keys.json that fails to parse is a hard error (we do NOT silently fall back to the legacy file — that could hand out the wrong key). The error wraps ONLY the json error, never the file bytes or any KeyEntry (key-safety).

Jump to

Keyboard shortcuts

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