From 58c9d4a2b22fe7e68c493c16109a520c7f0d0621 Mon Sep 17 00:00:00 2001 From: Gustavo Madeira Santana Date: Sun, 19 Apr 2026 15:40:16 -0400 Subject: [PATCH] fix(matrix): narrow live allowlist reload reads --- .../matrix/src/matrix/account-config.ts | 25 +++++++++++ .../matrix/src/matrix/monitor/handler.test.ts | 41 +++++++++++++++++++ .../matrix/src/matrix/monitor/handler.ts | 8 ++-- 3 files changed, 70 insertions(+), 4 deletions(-) diff --git a/extensions/matrix/src/matrix/account-config.ts b/extensions/matrix/src/matrix/account-config.ts index 0297c625c86..2ce95a0f679 100644 --- a/extensions/matrix/src/matrix/account-config.ts +++ b/extensions/matrix/src/matrix/account-config.ts @@ -148,3 +148,28 @@ export function resolveMatrixAccountConfig(params: { ...(rooms ? { rooms } : {}), }; } + +export function resolveMatrixAccountAllowlistConfig(params: { + cfg: CoreConfig; + accountId?: string | null; +}): { + dmAllowFrom?: NonNullable["allowFrom"]; + groupAllowFrom?: MatrixConfig["groupAllowFrom"]; +} { + const accountId = normalizeAccountId(params.accountId); + const base = resolveMatrixBaseConfig(params.cfg); + const accountConfig = findMatrixAccountConfig(params.cfg, accountId); + const accountDm = accountConfig?.dm; + + let dmAllowFrom = base.dm?.allowFrom; + if (accountDm && Object.hasOwn(accountDm, "allowFrom")) { + dmAllowFrom = accountDm.allowFrom; + } + + let groupAllowFrom = base.groupAllowFrom; + if (accountConfig && Object.hasOwn(accountConfig, "groupAllowFrom")) { + groupAllowFrom = accountConfig.groupAllowFrom; + } + + return { dmAllowFrom, groupAllowFrom }; +} diff --git a/extensions/matrix/src/matrix/monitor/handler.test.ts b/extensions/matrix/src/matrix/monitor/handler.test.ts index e574136d201..2b278e0b1be 100644 --- a/extensions/matrix/src/matrix/monitor/handler.test.ts +++ b/extensions/matrix/src/matrix/monitor/handler.test.ts @@ -1841,6 +1841,47 @@ describe("matrix monitor handler live allowlist reload", () => { expect(dispatchReplyFromConfig).toHaveBeenCalledTimes(1); }); + it("uses account-scoped live dm.allowFrom overrides", async () => { + const dispatchReplyFromConfig = createDispatchReplyFromConfig(); + const cfg = { + channels: { + matrix: { + dm: { allowFrom: ["@base:example.org"] }, + accounts: { + ops: { + dm: { allowFrom: ["@alice:example.org"] }, + }, + }, + }, + }, + }; + const { handler } = createMatrixHandlerTestHarness({ + cfg, + accountId: "ops", + dmPolicy: "allowlist", + isDirectMessage: true, + allowFrom: ["@alice:example.org"], + allowFromResolvedEntries: [{ input: "@alice:example.org", id: "@alice:example.org" }], + dispatchReplyFromConfig, + }); + + await sendLiveAllowlistMessage(handler, { + eventId: "$dm-account-before", + sender: "@alice:example.org", + body: "hello", + }); + expect(dispatchReplyFromConfig).toHaveBeenCalledTimes(1); + + cfg.channels.matrix.accounts.ops.dm.allowFrom = []; + await sendLiveAllowlistMessage(handler, { + eventId: "$dm-account-after", + sender: "@alice:example.org", + body: "hello again", + }); + + expect(dispatchReplyFromConfig).toHaveBeenCalledTimes(1); + }); + it("keeps startup-resolved display names only while the raw input remains configured", async () => { const dispatchReplyFromConfig = createDispatchReplyFromConfig(); const cfg = { diff --git a/extensions/matrix/src/matrix/monitor/handler.ts b/extensions/matrix/src/matrix/monitor/handler.ts index 9e495b03eaa..c4bd301b86a 100644 --- a/extensions/matrix/src/matrix/monitor/handler.ts +++ b/extensions/matrix/src/matrix/monitor/handler.ts @@ -14,7 +14,7 @@ import type { MatrixStreamingMode, ReplyToMode, } from "../../types.js"; -import { resolveMatrixAccountConfig } from "../account-config.js"; +import { resolveMatrixAccountAllowlistConfig } from "../account-config.js"; import { formatMatrixErrorMessage } from "../errors.js"; import { isMatrixMediaSizeLimitError } from "../media-errors.js"; import { @@ -706,17 +706,17 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam }; const storeAllowFrom = isDirectMessage ? await readStoreAllowFrom() : []; const roomUsers = roomConfig?.users ?? []; - const liveAccountCfg = resolveMatrixAccountConfig({ + const liveAccountAllowlists = resolveMatrixAccountAllowlistConfig({ cfg: core.config.loadConfig() as CoreConfig, accountId, }); const liveDmAllowFrom = resolveEffectiveMatrixLiveAllowlist({ - liveEntries: liveAccountCfg.dm?.allowFrom, + liveEntries: liveAccountAllowlists.dmAllowFrom, startupResolvedEntries: allowFromResolvedEntries, fallbackEntries: allowFrom, }); const liveGroupAllowFrom = resolveEffectiveMatrixLiveAllowlist({ - liveEntries: liveAccountCfg.groupAllowFrom, + liveEntries: liveAccountAllowlists.groupAllowFrom, startupResolvedEntries: groupAllowFromResolvedEntries, fallbackEntries: groupAllowFrom, });