Design issue, not a new gap — it names the pattern four existing findings on this board share, and asks for the factoring before it gets copied again.
The four instances, all on your board already
- qwen-cloud (GAP-4) — billing behind a browser cookie; you ported the Chrome cookie path to Linux and it now serves a real window.
- xAI/grok (#1 comment) — same shape: billing behind
grok.com web-session cookie; the API OAuth read returns credential_unusable structurally, and the error text misdirects to a re-signin that can't fix it.
- synthetic (GAP-3) — credential in a harness auth store rather than env; the mild variant of "the API key you'd reach for is not the surface".
- anthropic/openai (GAP-1/2 ruling) — the destructive variant: the store you'd read rotates refresh tokens, so a second reader breaks the user's sign-in. Not cookie-billed, but the same root lesson from the other side: which surface a credential lives on is a per-provider fact that the fetcher architecture has to respect.
Two of these lanes exist as working fetchers in our consumer tooling (alibaba's and xAI's), and they are structurally identical except for the response decoder (JSON vs grpc-web protobuf): passive read of an operator-captured cookie file, fail-open when the short-lived CF token (cf_clearance/__cf_bm) goes stale, recapture from a logged-in DevTools session, never touching an API-key path. That's evidence the factoring is real rather than speculative — both fetchers are available as reference implementations, offered.
The ask
Name it a kind. Roughly:
{ kind: "web_cookie",
source_file, cookie_fields[],
stale_signal: "empty-200 | 403 on short-lived CF token",
recapture: "operator devtools session" }
plus a pluggable per-provider decoder — the only genuinely per-provider part.
What this buys: the next cookie-billed provider is a manifest + decoder instead of a third hand-rolled lane; staleness handling and recapture semantics are uniform (fail-open, named cause — matching the #3 bucket discipline); and the onboarding discriminator becomes a documented step — probe whether the billing endpoint answers the API credential before assuming the auth store is the surface. Three of the four instances above were found only because a lane failed in a way that read as user-fixable ("sign in again") when it wasn't.
If the internal fetcher layer already has this seam and it's just not named, then this issue reduces to documentation — also a fine outcome; the docs sentence that prevents the fifth instance is the actual deliverable.
Design issue, not a new gap — it names the pattern four existing findings on this board share, and asks for the factoring before it gets copied again.
The four instances, all on your board already
grok.comweb-session cookie; the API OAuth read returnscredential_unusablestructurally, and the error text misdirects to a re-signin that can't fix it.Two of these lanes exist as working fetchers in our consumer tooling (alibaba's and xAI's), and they are structurally identical except for the response decoder (JSON vs grpc-web protobuf): passive read of an operator-captured cookie file, fail-open when the short-lived CF token (
cf_clearance/__cf_bm) goes stale, recapture from a logged-in DevTools session, never touching an API-key path. That's evidence the factoring is real rather than speculative — both fetchers are available as reference implementations, offered.The ask
Name it a kind. Roughly:
plus a pluggable per-provider decoder — the only genuinely per-provider part.
What this buys: the next cookie-billed provider is a manifest + decoder instead of a third hand-rolled lane; staleness handling and recapture semantics are uniform (fail-open, named cause — matching the #3 bucket discipline); and the onboarding discriminator becomes a documented step — probe whether the billing endpoint answers the API credential before assuming the auth store is the surface. Three of the four instances above were found only because a lane failed in a way that read as user-fixable ("sign in again") when it wasn't.
If the internal fetcher layer already has this seam and it's just not named, then this issue reduces to documentation — also a fine outcome; the docs sentence that prevents the fifth instance is the actual deliverable.