## 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_providers` runs on
  `spawn_blocking` so the runtime worker is not blocked during reload.
- Built-in usage pricing table has been removed; `cost_usd` and per-period
  `cost` fields are computed only from operator-configured rates under
  `gateway.usage.pricing.{default,overrides}`. Cost-bearing WS responses
  carry `pricingConfigured: bool` so 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`, and `usage.monthly`
  continue to track input/output tokens and request counts, but
  `cost_usd` (and the per-period `cost` field on daily/monthly) is `0.0`
  unless the operator configures rates under
  `gateway.usage.pricing.{default,overrides}`. Each cost-bearing
  response includes a top-level `pricingConfigured: 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:model` values: `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`, or `claude-cli:default`.
- **Classifier fallback rebound to the agent's primary model.**
  `agents.defaults.classifier.model` previously defaulted to a
  hard-coded `gpt-4o-mini` that was unroutable for non-OpenAI setups.
  It now falls back to the agent's primary `model`. 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.
  Set `gateway.classifier.model` explicitly to a small/cheap model
  like `openai:gpt-5-nano` or `anthropic:claude-haiku-4-5` for
  cost-sensitive deployments.
- **Plugin sandbox defaults are snake_case.**
  `gateway.plugins.sandbox.defaults` keys are `allow_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 supported `enc:v2` values.
- **`cara backup` covers handled sections only.** Archives `sessions`,
  `config`, `memory`, `cron`, `tasks`, and `usage`. 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/agent` JSON wire format is camelCase.** Field names
  are `wakeMode`, `timeoutSeconds`, `allowUnsafeExternalContent`,
  `veniceParameters`, `sessionKey`. Unchanged from v0.7 in shape; this
  release supersedes intermediate doc drafts that suggested
  snake_case.

## Migration Steps

1. Create a backup before upgrading and store credential recovery
   material separately:
   - `cara backup --output ./carapace-backup-v0.7.x.tar.gz`
2. Convert any bare or slash-form model IDs in `config.json5` and
   request bodies to canonical `provider:model` form.
3. If you rely on cost reporting, set per-model rates under
   `gateway.usage.pricing` before upgrading. Example:
   ```json5
   {
     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
             }
           }
         }
       }
     }
   }
   ```
4. If your agents rely on classifier-driven routing and you have not
   set `gateway.classifier.model`, set it now to a small/cheap model
   so every classified message does not run on your primary model.
5. If your config uses `gateway.plugins.sandbox.defaults` with
   camelCase keys (`allowHttp` etc.), rename them to snake_case.
6. Remove any plaintext credential files reported by startup, then
   re-run setup/import flows.
7. Re-enter or re-encrypt unsupported encrypted config secrets as
   `enc:v2` values.
8. Recreate backups under the current format after the upgraded
   binary is verified.

## Rollback Steps

1. Stop Cara.
2. Reinstall the previous known-good binary (`v0.7.0` pinned tag).
3. Restore the backup created before upgrade:
   - `cara restore ./carapace-backup-v0.7.x.tar.gz`
4. Revert any v0.8.0-only config changes (added `gateway.usage.pricing`
   keys, snake_case sandbox key renames) before starting `v0.7.0`.
5. Re-enroll any credentials intentionally excluded from
   `cara backup`.
6. Verify:
   - `cara status --port 18789`
   - `cara verify --outcome auto --port 18789`
   - `cara verify --outcome autonomy --port 18789`

## Security

- Startup fails closed when known plaintext credential files are
  detected.
- Current config-secret envelopes use `enc:v2` with Argon2id-derived
  keys; legacy envelopes are rejected at config load.
- Session integrity uses HMAC sidecars for metadata, history, and
  archives; with `sessions.integrity.action = "reject"`, tampered
  state is rejected.
- Encrypted sessions require `.crypto-manifest` plus
  `CARAPACE_CONFIG_PASSWORD` for 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=1` to 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 auto`
  - `cara verify --outcome autonomy`
- Confirm `/health/ready` is 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
  call `usage.cost`; confirm `pricingConfigured: true` and a non-zero
  `totalCost`.

## Known Caveats

- Carapace does not ship per-provider price defaults. `cost_usd` is
  `0.0` until 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_providers` on `spawn_blocking`; the
  runtime worker is no longer blocked during a provider rebuild.
  Rejected reloads broadcast zero ticks on `CONFIG_CHANGE_TX` and
  validate against the payload they carry rather than the latest
  cache value.
- WS `config.reload` routes through the same provider-validation
  pipeline as the file-watcher and SIGHUP paths; reloads that drop
  the LLM provider return `ERROR_UNAVAILABLE` to 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.
