This commit is contained in:
2026-07-22 11:08:54 -04:00
parent 422e241e13
commit 2d00a4e6e6
19 changed files with 1955 additions and 296 deletions
+40
View File
@@ -259,6 +259,46 @@ edges stay deterministic Rust. The harness appends a terminal
token (`resolve_generic_oauth_tokens`, refreshed on expiry) and routes
`platform.oauth().is_some()``platform.base_url()` (kimi-code alone →
`proxy_url()`). Tokens/codes/verifiers are NEVER logged.
- INFERENCE-AUTH INVARIANT (security): a SESSION bearer may ride a request ONLY
when the endpoint's platform `uses_oauth()``kimi-code` (the primary
session) or one of the four subscription-OAuth platforms (their OWN pooled
`AuthManager` via `oauth_registry::manager_for_model`, which is why they keep
a live `bearer_resolver` and mid-session refresh despite non-first-party base
URLs). Every API-key registry platform is refused, because
`manager_for_model` falls through to the PRIMARY manager for a non-OAuth key
and `SamplingClient::post` REPLACES the request's auth header from the
resolver. A model with NO platform (a bare slug / `[model.*]` entry) is
decided by the ENDPOINT — `util::is_effective_coding_endpoint_url` (the
effective `KIGI_CODE_BASE_URL` deployment, loopback dev proxies, and the
compiled production endpoint), never a blanket allow: BYOK is
`has_own_credentials()`, which probes `std::env::var` at call time, so a
`[model.*]` block with an unset `env_key` classifies `NotByok`. Both are
`auth_method::platform_takes_session_credential(platform, base_url)`, the
single predicate enforced at BOTH channels that reach the wire — the
`bearer_resolver` (outer term of `auth_method::session_token_auth_gate`) and
the `api_key` (`MvpAgent::session_token_for_model`,
`oauth_registry::session_key_for_endpoint` for the aux / summary /
subagent-override paths, and `sampler_turn::aux_bearer_resolver` for the
stamped aux configs).
- MODEL→PLATFORM LOOKUP (security): `SamplingConfig::model` is the BARE routing
slug, and duplicate slugs across platforms are BY DESIGN — an API-key platform
and its subscription-OAuth twin list identical ids (`xai`/`xai-grok`,
`anthropic`/`claude-pro-max`, `openai`/`openai-codex`), with the API-key
platform FIRST in `PlatformId::ALL`. The auth layer therefore resolves the
platform from the catalog KEY the picker selected
(`ModelsManager::current_model_id`), via
`agent::models::managed_key_for_slug`/`platform_for_slug`; anything else falls
back to the picker's own `resolve_catalog_key`, and
`config::find_model_by_id`'s slug scan takes the LAST match so the two can
never disagree. Resolving the wrong twin costs the OAuth platform its live
`bearer_resolver` (unrecoverable 401 ~1h in), its Messages adaptation and its
Copilot/Codex identity headers.
- CATALOG VISIBILITY: `platform_wire_model_to_entry` stamps
`supported_in_api = platform != KimiCode`. `ModelInfo::visible_for_auth`
reads only the PRIMARY manager's auth mode, so gating the other OAuth
platforms on it would hide every model from a user who signed in with ONLY a
Claude Pro/Max, ChatGPT, Copilot, or Grok subscription. Only `kimi-code`
rides the primary session, so only it may be gated on it.
- Model metadata (context window, thinking levels) comes from the provider
wire when served; metadata-poor listings are enriched from models.dev
(`kigi-models/src/enrichment.rs` — bundled raw snapshot regenerated by