refactor(auth): centralize inference-credential routing in CredentialAuthority

One authority answers 'which credential may ride this request':
credential_class / manager_for / credential_for / bearer_resolver_for,
keyed by (platform, base_url). SessionCredential is an opaque type with
no production constructor, so a new call site cannot re-introduce the
session-bearer leak. Platform-scoped tests extended across all bearer
channels (session, aux, summary, subagent override).

Verified: cargo check --workspace --all-targets clean; kigi-shell and
kigi-tui suites green (6611+ tests).
This commit is contained in:
2026-07-22 15:12:00 -04:00
parent 2d00a4e6e6
commit 48d89c7830
35 changed files with 3158 additions and 1099 deletions
@@ -980,10 +980,21 @@ pub(crate) async fn spawn_session_actor(
}
};
let doom_loop_recovery = effective_config.resolve_doom_loop_recovery();
let session_model_id_for_actor = session_model_id.clone();
let session = Arc::new_cyclic(|weak: &std::sync::Weak<SessionActor>| SessionActor {
session_info: session_info.clone(),
auth_method_id,
model_auth_facts: std::cell::RefCell::new(None),
// H4: seed the session's OWN selected catalog key from the model it was
// spawned with, resolved through the picker's lookup. Never the
// process-global `current_model_id()`. H-c: the rule lives in
// `selected_catalog_key_for_spawn` so it is covered by a test.
selected_catalog_key: std::cell::RefCell::new(
crate::agent::models::selected_catalog_key_for_spawn(
&models_manager.models(),
&session_model_id_for_actor,
),
),
attribution_callback,
auth_manager,
state,