config

package
v1.50.7 Latest Latest
Warning

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

Go to latest
Published: Sep 1, 2026 License: Apache-2.0 Imports: 25 Imported by: 0

Documentation

Overview

Package config manages CLI configuration and profiles.

Index

Constants

View Source
const (
	// ColorName is the color setting. It is also a valid profile field, so it can
	// appear both at the top level and inside a profile.
	ColorName = "color"

	// InstalledPluginsKey lists the locally installed plugins.
	InstalledPluginsKey = "installed_plugins"

	// MachineUUIDKey is the persistent machine identifier used for telemetry.
	MachineUUIDKey = "machine_uuid"
)

Top-level config.toml keys that belong to the CLI itself rather than to a profile. A profile with one of these names is a collision, which is what moving profiles under the reserved profiles table fixes.

View Source
const (
	// PluginConfigGlobalScope is used as the scope when a setting applies to all plugins.
	PluginConfigGlobalScope = "__global"

	// PluginConfigUpdatesField is the config field name controlling automatic updates.
	PluginConfigUpdatesField = "updates"

	// PluginConfigsKey is the top-level table holding every plugin config
	// section. It is a CLI setting, not a profile.
	PluginConfigsKey = "plugin_configs"
)
View Source
const (
	AccountIDName              = "account_id"
	UserIDName                 = "user_id"
	DeviceNameName             = "device_name"
	DisplayNameName            = "display_name"
	IsTermsAcceptanceValidName = "is_terms_acceptance_valid"
	TestModeAPIKeyName         = "test_mode_api_key"
	TestModePubKeyName         = "test_mode_pub_key"
	TestModeKeyExpiresAtName   = "test_mode_key_expires_at"
	LiveModeAPIKeyName         = "live_mode_api_key"
	LiveModePubKeyName         = "live_mode_pub_key"
	LiveModeKeyExpiresAtName   = "live_mode_key_expires_at"
	SandboxClaimURLName        = "sandbox_claim_url"
	SandboxExpiresAtName       = "sandbox_expires_at"
	UserInfoName               = "user_info" // TODO: remove with legacy RAK/OIDC flow

	// ConfigVersionName is the top-level key recording the config file's schema
	// version. It is absent from v1 files, which is how an unmigrated file is
	// recognized.
	ConfigVersionName = "config_version"

	// ProfilesTableName is the reserved top-level table that holds every profile
	// in a v2 config file.
	ProfilesTableName = "profiles"
)

config key names

View Source
const (
	// DateStringFormat is the format for expiredAt date
	DateStringFormat = "2006-01-02"

	// KeyValidInDays is the number of days the API key is valid for
	KeyValidInDays = 90

	// KeyManagementService is the key management service name
	KeyManagementService = "StripeCLI"
)
View Source
const ColorAuto = "auto"

ColorAuto represents the auto-state for colors

View Source
const ColorOff = "off"

ColorOff represents the off-state for colors

View Source
const ColorOn = "on"

ColorOn represnets the on-state for colors

View Source
const ConfigBackupSuffix = ".v1.bak"

ConfigBackupSuffix is appended to the config file name to name the backup that the migration leaves behind, e.g. "config.toml.v1.bak".

View Source
const ConfigVersionV1 = 1

ConfigVersionV1 is the original layout, with each profile as a top-level table. A v1 file records no config_version key at all; the constant exists so that version comparisons don't have to spell out that absence.

View Source
const ConfigVersionV2 = 2

ConfigVersionV2 is the schema version in which every profile moved under the reserved ProfilesTableName table, so that profile names can no longer collide with top-level CLI settings.

View Source
const MaxSupportedConfigVersion = ConfigVersionV2

MaxSupportedConfigVersion is the newest config.toml layout this binary can act on. A file recording a higher version was written by a newer CLI, whose layout this build has no way to know.

View Source
const OAuthActiveContextKeychainKey = "oauth_active_context"

OAuthActiveContextKeychainKey is the keyring key for the active OAuth context.

View Source
const OAuthRefreshTokenKeychainKey = "oauth_refresh_token"

OAuthRefreshTokenKeychainKey is the keyring key for the OAuth refresh token.

View Source
const OAuthUATExpiresAtKeychainKey = "oauth_uat_expires_at"

OAuthUATExpiresAtKeychainKey is the keyring key for the UAT expiry time (RFC3339).

View Source
const UATKeychainItemKey = "uat"

Variables

View Source
var ErrProfileNotFound = errorcategory.New(errorcategory.UserInput, "profile not found")

ErrProfileNotFound is returned when no profile matches the requested name.

KeyRing is the global secure credential store.

View Source
var OAuthTokenRefresher func(p *Profile) error

OAuthTokenRefresher is called by ResolveCredentials when an OAK token is expired or about to expire. It refreshes the token and updates p in-place. Set by the login package via init().

Functions

func CredentialsFilePath added in v1.43.0

func CredentialsFilePath() string

CredentialsFilePath returns the path of the plain-text credentials file used by the file fallback store when the OS keyring is unavailable.

func GetUATExpiresAt added in v1.45.3

func GetUATExpiresAt() (time.Time, error)

GetUATExpiresAt retrieves the stored UAT expiry time from the keyring. Returns ErrKeyNotFound (wrapped) when no expiry has been saved.

func IsMigrated added in v1.50.7

func IsMigrated() bool

IsMigrated reports whether the loaded config file uses the v2 layout.

func MigrateConfigFile added in v1.50.7

func MigrateConfigFile(path string) (bool, error)

MigrateConfigFile rewrites the config file at path in the v2 layout, moving every profile under the reserved profiles table and recording config_version = 2. It reports whether the file changed.

The original file is copied to path + ConfigBackupSuffix first. The migrated document is verified in memory and again after the write; a failure at either point restores the backup and returns an error, so a partial or mangled file is never left behind.

A file whose config_version is newer than this binary understands is left untouched and returns an error.

This function does not decide *whether* to migrate. Callers own that.

func NeedsMigration added in v1.50.7

func NeedsMigration() bool

NeedsMigration reports whether the loaded config file should be rewritten in the v2 layout. It answers from the config already in memory, so it costs nothing on the common path.

It does not check that migrating is safe for plugins, and it does not check that the config file exists: a viper with no file loaded looks exactly like an unmigrated one.

func PluginConfigKey added in v1.40.1

func PluginConfigKey(scope, field string) string

PluginConfigKey returns the key for a plugin config field. Use PluginConfigGlobalScope as scope to target all plugins. Use the plugin name as scope to target a specific plugin. Example: PluginConfigKey("__global", "updates") to read or set the global updates setting Example: PluginConfigKey("apps", "updates") to read or set the updates setting for the "apps" plugin

func RedactAPIKey added in v1.10.4

func RedactAPIKey(apiKey string) string

RedactAPIKey returns a redacted version of API keys. The first 8 and last 4 characters are not redacted, everything else is replaced by "*" characters.

It panics if the provided string has less than 12 characters.

func ReloadConfigFile added in v1.50.7

func ReloadConfigFile() error

ReloadConfigFile re-reads the config file into the global viper, replacing what is already loaded rather than merging into it. Anything that rewrites the file behind viper's back — the config migration, for one — needs this to see its own changes.

The reset matters: ReadInConfig merges with existing values, so keys the rewrite removed would otherwise linger in memory.

func SaveActiveContext added in v1.45.3

func SaveActiveContext(accountID string, livemode bool) error

SaveActiveContext persists the active OAuth context (account ID + livemode) in the keyring so that ResolveCredentials can build the Stripe-Context header.

func SaveUATExpiresAt added in v1.45.3

func SaveUATExpiresAt(t time.Time) error

SaveUATExpiresAt persists the UAT expiry time in the keyring.

func ValidateProfileName added in v1.50.7

func ValidateProfileName(name string) error

ValidateProfileName reports whether name can be used as a profile name.

A period is rejected because it is viper's path separator, which hides the profile from every operation that enumerates top-level tables; see WarnIfLegacyProfileName for the full explanation. An empty name produces a leading-period key that viper silently drops, so writes to it are discarded without error.

Every other character round-trips correctly and is allowed.

Types

type ActiveContext added in v1.45.3

type ActiveContext struct {
	AccountID string `json:"account_id"`
	Livemode  bool   `json:"livemode"`
}

ActiveContext identifies the account and mode that is currently selected.

func GetActiveContext added in v1.45.3

func GetActiveContext() (*ActiveContext, error)

GetActiveContext reads the stored OAuth active context from the keyring. Returns nil, nil when no active context has been saved yet.

type ActiveContextLivemodeMismatchError added in v1.45.3

type ActiveContextLivemodeMismatchError struct {
	RequestedLivemode bool
	ActiveLivemode    bool
}

ActiveContextLivemodeMismatchError indicates that the requested livemode does not match the OAuth active context's livemode. Callers that expose their own mode selection (e.g. a --live flag) can catch this with errors.As and explain how to reconcile it; callers that don't care which mode is used can retry ResolveCredentials(err.ActiveLivemode) to get credentials for whichever mode is actually active.

func (*ActiveContextLivemodeMismatchError) Error added in v1.45.3

type AuthorizedAccount added in v1.45.3

type AuthorizedAccount struct {
	ID    string   `json:"id"`
	Name  string   `json:"name"`
	Modes []string `json:"modes"`
}

AuthorizedAccount represents a Stripe account accessible to an OAuth token.

type Compartment added in v1.42.12

type Compartment struct {
	CompartmentID string `json:"compartment_id" mapstructure:"compartment_id" toml:"compartment_id"`
	Livemode      bool   `json:"livemode"        mapstructure:"livemode"        toml:"livemode"`
}

Compartment represents a Stripe workspace from the OIDC userinfo response. TODO: remove with legacy RAK/OIDC flow.

type Config

type Config struct {
	Color            string
	LogLevel         string
	Profile          Profile
	ProfilesFile     string
	InstalledPlugins []string
	// contains filtered or unexported fields
}

Config handles all overall configuration for the CLI

func (*Config) CopyProfile added in v1.38.0

func (c *Config) CopyProfile(source string, target string) error

func (*Config) EditConfig added in v0.3.0

func (c *Config) EditConfig() error

EditConfig opens the configuration file in the default editor.

func (*Config) GetConfigFolder added in v0.6.0

func (c *Config) GetConfigFolder(xdgPath string) string

func (*Config) GetInstalledPlugins added in v1.9.0

func (c *Config) GetInstalledPlugins() []string

GetInstalledPlugins returns a list of locally installed plugins. This does not vary by profile

func (*Config) GetMachineUUID added in v1.44.1

func (c *Config) GetMachineUUID() string

GetMachineUUID returns the persistent machine UUID from config, generating and saving one if it doesn't exist.

func (*Config) GetProfile added in v1.8.0

func (c *Config) GetProfile() *Profile

GetProfile returns the Profile of the config

func (*Config) InitConfig

func (c *Config) InitConfig()

InitConfig reads in profiles file and ENV variables if set.

func (*Config) ListProfiles added in v1.38.0

func (c *Config) ListProfiles() error

func (*Config) PrintConfig added in v0.3.0

func (c *Config) PrintConfig() error

PrintConfig outputs the contents of the configuration file.

func (*Config) RemoveAllAuthFields added in v1.40.1

func (c *Config) RemoveAllAuthFields() error

RemoveAllAuthFields removes only auth-related fields from all profiles, preserving non-auth settings like color.

func (*Config) RemoveAllProfiles added in v1.4.0

func (c *Config) RemoveAllProfiles() error

RemoveAllProfiles removes all the profiles from the config file.

func (*Config) RemoveAuthFields added in v1.40.1

func (c *Config) RemoveAuthFields(profileName string) error

RemoveAuthFields removes only auth-related fields for the named profile, preserving non-auth settings like color.

func (*Config) RemoveProfile added in v1.4.0

func (c *Config) RemoveProfile(profileName string) error

RemoveProfile removes the profile whose name matches the provided profileName from the config file.

It returns ErrProfileNotFound when there is nothing to remove, so a caller acting on a name a user typed can tell the difference between a removal and a no-op. Callers that treat removal as best effort can ignore it.

func (*Config) SwitchProfile added in v1.38.0

func (c *Config) SwitchProfile(profileName string) error

func (*Config) WriteConfigField added in v1.8.2

func (c *Config) WriteConfigField(field string, value interface{}) error

WriteConfigField updates a configuration field and writes the updated configuration to disk.

type IConfig added in v1.8.0

type IConfig interface {
	GetProfile() *Profile
	GetConfigFolder(xdgPath string) string
	InitConfig()
	EditConfig() error
	PrintConfig() error
	CopyProfile(source string, target string) error
	ListProfiles() error
	SwitchProfile(targetProfileName string) error
	RemoveProfile(profileName string) error
	RemoveAllProfiles() error
	RemoveAuthFields(profileName string) error
	RemoveAllAuthFields() error
	WriteConfigField(field string, value interface{}) error
	GetInstalledPlugins() []string
	GetMachineUUID() string
}

IConfig allows us to add more implementations, such as ones for unit tests

type Profile

type Profile struct {
	DeviceName             string
	ProfileName            string
	APIKey                 string
	LiveModeAPIKey         string
	LiveModePublishableKey string
	TestModeAPIKey         string
	TestModePublishableKey string
	TerminalPOSDeviceID    string
	DisplayName            string
	AccountID              string
	UserID                 string
	SandboxClaimURL        string
	SandboxExpiresAt       string
	UAT                    string
	UserInfo               *UserInfo // TODO: remove with legacy RAK/OIDC flow

	// OAuthAccessBaseURL is the access-srv base URL to use for token refresh
	// and revocation. Set at startup from the --access-base flag; not persisted.
	OAuthAccessBaseURL string
}

Profile handles all things related to managing the project specific configurations

func (*Profile) CreateProfile

func (p *Profile) CreateProfile() error

CreateProfile creates a profile when logging in

func (*Profile) DeleteConfigField added in v0.3.0

func (p *Profile) DeleteConfigField(field string) error

DeleteConfigField deletes a configuration field.

func (*Profile) GetAPIKey added in v0.3.0

func (p *Profile) GetAPIKey(livemode bool) (string, error)

GetAPIKey will return the existing key for the given profile

func (*Profile) GetAccountID added in v1.7.4

func (p *Profile) GetAccountID() (string, error)

GetAccountID returns the accountId for the given profile.

func (*Profile) GetColor added in v0.5.2

func (p *Profile) GetColor() (string, error)

GetColor gets the color setting for the user based on the flag or the persisted color stored in the config file

func (*Profile) GetCompartmentID added in v1.45.0

func (p *Profile) GetCompartmentID(livemode bool) (string, error)

GetCompartmentID returns the account ID for the given livemode from the legacy OIDC UserInfo stored in the config file. TODO: remove with legacy RAK/OIDC flow.

func (*Profile) GetConfigField

func (p *Profile) GetConfigField(field string) string

GetConfigField returns the flat (v1) configuration path for a profile field, e.g. "default.account_id".

This same string is used verbatim as the keyring item ID for livemode secrets, so it must not gain the v2 "profiles." prefix: changing it would orphan every credential already stored in the OS keychain. To read a config value, use ReadProfileString or profileFieldIsSet, which understand both the v1 and v2 layouts. To write one, use configFieldForWrite.

func (*Profile) GetDeviceName

func (p *Profile) GetDeviceName() (string, error)

GetDeviceName returns the configured device name

func (*Profile) GetDisplayName added in v1.5.6

func (p *Profile) GetDisplayName() string

GetDisplayName returns the account display name of the user

func (*Profile) GetExpiresAt added in v1.10.4

func (p *Profile) GetExpiresAt(livemode bool) (time.Time, error)

GetExpiresAt returns the API key expirary date

func (*Profile) GetPublishableKey added in v0.6.0

func (p *Profile) GetPublishableKey(livemode bool) (string, error)

GetPublishableKey returns the publishable key for the user

func (*Profile) GetSessionCredentials added in v1.14.2

func (p *Profile) GetSessionCredentials() (*SessionCredentials, error)

GetSessionCredentials retrieves the session credentials from the keyring

func (*Profile) GetTerminalPOSDeviceID added in v1.4.0

func (p *Profile) GetTerminalPOSDeviceID() string

GetTerminalPOSDeviceID returns the device id from the config for Terminal quickstart to use

func (*Profile) GetUAT added in v1.45.0

func (p *Profile) GetUAT() (string, error)

GetUAT retrieves the user access token from the keyring. Returns an empty string if no UAT is stored.

func (*Profile) GetUserID added in v1.44.0

func (p *Profile) GetUserID() (string, error)

GetUserID returns the user ID for the given profile.

func (*Profile) GetUserInfo added in v1.42.12

func (p *Profile) GetUserInfo() (*UserInfo, error)

GetUserInfo reads the stored UserInfo from the profile config. Returns nil, nil when no user_info has been saved yet. TODO: remove with legacy RAK/OIDC flow.

func (*Profile) HasAPIKey added in v1.42.2

func (p *Profile) HasAPIKey(livemode bool) bool

HasAPIKey reports whether an API key is available for the given mode without reading its value. For live mode this checks the keyring key list only, avoiding OS-level auth prompts (e.g. macOS Keychain) that would be required to access the secret data.

func (*Profile) HasOverrideAPIKey added in v1.42.2

func (p *Profile) HasOverrideAPIKey() bool

HasOverrideAPIKey reports whether an in-memory API key override is active (via STRIPE_API_KEY env var or --api-key flag).

func (*Profile) PrintActiveContextBanner added in v1.45.3

func (p *Profile) PrintActiveContextBanner()

PrintActiveContextBanner prints the active context to stderr once per process. Call this at the start of commands that make user-visible Stripe API requests (resource commands, raw HTTP, fixtures, triggers).

func (*Profile) ReadProfileString added in v1.50.7

func (p *Profile) ReadProfileString(field string) string

ReadProfileString reads a profile field from the config file, preferring the v2 nested layout and falling back to the v1 flat layout.

Both layouts are supported indefinitely. A config file that has never been migrated stays fully readable, and one that a v2 CLI migrated is readable from this release line without the user having to undo anything.

func (*Profile) ReadProfileStringMap added in v1.50.7

func (p *Profile) ReadProfileStringMap(field string) map[string]string

ReadProfileStringMap reads a nested table inside a profile, such as the docs preferences, from whichever layout holds it.

func (*Profile) RegisterAlias added in v0.3.0

func (p *Profile) RegisterAlias(alias, key string)

RegisterAlias registers an alias for a given key in both layouts, so that legacy field names (secret_key, api_key, publishable_key) keep resolving in a migrated config file as well as an unmigrated one.

func (*Profile) ResolveCredentials added in v1.44.1

func (p *Profile) ResolveCredentials(livemode bool) (stripe.Credentials, error)

ResolveCredentials returns the credentials for the given mode. If an OAK token (prefix "oak_") is stored in the keyring and no explicit override is active, it is preferred over the configured API key. For OAK tokens the active context stored in the keyring sets both Stripe-Context and Stripe-Livemode; the livemode parameter is used only for the legacy OIDC fallback and plain API key path. If the active context's livemode differs from the requested livemode, it returns an *ActiveContextLivemodeMismatchError.

func (*Profile) ResolveCredentialsForAnyMode added in v1.50.1

func (p *Profile) ResolveCredentialsForAnyMode(livemode bool) (stripe.Credentials, error)

ResolveCredentialsForAnyMode resolves credentials for specified mode, but if that doesn't match the OAuth active context, resolves credentials for whichever mode is actually active instead of failing.

func (*Profile) ValidateProfileNameForWrite added in v1.50.7

func (p *Profile) ValidateProfileNameForWrite() error

ValidateProfileNameForWrite validates the profile name before writing to it.

Profiles that already exist are allowed through unchanged: reads against them work correctly, and refusing to write would leave users unable to update a profile they are actively using. Only the creation of new invalid names is blocked.

This grandfather clause can be dropped once the config migration renames existing dotted profiles, at which point the rule becomes unconditional.

func (*Profile) WarnIfLegacyProfileName added in v1.50.2

func (p *Profile) WarnIfLegacyProfileName()

WarnIfLegacyProfileName tells the user when the active profile has a period in its name.

Profile fields are addressed as <profile>.<field> keys in viper, which uses "." as its path separator. A profile name containing a period is therefore indistinguishable from a nested table: viper reads ["a.b"] back as a -> b, so the profile becomes invisible to every operation that enumerates top-level tables, even though reads against it keep working. That makes this warning the only signal the user gets that the profile cannot be listed by name.

It only fires for a profile that is actually in the config file, so that a period in a name nobody is using stays silent.

func (*Profile) WriteConfigField added in v0.3.0

func (p *Profile) WriteConfigField(field, value string) error

WriteConfigField updates a configuration field and writes the updated configuration to disk.

type SessionCredentials added in v1.14.2

type SessionCredentials struct {
	UAT        string `json:"uat"`
	PrivateKey string `json:"private_key"`
	AccountID  string `json:"account_id"`
}

SessionCredentials are the credentials needed for this session

type UserInfo added in v1.42.12

type UserInfo struct {
	Compartments []Compartment `json:"https://stripe.com/compartments" mapstructure:"compartments" toml:"compartments"`
}

UserInfo mirrors the OIDC userinfo endpoint response and is persisted as a nested table in the profile config. TODO: remove with legacy RAK/OIDC flow.

Jump to

Keyboard shortcuts

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