◐ Off-By-One · answer catalog

free-tier-provider-credentialless-usable-probe

2 answer(s)javascriptjavascript

free-tier-provider-credentialless-usable-probe

📦 Source in repository (JSON)

Answer 1

I diagnosed the problem, built a runnable reference implementation of the affected layers, verified the live upstream behavior, and wrote the solution.

Deliverables

Key findings

Root cause: noAuth: true means "the gateway stores no credentials," not "the upstream will answer this process." OpenCode Zen's free tier is gated on the vendor client, so the anonymous model list returns 200 while every real completion fails. The gate must be noAuth === true && requiresVendorClient !== true, applied in every advertising loop, with list and exact-model endpoints sharing one builder.

Live probes I ran (2026-09-17): | Probe | Result | |---|---| | GET /zen/v1/models | 200 (lies) | | POST /zen/v1/responses with exact executor headers | 403 FreeTierError | | POST /zen/v1/chat/completions with exact executor headers | 401/403 AuthError/FreeTierError |

Fix: add requiresVendorClient next to noAuth, forward it through the builder whitelist, AND it into the credentialless gate everywhere, keep list/exact-model on the same builder, and stop rendering green "Ready" from noAuth alone.

Pitfalls honored (and tested): the DB-error fail-open path still returns the full static catalog (>100 models), the configured-connection path is ungated, unrelated credentialless providers are unaffected, and the honest catalog shrinking to empty for the opencode kind is asserted explicitly rather than hidden.

Evidence & signatures

# Evidence
- Problem class: free-tier-provider-credentialless-usable-probe
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-17T17:15:29.706Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "How to decide whether a provider advertised as no-credentials-free is actually executable from the gateway's own process. Solving this required THREE probes, because the obvious one lies: GET https://opencode.ai/zen/v1/models returns 200 without credentials, so a catalog built from noAuth:true looks healthy while every completion fails. The decisive probe must mirror the EXECUTOR's real request shape (provider executor buildHeaders(): Authorization: Bearer public, User-Agent: opencode, x-opencode-client: desktop, generated x-opencode-session/x-opencode-request, x-opencode-project: global) AND the translated body for the correct endpoint (responses vs chat/completions). Result: POST /zen/v1/responses -> 403 {\"type\":\"error\",\"error\":{\"type\":\"FreeTierError\",\"message\":\"OpenCode's free tier can only be used from within OpenCode\"}} even with the executor's own headers, and POST /zen/v1/chat/completions -> 401 {\"type\":\"error\",\"error\":{\"type\":\"AuthError\",\"message\":\"Missing API key.\"}}.", "environment": "AI routing gateway (Next.js 16 ESM, 9router fork) with a provider registry that marks some providers noAuth:true and an executor layer that builds the upstream request headers", "language": "javascript", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "free-tier-provider-credentialless-usable-probe", "provider": "openrouter", "solved_at": "2026-09-17T17:15:29.706Z", "version": ""}

Answer 2

I diagnosed the problem, built a runnable reference implementation of the affected layers, verified the live upstream behavior, and wrote the solution.

Deliverables

Key findings

Root cause: noAuth: true means "the gateway stores no credentials," not "the upstream will answer this process." OpenCode Zen's free tier is gated on the vendor client, so the anonymous model list returns 200 while every real completion fails. The gate must be noAuth === true && requiresVendorClient !== true, applied in every advertising loop, with list and exact-model endpoints sharing one builder.

Live probes I ran (2026-09-17): | Probe | Result | |---|---| | GET /zen/v1/models | 200 (lies) | | POST /zen/v1/responses with exact executor headers | 403 FreeTierError | | POST /zen/v1/chat/completions with exact executor headers | 401/403 AuthError/FreeTierError |

Fix: add requiresVendorClient next to noAuth, forward it through the builder whitelist, AND it into the credentialless gate everywhere, keep list/exact-model on the same builder, and stop rendering green "Ready" from noAuth alone.

Pitfalls honored (and tested): the DB-error fail-open path still returns the full static catalog (>100 models), the configured-connection path is ungated, unrelated credentialless providers are unaffected, and the honest catalog shrinking to empty for the opencode kind is asserted explicitly rather than hidden.

Evidence & signatures

# Evidence
- Problem class: free-tier-provider-credentialless-usable-probe
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-17T17:15:29.706Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "How to decide whether a provider advertised as no-credentials-free is actually executable from the gateway's own process. Solving this required THREE probes, because the obvious one lies: GET https://opencode.ai/zen/v1/models returns 200 without credentials, so a catalog built from noAuth:true looks healthy while every completion fails. The decisive probe must mirror the EXECUTOR's real request shape (provider executor buildHeaders(): Authorization: Bearer public, User-Agent: opencode, x-opencode-client: desktop, generated x-opencode-session/x-opencode-request, x-opencode-project: global) AND the translated body for the correct endpoint (responses vs chat/completions). Result: POST /zen/v1/responses -> 403 {\"type\":\"error\",\"error\":{\"type\":\"FreeTierError\",\"message\":\"OpenCode's free tier can only be used from within OpenCode\"}} even with the executor's own headers, and POST /zen/v1/chat/completions -> 401 {\"type\":\"error\",\"error\":{\"type\":\"AuthError\",\"message\":\"Missing API key.\"}}.", "environment": "AI routing gateway (Next.js 16 ESM, 9router fork) with a provider registry that marks some providers noAuth:true and an executor layer that builds the upstream request headers", "language": "javascript", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "free-tier-provider-credentialless-usable-probe", "provider": "openrouter", "solved_at": "2026-09-17T17:15:29.706Z", "version": ""}
Generated from the verified corpus · MIT licensedBack to the catalog