Documentation
¶
Overview ¶
Package credentials provides secure (preferred) + plaintext (fallback) storage for Sting authentication material.
Isolation Guarantee ¶
This package is deliberately isolated from the user's real GitHub CLI (gh) configuration:
- We never mutate the GH_CONFIG_DIR environment variable.
- We never use github.com/cli/go-gh/v2/pkg/config for writing credentials. (That package only supports configuration via GH_CONFIG_DIR, which creates too much risk of accidental leakage or corruption of ~/.config/gh during development, testing, or error conditions.)
- All insecure (plaintext) credential storage is written exclusively to Sting's own hosts.yml using our own minimal implementation.
- We never shell out to `gh auth token`, and we never silently adopt an ambient GitHub token (GH_TOKEN / GITHUB_TOKEN or the gh CLI config file). Consulting those ambient sources is strictly opt-in via STING_ALLOW_AMBIENT_GITHUB_TOKEN, so a stored Sting credential is never transparently replaced by whatever identity happens to live in the surrounding shell.
The design follows the same logical "hosts.<composite>" structure that gh uses for familiarity, but everything under Sting's own directory.
This package is intentionally internal. The public config package remains focused on query defaults and does not grow auth token concerns.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CredentialRef ¶
type CredentialRef struct {
Provider Provider
Host string
Username string // may be empty
Source Source
}
CredentialRef is a lightweight reference returned by List.
type KeyringBackend ¶
type KeyringBackend interface {
Set(service, user, secret string) error
Get(service, user string) (string, error)
Delete(service, user string) error
}
KeyringBackend is the minimal interface we need from a keyring implementation. This allows tests to inject a mock.
type Store ¶
type Store interface {
// Save persists a credential for the given provider + host.
// secureOnly=true forces an error instead of falling back to plaintext.
Save(ctx context.Context, provider Provider, host string, tok Token, secureOnly bool) (usedInsecure bool, err error)
// Load returns the best available token for (provider, host).
// It applies precedence rules (OAuth > PAT for the same provider+host)
// and returns the Source so callers (e.g. auth status) can produce
// appropriate messaging.
Load(ctx context.Context, provider Provider, host string) (tok Token, src Source, err error)
// Delete removes credentials for the given provider + host.
// It attempts to clean both secure and insecure locations.
Delete(ctx context.Context, provider Provider, host string) error
// List returns known (provider, host) combinations that have stored credentials.
// Useful for `auth status --all` or similar.
List(ctx context.Context) ([]CredentialRef, error)
}
Store is the main abstraction for credential lifecycle.
func New ¶
New creates a Store using the default discovery order: 1. Try secure keyring via our internal/keyring wrapper. 2. Fall back to our own hosts.yml (no env var mutation, no risk to gh config). The returned Store is safe for concurrent use.
func NewInsecure ¶
NewInsecure creates a Store rooted at Sting's config directory that never uses the system keyring: credentials are always written to the plaintext hosts.yml. This backs the `--insecure-storage` flag so it deterministically forces file storage instead of merely permitting fallback.