fix: honor signal setup dm policy accounts

This commit is contained in:
Tak Hoffman
2026-04-03 10:54:32 -05:00
parent b7f524abaa
commit d114b4e033
2 changed files with 89 additions and 5 deletions

View File

@@ -10,7 +10,11 @@ import {
} from "./identity.js";
import { probeSignal } from "./probe.js";
import { clearSignalRuntime } from "./runtime.js";
import { normalizeSignalAccountInput, parseSignalAllowFromEntries } from "./setup-core.js";
import {
normalizeSignalAccountInput,
parseSignalAllowFromEntries,
signalDmPolicy,
} from "./setup-core.js";
describe("looksLikeUuid", () => {
it("accepts hyphenated UUIDs", () => {
@@ -218,4 +222,56 @@ describe("signal setup parsing", () => {
error: "Invalid entry: invalid",
});
});
it("reads the named-account DM policy instead of the channel root", () => {
expect(
signalDmPolicy.getCurrent(
{
channels: {
signal: {
dmPolicy: "disabled",
accounts: {
work: {
account: "+15555550123",
dmPolicy: "allowlist",
},
},
},
},
},
"work",
),
).toBe("allowlist");
});
it("reports account-scoped config keys for named accounts", () => {
expect(signalDmPolicy.resolveConfigKeys?.({ channels: { signal: {} } }, "work")).toEqual({
policyKey: "channels.signal.accounts.work.dmPolicy",
allowFromKey: "channels.signal.accounts.work.allowFrom",
});
});
it('writes open policy state to the named account and preserves inherited allowFrom with "*"', () => {
const next = signalDmPolicy.setPolicy(
{
channels: {
signal: {
allowFrom: ["+15555550123"],
accounts: {
work: {
account: "+15555550999",
},
},
},
},
},
"open",
"work",
);
expect(next.channels?.signal?.dmPolicy).toBeUndefined();
expect(next.channels?.signal?.allowFrom).toEqual(["+15555550123"]);
expect(next.channels?.signal?.accounts?.work?.dmPolicy).toBe("open");
expect(next.channels?.signal?.accounts?.work?.allowFrom).toEqual(["+15555550123", "*"]);
});
});

View File

@@ -4,7 +4,8 @@ import {
createDelegatedTextInputShouldPrompt,
createPatchedAccountSetupAdapter,
createSetupInputPresenceValidator,
createTopLevelChannelDmPolicy,
mergeAllowFromEntries,
patchChannelConfigForAccount,
parseSetupEntriesAllowingWildcard,
promptParsedAllowFromForAccount,
setAccountAllowFromForChannel,
@@ -120,14 +121,41 @@ export async function promptSignalAllowFrom(params: {
});
}
export const signalDmPolicy = createTopLevelChannelDmPolicy({
export const signalDmPolicy = {
label: "Signal",
channel,
policyKey: "channels.signal.dmPolicy",
allowFromKey: "channels.signal.allowFrom",
getCurrent: (cfg: OpenClawConfig) => cfg.channels?.signal?.dmPolicy ?? "pairing",
resolveConfigKeys: (_cfg: OpenClawConfig, accountId?: string) =>
accountId && accountId !== resolveDefaultSignalAccountId(_cfg)
? {
policyKey: `channels.signal.accounts.${accountId}.dmPolicy`,
allowFromKey: `channels.signal.accounts.${accountId}.allowFrom`,
}
: {
policyKey: "channels.signal.dmPolicy",
allowFromKey: "channels.signal.allowFrom",
},
getCurrent: (cfg: OpenClawConfig, accountId?: string) =>
resolveSignalAccount({ cfg, accountId }).config.dmPolicy ?? "pairing",
setPolicy: (cfg: OpenClawConfig, policy: "pairing" | "allowlist" | "open" | "disabled", accountId?: string) =>
patchChannelConfigForAccount({
cfg,
channel,
accountId: accountId ?? resolveDefaultSignalAccountId(cfg),
patch:
policy === "open"
? {
dmPolicy: "open",
allowFrom: mergeAllowFromEntries(
resolveSignalAccount({ cfg, accountId }).config.allowFrom,
["*"],
),
}
: { dmPolicy: policy },
}),
promptAllowFrom: promptSignalAllowFrom,
});
};
function resolveSignalCliPath(params: {
cfg: OpenClawConfig;