Releases: SmooAI/config
v6.7.0
Minor Changes
- ad2c77f: SMOODEV-1526: Port the ESO manifest generator (
buildClusterSecretStore+buildExternalSecret) to the Go, Python, Rust, and C# SDKs for language parity with the TypeScript reference. Each emits the same ClusterSecretStore (webhook → real api.smoo.ai config-values endpoint) and per-workload ExternalSecret (secret-tier config keys → UPPER_SNAKE_CASE env vars, with overrides + duplicate guard), using each language's native snakecase util. Epic SMOODEV-1522. - ad2c77f: SMOODEV-1526: Port the ESO bearer-token refresher core (the refresh algorithm +
SecretWriterabstraction) to the Go, Python, Rust, and C# SDKs for parity with the TypeScript reference. Each mirrors the same behavior — invalidate-then-mint each cycle so the bootstrap Secret always holds a near-full-TTL token, fail-loud initial write, non-fatal loop-tick retries — driven by the language's own TokenProvider and unit-tested with a fake writer (no live cluster). The k8s-backed writer is intentionally an optional adapter so base SDK consumers don't pull a heavy k8s client; the TypeScript sidecar remains the canonical deployable. Epic SMOODEV-1522.
v6.6.0
Minor Changes
- bb64793: SMOODEV-1524: Add an ESO manifest generator (
@smooai/config/eso-manifests).buildClusterSecretStore()emits aClusterSecretStorewhose webhook provider points at the realapi.smoo.aiconfig-values endpoint (org + environment baked in, bearer from the bootstrap Secret the eso-refresher keeps fresh), andbuildExternalSecret()emits a per-workloadExternalSecretmapping secret-tier config keys to env-var names (UPPER_SNAKE_CASEby default, with per-key overrides likeDASHSCOPE_API_KEY←alibabaModelStudioApiKey). Replaces the hand-maintained ESO YAML and makes ESO sync a first-class output of the config system. Epic SMOODEV-1522.
v6.5.0
Minor Changes
- 8fe21bd: SMOODEV-1523: Add an ESO bearer-token refresher (
@smooai/config/eso-refresher+smooai-config-eso-refresherbin). It re-mints the OAuth2client_credentialsaccess token on a short interval (reusingTokenProvider) and writes it into the ExternalSecrets bootstrap Kubernetes Secret, so ESO's webhook provider always reads a fresh, non-expired bearer. This is what lets workload secrets sync via ESO instead of being Pulumi-baked at SST deploy time — decoupling@smooai/configsecret-value changes from the ~1h platform deploy (epic SMOODEV-1522).
v6.4.0
Minor Changes
-
2bff2d9: SMOODEV-1494: Add container/runtime mode to the Rust SDK (
smooai_config::container) — parity with the TypeScript reference (SMOODEV-1490) and the five-language contract (SMOODEV-1489).Container mode makes the HTTP config API the first-class, fail-loud path for long-lived containers (EKS/ECS) instead of the Lambda-oriented baked blob:
-
init_container_config(InitContainerConfigOptions) -> Result<ContainerConfigHandle, ConfigError>— validates the container env contract, mints an M2M OAuth token, and performs an initial config fetch so auth/network/missing-env failures surface at startup (not first read). Missing/blank required env returnsConfigError::Bootstrap(ConfigBootstrapError { missing })listing exactly which vars are absent. -
Fail-loud reads —
handle.secret_config()/public_config()/feature_flag()each exposeget(key).awaitandget_sync(key)that returnErr(ConfigError::KeyUnresolved(ConfigKeyUnresolvedError { key, env, tried_tiers }))for a required key that resolves absent, instead of silently returningOk(None)(the SMOODEV-1478 CrashLoop class).optional_keysopts specific keys out (returningOk(None)). -
config_health(&handle)/handle.health() -> ConfigHealth— non-failing status for Kubernetes readiness/liveness probes; serves last-good within the 30s cache TTL, reportsUnhealthy { reason }past hard-expiry. -
select_mode(Option<SelectModeInputs>) -> Mode— mode selection (explicitSMOOAI_CONFIG_MODE=container, blob/file present →Default, or auto-select on M2M creds). -
Typed errors
ConfigBootstrapError,ConfigKeyUnresolvedError, andConfigTier(blob|env|http|file) mirror the TS shapes/fields; constantsDEFAULT_CACHE_TTL(30s) andDEFAULT_TOKEN_REFRESH_BUFFER_SECONDS(60). On a 401 the token is invalidated and the request retried once.README gains a "Container / Runtime Mode" section linking the shared
docs/Container-Runtime-Mode.md.
-
v6.3.0
Minor Changes
-
68a1737: SMOODEV-1491: Add container/runtime mode to the .NET SDK (
SmooAI.Config.Container) — brings the C# client to parity with the TypeScript reference (SMOODEV-1490) of the five-language contract (SMOODEV-1489).Container mode makes the HTTP config API the first-class, fail-loud path for long-lived containers (EKS/ECS) instead of the Lambda-oriented baked blob:
ContainerConfig.InitContainerConfigAsync(options)— validates the container env contract, mints an M2M OAuth token, and does an initial fetch-all-values so auth/network failures surface at startup (not first read). Missing/blank required env throws a typedConfigBootstrapExceptioncarryingMissing(the exact env var names).- Fail-loud reads —
SecretConfig.GetAsync/GetSync(and the public/flag analogs) throwConfigKeyUnresolvedException { Key, Env, TriedTiers }for a required key that resolves absent, instead of silently returningnull(the SMOODEV-1478 CrashLoop class).OptionalKeysopts specific keys out. Per the TS design fork, all schema keys are required by default. ContainerConfig.Health(handle)/handle.Health()— non-throwingConfigHealth { Status, Reason }for Kubernetes readiness/liveness probes; serves last-good within the 30s cache TTL, reportsunhealthypast hard-expiry.ContainerConfig.SelectMode(inputs)— mode selection (explicitSMOOAI_CONFIG_MODE=container, blob/file present → default, or auto-select on M2M creds).- Same exact
SMOOAI_CONFIG_*env contract, env-over-http tier precedence,UPPER_SNAKE_CASE(key)env overrides, 30s cache TTL, 60s token refresh buffer, and 401 → refresh → retry as the TypeScript reference. - README "Container / Runtime Mode" section linking the shared
docs/Container-Runtime-Mode.md.
-
fedbabf: SMOODEV-1492: Add container/runtime mode to the Go SDK (
github.com/SmooAI/config/go/config/container) — bringing it to parity with the TypeScript reference (SMOODEV-1490) under the five-language contract (SMOODEV-1489).Container mode makes the HTTP config API the first-class, fail-loud path for long-lived containers (EKS/ECS) instead of the Lambda-oriented baked blob, with idiomatic Go semantics (error returns +
context.Context, no panics on the error-returning path):InitContainerConfig(ctx, opts) (*ContainerConfigHandle, error)— validates the container env contract, mints an M2M OAuth token, and does an initial fetch so auth/network failures surface at startup (not first read). Missing/blank required env returns a typed*ConfigBootstrapErrorlisting exactly which vars are missing.- Fail-loud reads —
handle.SecretConfig/PublicConfig/FeatureFlag:Get(key) (value, ok, err)returns*ConfigKeyUnresolvedError{ Key, Env, TriedTiers }for a required key that resolves absent (the SMOODEV-1478 CrashLoop class);MustGet(key) (value, ok)is the fail-loud sync analog that panics on the same.OptionalKeysopts specific keys out (returns the zero value,ok=false, no error). handle.Health() ConfigHealthandcontainer.ConfigHealthOf(handle)— non-erroring status for Kubernetes readiness/liveness probes; serves last-good within the 30s cache TTL, reportsunhealthypast hard-expiry.container.SelectMode(*SelectModeInputs) string— mode selection (explicitSMOOAI_CONFIG_MODE=container, blob/file present → default, or auto-select on M2M creds).- Same defaults as every SDK: 30s cache TTL, 60s token refresh buffer, 401→invalidate→retry once. New
ConfigClient.SeedCache/ConfigClient.GetCachedValuehelpers back the env-tier override + last-good serving.
v6.1.0
Minor Changes
-
5c9de91: SMOODEV-1490: Add container/runtime mode (
@smooai/config/container) — the TypeScript reference implementation of the five-language parity contract (SMOODEV-1489).Container mode makes the HTTP config API the first-class, fail-loud path for long-lived containers (EKS/ECS) instead of the Lambda-oriented baked blob:
initContainerConfig(options?)— validates the container env contract, mints an M2M OAuth token, and does an initial config fetch so auth/network failures surface at startup (not first read). Missing/blank required env throws a typedConfigBootstrapErrorlisting exactly which vars are missing.- Fail-loud reads —
secretConfig.get/getSync(and public/flag analogs) throwConfigKeyUnresolvedError { key, env, triedTiers }for a required key that resolves absent, instead of silently returningundefined(the SMOODEV-1478 CrashLoop class).optionalKeysopts specific keys out. configHealth()/handle.health()— non-throwing status for Kubernetes readiness/liveness probes; serves last-good within the 30s cache TTL, reportsUnhealthypast hard-expiry.selectMode()— mode selection (explicitSMOOAI_CONFIG_MODE=container, blob/file present → default, or auto-select on M2M creds).- New canonical doc
docs/Container-Runtime-Mode.mdwith the env contract, an ExternalSecret (External Secrets Operator) recipe, and a readiness-probe example.
v6.0.1
Patch Changes
- 85fafd9: SMOODEV-993: The CLI now honors
SMOOAI_CONFIG_CLIENT_ID/SMOOAI_CONFIG_CLIENT_SECRET/SMOOAI_CONFIG_ORG_ID/SMOOAI_CONFIG_API_URL/SMOOAI_CONFIG_AUTH_URL(legacySMOOAI_CONFIG_API_KEYandSMOOAI_AUTH_URLaccepted) when those env vars are fully populated. The env-var-supplied OAuth credentials take precedence over~/.smooai/credentials.jsonsosmooai-config list/get/setetc. hit the same org as every other tool in the same shell — matches howscripts/bake-config-dev.ts,smoo-secrets/push-secrets.ts, and the prod deploy baker already authenticate. Falls back to~/.smooai/credentials.jsonunchanged when env vars are absent. Fixes the silent org mismatch where the CLI could query a totally different account than the surrounding scripts (caused an entire investigation cycle to chase a "missing secrets" mirage that was actually just wrong-org auth).
v6.0.0
Major Changes
- 722c705: SMOODEV-975/976/977: Python, Go, and Rust ConfigClients now exchange OAuth client_credentials for a JWT (parity with TS / .NET, fixing the silent 401s that previously sent the raw API key as Bearer). Each runtime SDK now requires
client_idin addition toclient_secret/api_key. NewTokenProviderclass exported in each language for caching/refresh (60s default refresh window, single-flight under a lock, invalidate-and-retry once on 401). Breaking change in constructors of all three SDKs.
v5.0.0
Major Changes
-
aa6b007: SMOODEV-974:
ConfigClient(TypeScript runtime) now exchanges OAuthclient_credentialsfor a JWT and uses that JWT as the Bearer token on/config/valuescalls, matching the .NETSmooConfigClient, the in-packagebootstrap, and the CLI.Breaking — all four broken language clients in this package previously sent the raw API key as the Bearer token, which the backend rejects with 401 because it expects a JWT. Live feature flag fetches and runtime config reads were therefore silent failures across TypeScript, Python, Go, and Rust. This release fixes TypeScript; Python / Go / Rust ship in follow-up tickets (SMOODEV-9xx).
TypeScript migration:
-
Set both
SMOOAI_CONFIG_CLIENT_IDandSMOOAI_CONFIG_CLIENT_SECRET(or the legacySMOOAI_CONFIG_API_KEY) on every consumer Lambda / process. The runtime SDK now requires both. -
new ConfigClient({...})now requiresclientIdin addition toclientSecret(orapiKey). Constructing withoutclientIdthrows. -
apiKeyis preserved as a deprecated alias forclientSecret. Source-level code that passesapiKeycontinues to compile, but the value is now treated as the OAuth client secret (which is what it always was in the AuthDynamoTable). -
New exported class
TokenProviderin@smooai/config/platform— mirrorsSmooAI.Config.OAuth.TokenProvider(mint, cache, 60s refresh window). Passnew TokenProvider({...})via thetokenProvideroption to override caching or for testing.No-change consumers:
-
bootstrap(@smooai/config/bootstrap) and the CLI were already doing the OAuth exchange — their behavior is unchanged. -
.NETSmooConfigClientwas already correct — unchanged. -
Schema/build/manage tooling is unchanged.
Behavior change to be aware of:
-
The TS runtime now makes an additional
POST /tokenrequest on cold start (and after token expiry / 401). The JWT is cached in-memory for the lifetime of theConfigClientinstance, refreshed 60s before expiry. On a 401 response from/config/valuesor/evaluate, the cached token is invalidated and the call is retried once.
-
v4.7.4
Patch Changes
- b36aa04: SMOODEV-957: Extend
ConfigKey<T>.ResolveAsyncin the .NET SDK to the full SMOODEV-857 priority chain — baked runtime →SMOOAI_CONFIG_<KEY>env var → live HTTP → local.smooai-config/<env>.json. Previously the .NET port only didbaked → HTTP, so deployments that needed a single key overridden without a re-bake had no env-var path, and dev laptops without network connectivity had no file-tier fallback.- Env-var names follow the existing convention (
moonshotApiKey→SMOOAI_CONFIG_MOONSHOT_API_KEY). JSON-shaped values are parsed; primitives become JSON strings so the typed deserializer round-trips correctly. - File-tier reads from
$SMOOAI_CONFIG_FILE_DIR/<env>.json(or./.smooai-config/<env>.json). Malformed or missing files are silent — same posture as TS / Python / Rust / Go. - HTTP failures (
HttpRequestException,SmooConfigApiException, request timeouts) fall through to the file tier so an offline laptop can still resolve from local defaults. Caller cancellation still propagates. SmooConfigClient.DefaultEnvironmentis now exposed internally so the file-tier lookup aligns with whatever env name the HTTP tier would have used.
- Env-var names follow the existing convention (