Storage modes reference¶
The exact values of the three Mode constants, what each one persists, and the two
different functions that decide which modes a process may offer. For the reasoning
behind the modes rather than their definitions, see the
trust model.
What are the three Mode values?¶
Mode is a defined string type. Its three constants are:
| Constant | String value | The config records | The secret lives in |
|---|---|---|---|
ModeEnvVar |
env |
the name of an environment variable | the process environment |
ModeKeychain |
keychain |
a service / account reference |
whatever Backend is registered — the OS keychain by default |
ModeLiteral |
literal |
the secret itself | the config file, in plaintext |
The string values are what a config file persists, so they are part of your on-disk
format. ModeEnvVar is the recommended default.
Is an unrecognised mode string rejected?¶
No. The package provides no parser and no validator for Mode. Reading "Env",
"ENV" or "vault" out of a config file yields a Mode that compares unequal to
all three constants and is silently carried around as-is. If your tool reads a mode
back from config, compare it against the constants yourself and decide what an
unknown value means — the package will not do it for you, and RefuseLiteralUnderCI
will pass an unrecognised value straight through.
Which modes may this process use? (AvailableModes)¶
Reports the modes the process is capable of, in a fixed order:
ModeEnvVar— always present, always first.ModeKeychain— present only whenKeychainAvailable()is true, i.e. a keychain-capableBackendis registered.ModeLiteral— always present.
Two things it deliberately does not do, and both surprise people:
- It does not consult
IsCI().ModeLiteralis in the returned slice underCI=true.AvailableModesanswers "what is compiled in", not "what may be offered". - It does not probe.
ModeKeychainappears as soon as a backend is registered, even if the keychain is locked or the Secret Service is absent.
Which modes should I show the user? (ModeChoices)¶
func ModeChoices(ci, keychainUsable bool, envLabel, keychainLabel, literalLabel string) []ModeChoice
This is the function to build a menu from. Each returned ModeChoice is a Mode
plus the Label you supplied. The filtering rules:
| Mode | Included when | Position |
|---|---|---|
ModeEnvVar |
always | always first |
ModeKeychain |
keychainUsable is true |
second, when present |
ModeLiteral |
ci is false |
last, when present |
Both booleans are yours to supply. The idiomatic call passes credentials.IsCI()
and credentials.Probe(ctx) — the package does not call them for you, so passing
true, true from a CI job will happily offer literal mode.
Labels are used verbatim and are never defaulted: pass an empty string and the menu
renders an entry with no text. ModeEnvVar being first is what makes "press Enter
for the default" land on the safe option in
DefaultPrompter.
When is ModeKeychain genuinely usable?¶
Two functions answer different halves of that question, and a setup flow needs both.
KeychainAvailable() |
Probe(ctx) |
What it means | Offer keychain? |
|---|---|---|---|
false |
false (short-circuits) |
No keychain-capable backend registered — the credentials/keychain subpackage was not imported and no custom backend was registered. |
No |
true |
false |
A backend is compiled in, but the live round-trip failed right now: locked keychain, absent Secret Service on a headless Linux host, unreachable remote store, or the call exceeded the context deadline. | No |
true |
true |
A backend is registered and it accepted a full Set → Get → Delete round-trip. | Yes |
Probe short-circuits to false without touching anything when
KeychainAvailable() is false, so it is always safe to call. It can never return
true when KeychainAvailable() is false.
What the modes do not come with¶
- No resolution chain. This module has no "try the env var, then the keychain,
then the literal" resolver. It defines the modes and the keychain round-trip; the
precedence your tool applies at runtime is your tool's code. Documentation
elsewhere in the toolkit that describes a
*.env→*.keychain→*.keycascade is describing a consumer of this module, not this module. - No config reading or writing. Nothing here reads or writes a config file.
ClearKeysExceptis the only config-adjacent helper and it writes through an interface you supply. - No automatic CI refusal.
RefuseLiteralUnderCIis a check you call; nothing inStore,Retrieveor the prompters invokes it for you.
Related¶
- API reference — every exported symbol
- Errors reference — the two sentinels and when each is returned
- Choose a storage mode — the decision, with code
- Trust model — what each mode protects against