mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-31 04:12:10 +03:00
fix(vertex): add generative-language scope so SA-JSON model discovery works (#3922)
Integrated into release/v3.8.26
This commit is contained in:
@@ -13,6 +13,18 @@ interface ServiceAccount {
|
||||
|
||||
const TOKEN_CACHE = new Map<string, { token: string; expiresAt: number }>();
|
||||
|
||||
// OAuth scopes minted into the Vertex SA access token.
|
||||
// - cloud-platform authorizes Vertex AI (aiplatform.googleapis.com) for chat/image execution.
|
||||
// - generative-language.retriever is ADDITIONALLY required so model discovery can list the live
|
||||
// catalog from generativelanguage.googleapis.com/v1beta/models — without it that listing returns
|
||||
// 403 ACCESS_TOKEN_SCOPE_INSUFFICIENT and discovery silently falls back to the static ~10-model
|
||||
// registry list. The extra scope is harmless for execution (cloud-platform still present) and for
|
||||
// projects where it isn't needed (the mint never validates scope availability).
|
||||
export const VERTEX_OAUTH_SCOPES = [
|
||||
"https://www.googleapis.com/auth/cloud-platform",
|
||||
"https://www.googleapis.com/auth/generative-language.retriever",
|
||||
] as const;
|
||||
|
||||
export function parseSAFromApiKey(apiKey: string): ServiceAccount {
|
||||
try {
|
||||
return JSON.parse(apiKey);
|
||||
@@ -67,7 +79,7 @@ export async function getAccessToken(sa: ServiceAccount): Promise<string> {
|
||||
aud: "https://oauth2.googleapis.com/token",
|
||||
iat: now,
|
||||
exp: now + 3600,
|
||||
scope: "https://www.googleapis.com/auth/cloud-platform",
|
||||
scope: VERTEX_OAUTH_SCOPES.join(" "),
|
||||
})
|
||||
.setProtectedHeader({ alg: "RS256", kid: sa.private_key_id })
|
||||
.sign(privateKey);
|
||||
|
||||
31
tests/unit/vertex-oauth-scopes.test.ts
Normal file
31
tests/unit/vertex-oauth-scopes.test.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
// #3922 — the Vertex SA access token must carry BOTH cloud-platform (chat/image
|
||||
// execution on aiplatform.googleapis.com) AND generative-language.retriever
|
||||
// (live model discovery on generativelanguage.googleapis.com). Dropping the
|
||||
// second scope makes discovery return 403 ACCESS_TOKEN_SCOPE_INSUFFICIENT and
|
||||
// silently fall back to the static ~10-model registry list. This guards both.
|
||||
const { VERTEX_OAUTH_SCOPES } = await import("../../open-sse/executors/vertex.ts");
|
||||
|
||||
test("Vertex OAuth scopes include cloud-platform (execution)", () => {
|
||||
assert.ok(
|
||||
VERTEX_OAUTH_SCOPES.includes("https://www.googleapis.com/auth/cloud-platform"),
|
||||
"cloud-platform scope is required for Vertex AI execution"
|
||||
);
|
||||
});
|
||||
|
||||
test("Vertex OAuth scopes include generative-language.retriever (discovery)", () => {
|
||||
assert.ok(
|
||||
VERTEX_OAUTH_SCOPES.includes("https://www.googleapis.com/auth/generative-language.retriever"),
|
||||
"generative-language.retriever scope is required for live model discovery"
|
||||
);
|
||||
});
|
||||
|
||||
test("Vertex OAuth scopes serialize as a space-delimited string for the JWT", () => {
|
||||
const serialized = VERTEX_OAUTH_SCOPES.join(" ");
|
||||
assert.equal(
|
||||
serialized,
|
||||
"https://www.googleapis.com/auth/cloud-platform https://www.googleapis.com/auth/generative-language.retriever"
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user