fix: bind Gemini CLI epochs to profile homes

This commit is contained in:
Shakker
2026-06-15 19:48:29 +01:00
committed by Shakker
parent 625085187e
commit d53e559ae7
2 changed files with 69 additions and 2 deletions

View File

@@ -112,6 +112,71 @@ describe("resolveCliAuthEpoch", () => {
});
});
it("separates Gemini CLI OAuth profile epochs by profile id", async () => {
let access = "access-a";
let refresh = "refresh-a";
const store: AuthProfileStore = {
version: 1,
profiles: {
"google-gemini-cli:primary": {
type: "oauth",
provider: "google-gemini-cli",
access,
refresh,
expires: 1,
email: "user@example.test",
accountId: "google-account-1",
projectId: "project-1",
},
"google-gemini-cli:renamed": {
type: "oauth",
provider: "google-gemini-cli",
access,
refresh,
expires: 1,
email: "user@example.test",
accountId: "google-account-1",
projectId: "project-1",
},
},
};
setCliAuthEpochTestDeps({
readGeminiCliCredentialsCached: () => null,
loadAuthProfileStoreForRuntime: () => store,
});
const primary = await resolveCliAuthEpoch({
provider: "google-gemini-cli",
agentDir: "/agents/main/agent",
authProfileId: "google-gemini-cli:primary",
skipLocalCredential: true,
});
access = "access-b";
refresh = "refresh-b";
store.profiles["google-gemini-cli:primary"] = {
...store.profiles["google-gemini-cli:primary"]!,
access,
refresh,
expires: 2,
};
const primaryAfterRefresh = await resolveCliAuthEpoch({
provider: "google-gemini-cli",
agentDir: "/agents/main/agent",
authProfileId: "google-gemini-cli:primary",
skipLocalCredential: true,
});
const renamed = await resolveCliAuthEpoch({
provider: "google-gemini-cli",
agentDir: "/agents/main/agent",
authProfileId: "google-gemini-cli:renamed",
skipLocalCredential: true,
});
expectCliAuthEpoch(primary);
expect(primaryAfterRefresh).toBe(primary);
expect(renamed).not.toBe(primary);
});
it("keeps identity-less claude cli oauth epochs stable across token changes", async () => {
let access = "access-a";
let refresh = "refresh-a";

View File

@@ -32,7 +32,9 @@ const defaultCliAuthEpochDeps: CliAuthEpochDeps = {
const cliAuthEpochDeps: CliAuthEpochDeps = { ...defaultCliAuthEpochDeps };
/** Version salt for CLI auth epoch encoding semantics. */
export const CLI_AUTH_EPOCH_VERSION = 5;
export const CLI_AUTH_EPOCH_VERSION = 6;
const GEMINI_CLI_PROVIDER_ID = "google-gemini-cli";
/** Overrides credential readers for auth-epoch unit tests. */
export function setCliAuthEpochTestDeps(overrides: Partial<CliAuthEpochDeps>): void {
@@ -159,7 +161,7 @@ function encodeAuthProfileEpochPart(
credential: AuthProfileCredential,
): string {
const credentialHash = hashCliAuthEpochPart(encodeAuthProfileCredential(credential));
if (hasOAuthAccountIdentity(credential)) {
if (hasOAuthAccountIdentity(credential) && credential.provider !== GEMINI_CLI_PROVIDER_ID) {
return `profile:oauth-identity:${credentialHash}`;
}
return `profile:${authProfileId}:${credentialHash}`;