Allow provider selection for gateway OAuth reads and logins (#59819)

## Why

Gateway OAuth reads and logins previously used only the current provider, preventing clients from authorizing another configured provider without changing the default.

## What changed

- Add optional `modelProvider` params to `account/gatewayOAuth/read` and `account/gatewayOAuth/login`, preserving current-provider behavior for omitted or null params and selectors.
- Validate explicit providers against current managed policy without changing the default or any thread's provider.
- Retain readiness state across providers and send `account/gatewayOAuth/changed` notifications for every configured provider sharing the changed credential.
- Update protocol schemas, TypeScript types, Python models, and documentation.

## Testing

Add coverage for non-default provider login, retained readiness when alternating providers, notifications for shared credentials without starting login, and legacy TypeScript request compatibility.

GitOrigin-RevId: cfd472c322b821fe36b8c133a8de774f4ba48534
This commit is contained in:
Abhinav
2026-11-06 04:02:11 +00:00
committed by copyberry
parent a142c90e26
commit aece559654
22 changed files with 561 additions and 71 deletions
+15 -1
View File
@@ -2206,6 +2206,16 @@ mod tests {
"params?: GetAccountRateLimitsParams | undefined, }"
);
assert!(client_request_ts.contains(LEGACY_ACCOUNT_RATE_LIMITS_REQUEST));
const LEGACY_GATEWAY_READ_REQUEST: &str = concat!(
"{ \"method\": \"account/gatewayOAuth/read\", id: RequestId, ",
"params?: GatewayOAuthReadParams | null | undefined, }"
);
assert!(client_request_ts.contains(LEGACY_GATEWAY_READ_REQUEST));
const LEGACY_GATEWAY_LOGIN_REQUEST: &str = concat!(
"{ \"method\": \"account/gatewayOAuth/login\", id: RequestId, ",
"params?: GatewayOAuthLoginParams | null | undefined, }"
);
assert!(client_request_ts.contains(LEGACY_GATEWAY_LOGIN_REQUEST));
let account_usage_response_ts = std::str::from_utf8(
fixture_tree
.get(Path::new("v2/GetAccountTokenUsageResponse.ts"))
@@ -2290,18 +2300,22 @@ mod tests {
});
let contents = std::str::from_utf8(contents)?;
// Both stable usage RPCs originally required `params: undefined`. Preserve that
// These existing RPCs originally required `params: undefined`. Preserve that
// source compatibility only for these exact envelopes, not arbitrary new fields.
let checked_contents = if path == Path::new("ClientRequest.ts") {
contents
.replace(LEGACY_ACCOUNT_USAGE_REQUEST, "")
.replace(LEGACY_ACCOUNT_RATE_LIMITS_REQUEST, "")
.replace(LEGACY_GATEWAY_READ_REQUEST, "")
.replace(LEGACY_GATEWAY_LOGIN_REQUEST, "")
} else {
contents.to_owned()
};
if checked_contents.contains("| undefined") {
undefined_offenders.push(path.clone());
}
// The exact gateway envelopes above also accept legacy null params.
let contents = checked_contents.as_str();
const SKIP_PREFIXES: &[&str] = &[
"const ",