Files
openclaw/src/secrets/runtime-telegram-token-inheritance.test.ts
2026-04-06 08:18:40 +01:00

305 lines
9.3 KiB
TypeScript

import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
import type { AuthProfileStore } from "../agents/auth-profiles.js";
import type { OpenClawConfig } from "../config/config.js";
import { createEmptyPluginRegistry } from "../plugins/registry.js";
import { setActivePluginRegistry } from "../plugins/runtime.js";
vi.mock("../channels/plugins/bootstrap-registry.js", async () => {
const telegramSecrets = await import("../../extensions/telegram/src/secret-contract.ts");
return {
getBootstrapChannelPlugin: (id: string) =>
id === "telegram"
? {
secrets: {
collectRuntimeConfigAssignments: telegramSecrets.collectRuntimeConfigAssignments,
},
}
: undefined,
};
});
function asConfig(value: unknown): OpenClawConfig {
return value as OpenClawConfig;
}
let clearConfigCache: typeof import("../config/config.js").clearConfigCache;
let clearRuntimeConfigSnapshot: typeof import("../config/config.js").clearRuntimeConfigSnapshot;
let clearSecretsRuntimeSnapshot: typeof import("./runtime.js").clearSecretsRuntimeSnapshot;
let prepareSecretsRuntimeSnapshot: typeof import("./runtime.js").prepareSecretsRuntimeSnapshot;
function loadAuthStoreWithProfiles(profiles: AuthProfileStore["profiles"]): AuthProfileStore {
return {
version: 1,
profiles,
};
}
describe("secrets runtime snapshot telegram token inheritance", () => {
beforeAll(async () => {
({ clearConfigCache, clearRuntimeConfigSnapshot } = await import("../config/config.js"));
({ clearSecretsRuntimeSnapshot, prepareSecretsRuntimeSnapshot } = await import("./runtime.js"));
});
afterEach(() => {
setActivePluginRegistry(createEmptyPluginRegistry());
clearSecretsRuntimeSnapshot();
clearRuntimeConfigSnapshot();
clearConfigCache();
});
it("fails when enabled channel surfaces contain unresolved refs", async () => {
await expect(
prepareSecretsRuntimeSnapshot({
config: asConfig({
channels: {
telegram: {
botToken: {
source: "env",
provider: "default",
id: "MISSING_ENABLED_TELEGRAM_TOKEN",
},
accounts: {
work: {
enabled: true,
},
},
},
},
}),
env: {},
agentDirs: ["/tmp/openclaw-agent-main"],
loadAuthStore: () => loadAuthStoreWithProfiles({}),
}),
).rejects.toThrow('Environment variable "MISSING_ENABLED_TELEGRAM_TOKEN" is missing or empty.');
});
it("fails when default Telegram account can inherit an unresolved top-level token ref", async () => {
await expect(
prepareSecretsRuntimeSnapshot({
config: asConfig({
channels: {
telegram: {
botToken: {
source: "env",
provider: "default",
id: "MISSING_ENABLED_TELEGRAM_TOKEN",
},
accounts: {
default: {
enabled: true,
},
},
},
},
}),
env: {},
agentDirs: ["/tmp/openclaw-agent-main"],
loadAuthStore: () => loadAuthStoreWithProfiles({}),
}),
).rejects.toThrow('Environment variable "MISSING_ENABLED_TELEGRAM_TOKEN" is missing or empty.');
});
it("treats top-level Telegram token as inactive when all enabled accounts override it", async () => {
const snapshot = await prepareSecretsRuntimeSnapshot({
config: asConfig({
channels: {
telegram: {
botToken: {
source: "env",
provider: "default",
id: "UNUSED_TELEGRAM_BASE_TOKEN",
},
accounts: {
work: {
enabled: true,
botToken: {
source: "env",
provider: "default",
id: "TELEGRAM_WORK_TOKEN",
},
},
disabled: {
enabled: false,
},
},
},
},
}),
env: {
TELEGRAM_WORK_TOKEN: "telegram-work-token",
},
agentDirs: ["/tmp/openclaw-agent-main"],
loadAuthStore: () => loadAuthStoreWithProfiles({}),
});
expect(snapshot.config.channels?.telegram?.accounts?.work?.botToken).toBe(
"telegram-work-token",
);
expect(snapshot.config.channels?.telegram?.botToken).toEqual({
source: "env",
provider: "default",
id: "UNUSED_TELEGRAM_BASE_TOKEN",
});
expect(snapshot.warnings.map((warning) => warning.path)).toContain(
"channels.telegram.botToken",
);
});
it("treats Telegram account overrides as enabled when account.enabled is omitted", async () => {
await expect(
prepareSecretsRuntimeSnapshot({
config: asConfig({
channels: {
telegram: {
enabled: true,
accounts: {
inheritedEnabled: {
botToken: {
source: "env",
provider: "default",
id: "MISSING_INHERITED_TELEGRAM_ACCOUNT_TOKEN",
},
},
},
},
},
}),
env: {},
agentDirs: ["/tmp/openclaw-agent-main"],
loadAuthStore: () => loadAuthStoreWithProfiles({}),
}),
).rejects.toThrow(
'Environment variable "MISSING_INHERITED_TELEGRAM_ACCOUNT_TOKEN" is missing or empty.',
);
});
it("treats top-level Telegram botToken refs as active when account botToken is blank", async () => {
const snapshot = await prepareSecretsRuntimeSnapshot({
config: asConfig({
channels: {
telegram: {
botToken: {
source: "env",
provider: "default",
id: "TELEGRAM_BASE_TOKEN",
},
accounts: {
work: {
enabled: true,
botToken: "",
},
},
},
},
}),
env: {
TELEGRAM_BASE_TOKEN: "telegram-base-token",
},
agentDirs: ["/tmp/openclaw-agent-main"],
loadAuthStore: () => loadAuthStoreWithProfiles({}),
});
expect(snapshot.config.channels?.telegram?.botToken).toBe("telegram-base-token");
expect(snapshot.config.channels?.telegram?.accounts?.work?.botToken).toBe("");
expect(snapshot.warnings.map((warning) => warning.path)).not.toContain(
"channels.telegram.botToken",
);
});
it("treats Telegram webhookSecret refs as inactive when webhook mode is not configured", async () => {
const snapshot = await prepareSecretsRuntimeSnapshot({
config: asConfig({
channels: {
telegram: {
webhookSecret: {
source: "env",
provider: "default",
id: "MISSING_TELEGRAM_WEBHOOK_SECRET",
},
accounts: {
work: {
enabled: true,
},
},
},
},
}),
env: {},
agentDirs: ["/tmp/openclaw-agent-main"],
loadAuthStore: () => loadAuthStoreWithProfiles({}),
});
expect(snapshot.config.channels?.telegram?.webhookSecret).toEqual({
source: "env",
provider: "default",
id: "MISSING_TELEGRAM_WEBHOOK_SECRET",
});
expect(snapshot.warnings.map((warning) => warning.path)).toContain(
"channels.telegram.webhookSecret",
);
});
it("treats Telegram top-level botToken refs as inactive when tokenFile is configured", async () => {
const snapshot = await prepareSecretsRuntimeSnapshot({
config: asConfig({
channels: {
telegram: {
tokenFile: "/tmp/telegram-bot-token",
botToken: {
source: "env",
provider: "default",
id: "MISSING_TELEGRAM_BOT_TOKEN",
},
},
},
}),
env: {},
agentDirs: ["/tmp/openclaw-agent-main"],
loadAuthStore: () => loadAuthStoreWithProfiles({}),
});
expect(snapshot.config.channels?.telegram?.botToken).toEqual({
source: "env",
provider: "default",
id: "MISSING_TELEGRAM_BOT_TOKEN",
});
expect(snapshot.warnings.map((warning) => warning.path)).toContain(
"channels.telegram.botToken",
);
});
it("treats Telegram account botToken refs as inactive when account tokenFile is configured", async () => {
const snapshot = await prepareSecretsRuntimeSnapshot({
config: asConfig({
channels: {
telegram: {
accounts: {
work: {
enabled: true,
tokenFile: "/tmp/telegram-work-bot-token",
botToken: {
source: "env",
provider: "default",
id: "MISSING_TELEGRAM_WORK_BOT_TOKEN",
},
},
},
},
},
}),
env: {},
agentDirs: ["/tmp/openclaw-agent-main"],
loadAuthStore: () => loadAuthStoreWithProfiles({}),
});
expect(snapshot.config.channels?.telegram?.accounts?.work?.botToken).toEqual({
source: "env",
provider: "default",
id: "MISSING_TELEGRAM_WORK_BOT_TOKEN",
});
expect(snapshot.warnings.map((warning) => warning.path)).toContain(
"channels.telegram.accounts.work.botToken",
);
});
});