Documentation
¶
Overview ¶
Package soliconfig is a thin Go client for the soliconfig REST core, intended for machine/service usage (agents, CI, servers). It is the foundation for the soliconfig Terraform provider.
The client talks to the env-scoped "agent" endpoints (/v1/agent/...) and authenticates with an env-scoped API key (sc_...) via Authorization: Bearer.
Only the standard library is used — there are no external dependencies.
Index ¶
Constants ¶
const ( TemplateClient = "client" TemplateServer = "server" )
Template types for a config fetch. When unspecified the server defaults to TemplateClient.
const ( CodeQuotaExceeded = "quota_exceeded" CodeOverageBlocked = "overage_blocked" CodeSeatLimit = "seat_limit" )
Machine-readable codes surfaced by entitlement/quota gates.
const DefaultBaseURL = "https://api.soliconfig.com"
DefaultBaseURL is the production soliconfig API base URL.
Variables ¶
This section is empty.
Functions ¶
func IsEncrypted ¶
IsEncrypted reports whether a value is ECIES ciphertext (i.e. carries the "encrypted:" prefix) rather than plaintext.
Types ¶
type APIError ¶
type APIError struct {
// StatusCode is the HTTP status code of the response.
StatusCode int
// Code is the machine-readable error code (e.g. "quota_exceeded"), if any.
Code string
// Message is the human-readable error message.
Message string
}
APIError is returned for any non-2xx response from the soliconfig API.
The API reports failures in two shapes:
- Generic HTTP failures carry a human message: {"error": "..."}.
- Quota/entitlement gates carry a machine code: {"code": "quota_exceeded"} (also "overage_blocked", "seat_limit"), typically with HTTP 429.
Both are captured here: Code holds the machine code (when present) and Message holds the human message (falling back to the code or the HTTP status text). Callers can branch on Code, e.g.:
var apiErr *soliconfig.APIError
if errors.As(err, &apiErr) && apiErr.Code == soliconfig.CodeQuotaExceeded {
// back off / surface upgrade prompt
}
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a soliconfig REST client. Create one with New. It is safe for concurrent use by multiple goroutines.
func New ¶
New creates a Client authenticated with the given env-scoped API key (sc_...). Options may override the base URL and HTTP client.
func (*Client) DecryptSecrets ¶
func (c *Client) DecryptSecrets(ctx context.Context, orgID, envID string) (map[string]string, error)
DecryptSecrets fetches the latest env version and returns fully-decrypted, plaintext secret values via the server-side decrypt endpoint POST /v1/orgs/{orgID}/environments/{envID}/vault/decrypt.
Unlike PullSecrets — which returns "encrypted:"-prefixed ciphertext verbatim — this performs the decrypt on the server. It requires a read or admin scoped API key (sc_...); an encrypt-only key is rejected with a 403 *APIError. The environment's vault must have server-managed decrypt enabled (requireApproval = false); when approval is required the server responds 409 (surfaced as an *APIError with the "approval_required" code) and this method does not perform the approval dance. Entitlement/plan gates surface as a 402 *APIError.
The returned map is keyed by secret name with plaintext values.
func (*Client) FetchConfig ¶
FetchConfig performs a one-shot, server-evaluated config fetch against POST /v1/agent/config/fetch. The API key must be env-scoped and readable (an encrypt-only key is rejected with an *APIError).
func (*Client) PullSecrets ¶
PullSecrets fetches the latest env version via GET /v1/agent/env. The API key must be env-scoped and readable (an encrypt-only, write-only key is rejected with an *APIError). When no version has been pushed yet, Version is 0 and Entries is empty.
See the Secrets docs: entry values may be "encrypted:"-prefixed ciphertext; this client returns them verbatim and does not decrypt.
type Config ¶
type Config struct {
Version int `json:"version"`
Evaluated map[string]EvaluatedValue `json:"evaluated"`
}
Config is the result of FetchConfig: the published version and the evaluated parameter map keyed by parameter name.
type Environment ¶
type Environment struct {
ID string `json:"id"`
Name string `json:"name"`
PublicKey string `json:"publicKey"`
}
Environment describes the env-scoped target resolved from the API key, plus its public key (used by producers to encrypt values before push).
type EvalContext ¶
type EvalContext struct {
// RandomizationID is the sticky bucketing id (required, min length 1).
RandomizationID string `json:"randomizationId"`
// CustomSignals are arbitrary string key/value signals for rule matching.
CustomSignals map[string]string `json:"customSignals,omitempty"`
// Platform is one of "web", "ios", "android", "server".
Platform string `json:"platform,omitempty"`
// Country is an ISO 3166-1 alpha-2 code (2 letters).
Country string `json:"country,omitempty"`
// Language is a BCP-47-ish language tag.
Language string `json:"language,omitempty"`
// Now is an optional ISO-8601 timestamp override for time-based rules.
Now string `json:"now,omitempty"`
}
EvalContext is the server-side evaluation context (Firebase Remote Config parity). RandomizationID is required; all other fields are optional.
type EvaluatedValue ¶
type EvaluatedValue struct {
// Value is the raw string value.
Value string `json:"value"`
// ValueType is one of "string", "boolean", "number", "json".
ValueType string `json:"valueType"`
// Source is "conditional" or "default".
Source string `json:"source"`
// MatchedCondition is the name of the matched condition, when Source is
// "conditional".
MatchedCondition string `json:"matchedCondition,omitempty"`
}
EvaluatedValue is a single evaluated parameter. Value is always the raw string representation; ValueType indicates how to interpret it. Use the typed accessors (Bool, Int, Float, JSON) to cast.
func (EvaluatedValue) Bool ¶
func (v EvaluatedValue) Bool() bool
Bool parses the value as a boolean (true when Value == "true"), matching the server-side cast semantics.
func (EvaluatedValue) Float ¶
func (v EvaluatedValue) Float() (float64, error)
Float parses the value as a float.
func (EvaluatedValue) Int ¶
func (v EvaluatedValue) Int() (int64, error)
Int parses the value as an integer.
func (EvaluatedValue) JSON ¶
func (v EvaluatedValue) JSON(out any) error
JSON unmarshals the value (a JSON document) into out.
type FetchConfigParams ¶
type FetchConfigParams struct {
// Context is the evaluation context. RandomizationID must be set.
Context EvalContext
// TemplateType is "client" or "server" (default "client" server-side).
TemplateType string
}
FetchConfigParams are the inputs to FetchConfig.
type HTTPDoer ¶
HTTPDoer is the subset of *http.Client used by the client. It lets callers inject a custom transport (retries, tracing, mocks, ...) via WithHTTPClient.
type Option ¶
type Option func(*Client)
Option configures a Client in New.
func WithBaseURL ¶
WithBaseURL overrides the API base URL (default DefaultBaseURL). A trailing slash is trimmed. Useful for self-hosted deployments or tests.
func WithHTTPClient ¶
WithHTTPClient sets a custom HTTP client (or any HTTPDoer). When unset a *http.Client with a 30s timeout is used.
type Secrets ¶
type Secrets struct {
Environment Environment `json:"environment"`
Version int `json:"version"`
Entries map[string]string `json:"entries"`
}
Secrets is the result of PullSecrets: the environment metadata, the current version, and the entries map.
Entries values are stored server-side as ciphertext and are returned with the "encrypted:" prefix (base64 ECIES over secp256k1 + AES-256-GCM, dotenvx wire-compatible). The server never sees plaintext and there is no server-side decrypt endpoint, so decryption is a client-side concern requiring the environment's private key and a secp256k1 ECIES implementation — which is out of scope for this stdlib-only client. Use IsEncrypted to detect ciphertext; values without the prefix are already plaintext.