Documentation
¶
Overview ¶
Package credential resolves API credential values for model_list entries.
An API key is a form of authorization credential. This package centralizes how raw credential strings—plaintext or file references—are resolved into their actual values, keeping that logic out of the config loader.
Supported formats for the api_key field:
- Plaintext: "sk-abc123" → returned as-is
- File ref: "file://filename.key" → content read from configDir/filename.key
- Encrypted: "enc://<base64>" → AES-256-GCM decrypt via PICOCLAW_KEY_PASSPHRASE
- Empty: "" → returned as-is (auth_method=oauth etc.)
Encryption uses AES-256-GCM with HKDF-SHA256 key derivation (< 1ms, safe for embedded Linux). An SSH private key is required for both encryption and decryption. Key derivation:
HKDF-SHA256(ikm=HMAC-SHA256(SHA256(sshKeyBytes), passphrase), salt, info)
SSH key path resolution priority:
- sshKeyPath argument to Encrypt (explicit)
- PICOCLAW_SSH_KEY_PATH env var
- ~/.ssh/picoclaw_ed25519.key (os.UserHomeDir is cross-platform)
Index ¶
Constants ¶
const ( FileScheme = "file://" EncScheme = "enc://" )
const PassphraseEnvVar = "PICOCLAW_KEY_PASSPHRASE"
PassphraseEnvVar is the environment variable that holds the encryption passphrase. Other packages (e.g. config) reference this constant to avoid duplicating the string.
const SSHKeyPathEnvVar = "PICOCLAW_SSH_KEY_PATH"
SSHKeyPathEnvVar is the environment variable that specifies the path to the SSH private key used for enc:// credential encryption and decryption.
Variables ¶
var ErrDecryptionFailed = errors.New("credential: enc:// decryption failed (wrong passphrase or SSH key?)")
ErrDecryptionFailed is returned when an enc:// credential cannot be decrypted, indicating a wrong passphrase or SSH key. Callers can detect this with errors.Is.
var ErrPassphraseRequired = errors.New("credential: enc:// passphrase required")
ErrPassphraseRequired is returned when an enc:// credential is encountered but no passphrase is available from PassphraseProvider. Callers can detect this with errors.Is to distinguish a missing-passphrase condition from other errors.
var PassphraseProvider func() string = func() string { return os.Getenv(PassphraseEnvVar) }
PassphraseProvider is the function used to retrieve the passphrase for enc:// credential decryption. It defaults to reading PICOCLAW_KEY_PASSPHRASE from the process environment. Replace it at startup to use a different source, such as an in-memory SecureStore, so that all LoadConfig() calls everywhere share the same passphrase source without needing os.Environ.
Example (launcher main.go):
credential.PassphraseProvider = apiHandler.passphraseStore.Get
Functions ¶
func DefaultSSHKeyPath ¶
DefaultSSHKeyPath returns the canonical path for the picoclaw-specific SSH key. The path is always ~/.ssh/picoclaw_ed25519.key (os.UserHomeDir is cross-platform).
func Encrypt ¶
Encrypt encrypts plaintext and returns an enc:// credential string.
passphrase is required (PICOCLAW_KEY_PASSPHRASE value). sshKeyPath is the SSH private key file to use; pass "" to auto-detect via PICOCLAW_SSH_KEY_PATH env var or ~/.ssh/picoclaw_ed25519.key. An SSH private key must be resolvable or Encrypt returns an error.
func GenerateSSHKey ¶
GenerateSSHKey generates an Ed25519 SSH key pair and writes the private key to path (permissions 0600) and the public key to path+".pub" (permissions 0644). The ~/.ssh/ directory is created with 0700 if it does not exist. If the files already exist they are overwritten.
Types ¶
type Resolver ¶
type Resolver struct {
// contains filtered or unexported fields
}
Resolver resolves raw credential strings for model_list api_key fields. File references are resolved relative to the directory of the config file.
func NewResolver ¶
NewResolver returns a Resolver that resolves file:// references relative to configDir (typically filepath.Dir of the config file path).
type SecureStore ¶
type SecureStore struct {
// contains filtered or unexported fields
}
SecureStore holds a passphrase in memory.
Uses atomic.Pointer so reads and writes are lock-free. The passphrase is never written to disk; callers decide how to transport it outside this store (e.g., via cmd.Env or os.Environ).
func NewSecureStore ¶
func NewSecureStore() *SecureStore
NewSecureStore creates an empty SecureStore.
func (*SecureStore) Get ¶
func (s *SecureStore) Get() string
Get returns the stored passphrase, or "" if not set.
func (*SecureStore) IsSet ¶
func (s *SecureStore) IsSet() bool
IsSet reports whether a passphrase is currently stored.
func (*SecureStore) SetString ¶
func (s *SecureStore) SetString(passphrase string)
SetString stores the passphrase. An empty string clears the store.