Documentation
¶
Overview ¶
Package tokenstore provides a pluggable credential store shared by the entiredb and entire-core CLIs.
By default it delegates to the OS keyring (macOS Keychain, Linux Secret Service, etc.). Set ENTIRE_TOKEN_STORE=file to use a JSON file instead, which is useful in CI environments that lack a keyring daemon.
When using the file backend the tokens are stored in $ENTIRE_TOKEN_STORE_PATH (default: ~/.config/entire/tokens.json).
Service-name conventions:
- "entire:<cluster-host>" — entiredb cluster login tokens
- "entire-core:<core-base-url>" — entire-core control-plane tokens
- "<service>:refresh" — refresh-token entry paired with the corresponding access-token service
Index ¶
- Constants
- Variables
- func ClusterKeyringService(host string) string
- func CoreKeyringService(coreURL string) string
- func DecodeTokenWithExpiration(encoded string) (token string, expiresAt time.Time)
- func Delete(service, user string) error
- func EncodeTokenWithExpiration(token string, expiresIn int64) string
- func Get(service, user string) (string, error)
- func IsTokenExpiredOrExpiring(expiresAt time.Time) bool
- func KeyringServiceForIssuerKey(key string) string
- func Set(service, user, password string) error
- func UseFileBackendForTesting(path string) func()
Constants ¶
const ( ClusterKeyringPrefix = "entire:" // entiredb cluster-issued tokens CoreKeyringPrefix = "entire-core:" // entire-core control-plane tokens )
Keyring service-name prefixes. Tokens are filed under whichever issuer vouched for them, so a JWT obtained via an entire-core login flow lives at "entire-core:<base-url>" regardless of which CLI wrote it. Two CLIs sharing this prefix on the same machine read each other's writes.
const TokenExpirationBuffer = 5 * time.Minute
TokenExpirationBuffer is how long before expiration we should refresh.
const TokenExpirationSeparator = "|"
TokenExpirationSeparator separates the token from its expiration timestamp. Format: "token|expires_at_unix"
Variables ¶
var ErrNotFound = keyring.ErrNotFound
ErrNotFound is returned when a credential is not present in the store.
Functions ¶
func ClusterKeyringService ¶
ClusterKeyringService returns the service name for tokens issued by an entiredb cluster. host is typically the cluster's entry domain.
func CoreKeyringService ¶
CoreKeyringService returns the service name for tokens issued by entire-core. coreURL is the base URL of the issuer; trailing slashes are normalized away so callers don't have to.
func DecodeTokenWithExpiration ¶
DecodeTokenWithExpiration decodes a token that may have an expiration timestamp. Returns the token and expiration time. If no expiration is encoded, returns the token as-is and a zero time.
func EncodeTokenWithExpiration ¶
EncodeTokenWithExpiration encodes a token with its expiration time as a "token|expires_at_unix" suffix. Callers must pass a positive expiresIn — the encoded suffix is the contract that tells future readers when to refresh, and a zero/negative TTL would record an immediately-expired token.
func IsTokenExpiredOrExpiring ¶
IsTokenExpiredOrExpiring checks if a token is expired or will expire soon. A zero expiresAt is treated as "unknown, assume expired".
func KeyringServiceForIssuerKey ¶
KeyringServiceForIssuerKey infers the right service prefix from a raw issuer key (entire-core URL or entiredb cluster host). URL-shaped keys (anything beginning with a scheme) are treated as entire-core issuers; bare hostnames as cluster issuers. Used by callers that derive a service name without already having a *contexts.Context in hand (tests, entiredb's pre-resolution code paths).
func UseFileBackendForTesting ¶
func UseFileBackendForTesting(path string) func()
UseFileBackendForTesting points the package-level token store at a per-test JSON file and returns a cleanup function that restores the previous backend (re-resolving on next use). It serializes against concurrent Get/Set/Delete calls via the same mutex they use, so it is safe to call from any test even if other goroutines are mid-call.
Each call replaces the active backend; tests that invoke this from parallel subtests will trample each other and should arrange their own per-subtest paths if they actually need isolation.
Types ¶
This section is empty.