Immutable
release. Only release title and notes can be modified.
Summary
- Provider setup and runtime routing now require explicit
provider:model
IDs across config, request bodies, and WebSocket surfaces; bare and
slash-form model strings are rejected. - Provider coverage extends to Codex subscription-login, Vertex AI, Bedrock,
Venice AI, and the local Claude CLI alongside Anthropic, OpenAI, Gemini,
and Ollama. - WebSocket and HTTP configuration/model errors expose public-safe messages
and typed error codes while logging operator hints server-side. - Hot-reload bridge owns the provider-cache write so rejected reloads no
longer broadcast spurious change ticks;build_providersruns on
spawn_blockingso the runtime worker is not blocked during reload. - Built-in usage pricing table has been removed;
cost_usdand per-period
costfields are computed only from operator-configured rates under
gateway.usage.pricing.{default,overrides}. Cost-bearing WS responses
carrypricingConfigured: boolso clients can tell "not configured" from
"actually $0". - Security hardening rejects known plaintext credential files at startup
and unsupported encrypted config-secret envelopes at config load.
Breaking Changes
- Built-in usage pricing table removed.
usage.status,usage.cost,
usage.session,usage.providers,usage.daily, andusage.monthly
continue to track input/output tokens and request counts, but
cost_usd(and the per-periodcostfield on daily/monthly) is0.0
unless the operator configures rates under
gateway.usage.pricing.{default,overrides}. Each cost-bearing
response includes a top-levelpricingConfigured: bool. A startup
warn fires once per process when usage tracking is enabled but no
pricing rates are configured. Carapace is not a billing source of
truth — provider rates change frequently with region, batch/flex
modes, cached-token discounts, subscriptions, and OpenAI-compatible
proxies, and we will not carry stale numbers that silently mislead. - Bare and slash-form model IDs are rejected. Use canonical
provider:modelvalues:anthropic:claude-sonnet-4-6,
anthropic:claude-opus-4-7,openai:gpt-5.5,
gemini:gemini-2.5-flash,vertex:gemini-2.5-flash,
bedrock:anthropic.claude-sonnet-4-6,ollama:llama3.2,
codex:default,venice:llama-3.3-70b, orclaude-cli:default. - Classifier fallback rebound to the agent's primary model.
agents.defaults.classifier.modelpreviously defaulted to a
hard-codedgpt-4o-minithat was unroutable for non-OpenAI setups.
It now falls back to the agent's primarymodel. If your agent runs
on a strong model (e.g.anthropic:claude-opus-4-7,
openai:gpt-5.5), every classified message now hits that model.
Setgateway.classifier.modelexplicitly to a small/cheap model
likeopenai:gpt-5-nanooranthropic:claude-haiku-4-5for
cost-sensitive deployments. - Plugin sandbox defaults are snake_case.
gateway.plugins.sandbox.defaultskeys areallow_http,
allow_credentials,allow_media. The camelCase form was always
silently ignored at runtime; the schema validator now warns on it
during config load. - Removed compatibility shapes fail closed. Config aliases removed
in earlier releases, old WebSocket method aliases, and removed wire
shapes now fail validation or return method errors instead of being
accepted. - Plaintext credential files rejected at startup. Gateway startup
refuses known plaintext credential files in the state directory.
Delete those files and re-enroll via current setup/import flows. - Unsupported config-secret envelopes fail config load. Re-enter or
re-encrypt secrets as supportedenc:v2values. cara backupcovers handled sections only. Archivessessions,
config,memory,cron,tasks, andusage. Excludes OS
credential-store secrets,auth_profiles.json, managed plugin
binaries, node/device registries, and arbitrary state-dir files.
Preserve credential recovery material separately.- Direct
/hooks/agentJSON wire format is camelCase. Field names
arewakeMode,timeoutSeconds,allowUnsafeExternalContent,
veniceParameters,sessionKey. Unchanged from v0.7 in shape; this
release supersedes intermediate doc drafts that suggested
snake_case.
Migration Steps
- Create a backup before upgrading and store credential recovery
material separately:cara backup --output ./carapace-backup-v0.7.x.tar.gz
- Convert any bare or slash-form model IDs in
config.json5and
request bodies to canonicalprovider:modelform. - If you rely on cost reporting, set per-model rates under
gateway.usage.pricingbefore upgrading. Example:{ gateway: { usage: { pricing: { default: { input_per_1m_usd: 0, output_per_1m_usd: 0 }, overrides: { "anthropic:claude-sonnet-4-6": { input_per_1m_usd: 3.0, output_per_1m_usd: 15.0 } } } } } }
- If your agents rely on classifier-driven routing and you have not
setgateway.classifier.model, set it now to a small/cheap model
so every classified message does not run on your primary model. - If your config uses
gateway.plugins.sandbox.defaultswith
camelCase keys (allowHttpetc.), rename them to snake_case. - Remove any plaintext credential files reported by startup, then
re-run setup/import flows. - Re-enter or re-encrypt unsupported encrypted config secrets as
enc:v2values. - Recreate backups under the current format after the upgraded
binary is verified.
Rollback Steps
- Stop Cara.
- Reinstall the previous known-good binary (
v0.7.0pinned tag). - Restore the backup created before upgrade:
cara restore ./carapace-backup-v0.7.x.tar.gz
- Revert any v0.8.0-only config changes (added
gateway.usage.pricing
keys, snake_case sandbox key renames) before startingv0.7.0. - Re-enroll any credentials intentionally excluded from
cara backup. - Verify:
cara status --port 18789cara verify --outcome auto --port 18789cara verify --outcome autonomy --port 18789
Security
- Startup fails closed when known plaintext credential files are
detected. - Current config-secret envelopes use
enc:v2with Argon2id-derived
keys; legacy envelopes are rejected at config load. - Session integrity uses HMAC sidecars for metadata, history, and
archives; withsessions.integrity.action = "reject", tampered
state is rejected. - Encrypted sessions require
.crypto-manifestplus
CARAPACE_CONFIG_PASSWORDfor recovery. - CLI device identity uses the OS credential store when available
and falls back to{state_dir}/device-identity.json; set
CARAPACE_DEVICE_IDENTITY_STRICT=1to disable that fallback. - Bumped hickory-{net,proto,resolver} to 0.26.1 to address
RUSTSEC-2026-0119 and RUSTSEC-2026-0120 (DNS DoS).
Verification
- Verify published artifacts and Sigstore bundles:
RELEASE_TAG=v0.8.0 ./scripts/smoke/verify-release-artifacts.sh
- After upgrading, verify runtime behavior:
cara verify --outcome autocara verify --outcome autonomy
- Confirm
/health/readyis ready and logs do not report provider
reload rollback, credential-shape rejection, or unconfigured-pricing
warnings you did not expect. - If you configured
gateway.usage.pricing, issue a real request and
callusage.cost; confirmpricingConfigured: trueand a non-zero
totalCost.
Known Caveats
- Carapace does not ship per-provider price defaults.
cost_usdis
0.0until rates are configured. This is intentional — operators
know their own contracts (region, batch mode, cached-token
discounts, subscriptions) better than we can encode in a shared
table. - Hot-reload bridge runs
build_providersonspawn_blocking; the
runtime worker is no longer blocked during a provider rebuild.
Rejected reloads broadcast zero ticks onCONFIG_CHANGE_TXand
validate against the payload they carry rather than the latest
cache value. - WS
config.reloadroutes through the same provider-validation
pipeline as the file-watcher and SIGHUP paths; reloads that drop
the LLM provider returnERROR_UNAVAILABLEto the WS client. - Signal read receipts, when enabled, are sent after durable append
and before assistant reply generation/delivery. - Plugin ABI remains
carapace:plugin@1.0.0; WASM provider plugins
are identifiable but not wired into agent model selection.