diff --git a/src/plugin-sdk/channel-config-helpers.test.ts b/src/plugin-sdk/channel-config-helpers.test.ts index 44c3d29385c..9921b6354c4 100644 --- a/src/plugin-sdk/channel-config-helpers.test.ts +++ b/src/plugin-sdk/channel-config-helpers.test.ts @@ -3,6 +3,7 @@ import { formatPairingApproveHint } from "../channels/plugins/helpers.js"; import { DEFAULT_ACCOUNT_ID } from "../routing/session-key.js"; import { adaptScopedAccountAccessor, + authorizeConfigWrite, createScopedAccountConfigAccessors, createScopedChannelConfigAdapter, createScopedChannelConfigBase, @@ -12,6 +13,7 @@ import { createTopLevelChannelConfigBase, createHybridChannelConfigBase, mapAllowFromEntries, + resolveChannelConfigWrites, resolveIMessageConfigAllowFrom, resolveIMessageConfigDefaultTo, resolveOptionalConfigString, @@ -113,6 +115,55 @@ describe("provider config readers", () => { }); }); +describe("config write helpers", () => { + it("matches account ids case-insensitively", () => { + const cfg = { + channels: { + telegram: { + configWrites: true, + accounts: { + Work: { configWrites: false }, + }, + }, + }, + }; + + expect(resolveChannelConfigWrites({ cfg, channelId: "telegram", accountId: "work" })).toBe( + false, + ); + }); + + it("blocks account-scoped writes when the configured account key differs only by case", () => { + const cfg = { + channels: { + telegram: { + configWrites: true, + accounts: { + Work: { configWrites: false }, + }, + }, + }, + }; + + expect( + authorizeConfigWrite({ + cfg, + target: { + kind: "account", + scope: { channelId: "telegram", accountId: "work" }, + }, + }), + ).toEqual({ + allowed: false, + reason: "target-disabled", + blockedScope: { + kind: "target", + scope: { channelId: "telegram", accountId: "work" }, + }, + }); + }); +}); + describe("adaptScopedAccountAccessor", () => { it("binds positional callback args into the shared account context object", () => { const accessor = adaptScopedAccountAccessor(({ cfg, accountId }) => ({ diff --git a/src/plugin-sdk/channel-config-helpers.ts b/src/plugin-sdk/channel-config-helpers.ts index 1ab5a31aec3..7fb7aaed091 100644 --- a/src/plugin-sdk/channel-config-helpers.ts +++ b/src/plugin-sdk/channel-config-helpers.ts @@ -6,6 +6,7 @@ import { import type { ChannelConfigAdapter } from "../channels/plugins/types.adapters.js"; import { formatCliCommand } from "../cli/command-format.js"; import type { OpenClawConfig } from "../config/config.js"; +import { resolveAccountEntry } from "../routing/account-lookup.js"; import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../routing/session-key.js"; import { normalizeStringEntries } from "../shared/string-normalization.js"; @@ -173,8 +174,7 @@ function resolveChannelAccountConfig( channelConfig: ChannelConfigWithAccounts, accountId?: string | null, ): AccountConfigWithWrites | undefined { - const normalized = normalizeAccountId(accountId); - return normalized ? channelConfig.accounts?.[normalized] : undefined; + return resolveAccountEntry(channelConfig.accounts, normalizeAccountId(accountId)); } function listConfigWriteTargetScopes(target?: ConfigWriteTarget): ConfigWriteScope[] {