Google Chat: require stable group ids (#55131)

* Google Chat: require stable group ids

* Google Chat: fail closed on deprecated room keys
This commit is contained in:
Jacob Tomlinson
2026-03-26 07:15:51 -07:00
committed by GitHub
parent 464e2c10a5
commit 11ea1f6786
2 changed files with 175 additions and 8 deletions

View File

@@ -230,4 +230,129 @@ describe("googlechat inbound access policy", () => {
expect(logVerbose).toHaveBeenCalledWith("googlechat: drop control command from users/alice");
});
it("does not match group policy by mutable space displayName when the stable id differs", async () => {
primeCommonDefaults();
createChannelPairingController.mockReturnValue({
readAllowFromStore: vi.fn(async () => []),
issueChallenge: vi.fn(),
});
resolveDmGroupAccessWithLists.mockReturnValue({
decision: "allow",
effectiveAllowFrom: [],
effectiveGroupAllowFrom: ["users/alice"],
});
resolveMentionGatingWithBypass.mockReturnValue({
shouldSkip: false,
effectiveWasMentioned: true,
});
const logVerbose = vi.fn();
const { applyGoogleChatInboundAccessPolicy } = await import("./monitor-access.js");
await expect(
applyGoogleChatInboundAccessPolicy({
account: {
accountId: "default",
config: {
groups: {
"Finance Ops": {
users: ["users/alice"],
requireMention: true,
systemPrompt: "finance-only prompt",
},
},
},
} as never,
config: {
channels: { googlechat: {} },
commands: { useAccessGroups: true },
} as never,
core: createCore() as never,
space: { name: "spaces/BBB", displayName: "Finance Ops" } as never,
message: {
annotations: [
{
type: "USER_MENTION",
userMention: { user: { name: "users/app" } },
},
],
} as never,
isGroup: true,
senderId: "users/alice",
senderName: "Alice",
senderEmail: "alice@example.com",
rawBody: "show quarter close status",
logVerbose,
}),
).resolves.toEqual({ ok: false });
expect(logVerbose).toHaveBeenCalledWith(
"Deprecated Google Chat group key detected: group routing now requires stable space ids (spaces/<spaceId>). Update channels.googlechat.groups keys: Finance Ops",
);
expect(logVerbose).toHaveBeenCalledWith(
"drop group message (deprecated mutable group key matched, space=spaces/BBB)",
);
});
it("fails closed instead of falling back to wildcard when a deprecated room key matches", async () => {
primeCommonDefaults();
resolveAllowlistProviderRuntimeGroupPolicy.mockReturnValue({
groupPolicy: "open",
providerMissingFallbackApplied: false,
});
createChannelPairingController.mockReturnValue({
readAllowFromStore: vi.fn(async () => []),
issueChallenge: vi.fn(),
});
resolveDmGroupAccessWithLists.mockReturnValue({
decision: "allow",
effectiveAllowFrom: [],
effectiveGroupAllowFrom: ["users/alice"],
});
resolveMentionGatingWithBypass.mockReturnValue({
shouldSkip: false,
effectiveWasMentioned: true,
});
const logVerbose = vi.fn();
const { applyGoogleChatInboundAccessPolicy } = await import("./monitor-access.js");
await expect(
applyGoogleChatInboundAccessPolicy({
account: {
accountId: "default",
config: {
groupPolicy: "open",
groups: {
"*": {
users: ["users/alice"],
},
"Finance Ops": {
allow: false,
users: ["users/bob"],
},
},
},
} as never,
config: {
channels: { googlechat: {} },
commands: { useAccessGroups: true },
} as never,
core: createCore() as never,
space: { name: "spaces/BBB", displayName: "Finance Ops" } as never,
message: { annotations: [] } as never,
isGroup: true,
senderId: "users/alice",
senderName: "Alice",
senderEmail: "alice@example.com",
rawBody: "show quarter close status",
logVerbose,
}),
).resolves.toEqual({ ok: false });
expect(logVerbose).toHaveBeenCalledWith(
"drop group message (deprecated mutable group key matched, space=spaces/BBB)",
);
});
});