credstore

package
v0.88.2 Latest Latest
Warning

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

Go to latest
Published: Oct 16, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package credstore implements credential storage.

Per § Credentials: encrypted-file is the primary store (AES-GCM with a passphrase- or machine-bound key). OS keychain integrations are opt-in build-tagged plugins per platform, those live next to this file with `_darwin.go` / `_linux.go` / `_windows.go` suffixes and call back into Store.

Package credstore is part of the GoFastr harness.

See docs/harness-architecture.md for the architecture this package implements.

Index

Constants

This section is empty.

Variables

View Source
var ErrAmbiguousLegacyKey = errors.New("credstore: ambiguous legacy credential key; re-enter the credential")

ErrAmbiguousLegacyKey is returned by Get when the only entry for the pair is a legacy "provider|account" key holding more than one '|': the old format cannot say which pair wrote it, so the secret is not handed to either. Re-enter it with Put (or remove it with Delete) on the right pair.

View Source
var ErrNotFound = errors.New("credstore: not found")

ErrNotFound is returned by Get when the (provider, account) pair has no entry.

Functions

func DeriveKey

func DeriveKey(passphrase, salt []byte) []byte

DeriveKey returns a 32-byte key from a passphrase using PBKDF2-SHA256.

salt should be a stable per-install value (e.g. a UUID generated on first run and stored in `~/.config/gofastr/harness/salt`).

The PBKDF2 iteration count is intentionally high (200k) since unlocking is rare, once per harness boot for interactive use.

func MachineKey

func MachineKey(hostname string, extra []byte) []byte

MachineKey derives a 32-byte key from machine-stable inputs without any user passphrase. Used for headless/CI where there's no human to type a passphrase. The threat model accepts that anyone with root on the machine can re-derive the same key, that's expected for the CI use case.

Types

type EncryptedFileStore

type EncryptedFileStore struct {
	// contains filtered or unexported fields
}

EncryptedFileStore is the primary implementation: an AES-GCM encrypted JSON file at the configured path.

File layout (post-decryption):

{
  "entries": {
    "openrouter|default": "<api-key>",
    "zai|default":        "<api-key>"
  }
}

func NewEncryptedFileStore

func NewEncryptedFileStore(path string, key []byte) (*EncryptedFileStore, error)

NewEncryptedFileStore returns a Store backed by an encrypted file at the given path. The 32-byte key is derived elsewhere (DeriveKey from passphrase, or machine-bound key from /etc/machine-id + hostname).

func (*EncryptedFileStore) Delete

func (s *EncryptedFileStore) Delete(provider, account string) error

func (*EncryptedFileStore) Get

func (s *EncryptedFileStore) Get(provider, account string) (string, error)

func (*EncryptedFileStore) List

func (s *EncryptedFileStore) List() ([]Entry, error)

func (*EncryptedFileStore) Put

func (s *EncryptedFileStore) Put(provider, account, secret string) error

type Entry

type Entry struct {
	Provider string
	Account  string
}

Entry describes a stored credential without its secret value.

type Store

type Store interface {
	Get(provider, account string) (string, error)
	Put(provider, account, secret string) error
	Delete(provider, account string) error
	List() ([]Entry, error)
}

Store is the credential store interface. Tokens are addressed by a {provider, account} key pair, most providers have one account per install (the API key); Copilot's auth flow has an explicit account-per-GitHub-user model.

Jump to

Keyboard shortcuts

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