Files
clawX/harness/specs/tasks/provider-switch-api-protocol-validation.md

71 lines
4.2 KiB
Markdown

---
id: provider-switch-api-protocol-validation
title: Reject invalid OpenClaw api protocol writes and self-heal stale entries
scenario: gateway-backend-communication
taskType: runtime-bridge
intent: Prevent ClawX from writing models.providers.*.api values outside the OpenClaw allowlist into openclaw.json, and opportunistically prune pre-existing invalid entries when the user switches default provider so a clean switch can rescue the Gateway from Invalid-config restart loops.
touchedAreas:
- harness/specs/tasks/provider-switch-api-protocol-validation.md
- electron/shared/providers/registry.ts
- electron/shared/providers/types.ts
- electron/utils/openclaw-auth.ts
- electron/services/providers/provider-runtime-sync.ts
- tests/unit/openclaw-auth.test.ts
expectedUserBehavior:
- Selecting OpenRouter (or any built-in provider) as default writes a Gateway-valid api protocol so Gateway reload stays healthy.
- Attempting to save a provider whose api protocol is not in the OpenClaw allowlist surfaces an actionable error in the UI without polluting openclaw.json or triggering a Gateway restart.
- Switching default to a healthy provider after a prior corrupt openclaw.json (legacy api=openrouter typo) self-heals the file before the next reload signal so the Gateway boots cleanly.
requiredProfiles:
- fast
- comms
requiredRules:
- active-config-guards
- backend-communication-boundary
- renderer-main-boundary
- api-client-transport-policy
requiredTests:
- tests/unit/openclaw-auth.test.ts
acceptance:
- electron/shared/providers/types.ts exports OPENCLAW_API_PROTOCOLS as the single source of truth for openclaw.json api values, plus assertValidApiProtocol and InvalidApiProtocolError.
- setOpenClawDefaultModel, setOpenClawDefaultModelWithOverride, syncProviderConfigToOpenClaw, and upsertOpenClawProviderEntry all invoke assertValidApiProtocol before any write to openclaw.json.
- syncDefaultProviderToRuntime calls pruneInvalidApiProviderEntries before the OAuth and non-OAuth branches so a switch to any healthy provider drops legacy invalid models.providers entries.
- Renderer does not add new direct ipcRenderer or Gateway HTTP calls.
- Unit tests cover both the rejection path (no file write on invalid api) and the self-heal path (legacy entries pruned while valid ones remain).
docs:
required: false
---
## Background
A historical bug in [electron/shared/providers/registry.ts](electron/shared/providers/registry.ts) set the OpenRouter
`providerConfig.api` to the literal string `'openrouter'`, which is not in OpenClaw's allowed
`api` enum (`openai-completions | openai-responses | openai-codex-responses | anthropic-messages |
google-generative-ai | github-copilot | bedrock-converse-stream | ollama | azure-openai-responses`).
When the user selected OpenRouter as their default provider, ClawX wrote that invalid value into
`~/.openclaw/openclaw.json` and then sent SIGUSR1 to the running Gateway. The Gateway's
`assertValidGatewayStartupConfigSnapshot` rejected the config, tore down all channels (close code
1012), entered the `startup_failed` state, but kept the OS process alive. The Main process then
spun for ~8 minutes inside `waitForGatewayReady` before doctor self-heal kicked in.
Switching to MiniMax during the broken window did not help, because the runtime-sync path only
appended the MiniMax block and left the broken OpenRouter entry untouched.
## Scope
- Fix the registry typo so OpenRouter writes `api: 'openai-completions'`, matching every other
OpenAI-compatible built-in provider.
- Add a single source of truth for the allowed api protocols and a runtime guard at every write
site (`setOpenClawDefaultModel`, `setOpenClawDefaultModelWithOverride`,
`syncProviderConfigToOpenClaw`, plus defense-in-depth inside `upsertOpenClawProviderEntry`).
- Add a self-heal helper that prunes any `models.providers.*` entry whose `api` is outside the
allowlist, and invoke it at the top of `syncDefaultProviderToRuntime` so a clean switch rescues
legacy corrupted configs.
## Out of scope
- Gateway-side `waitForGatewayReady` short-circuit when the owned process is stuck in
`startup_failed`.
- Renderer pre-flight validation UI surface beyond the existing route-level error handling.
- README updates (no user-visible UI change in this task).