Slack: align exec approval actions with policy

This commit is contained in:
Gustavo Madeira Santana
2026-04-01 21:49:42 -04:00
parent ec82d6f3ad
commit d579b97a93
2 changed files with 34 additions and 0 deletions

View File

@@ -130,6 +130,37 @@ describe("SlackExecApprovalHandler", () => {
);
});
it("omits allow-always when exec approvals disallow it", async () => {
const app = buildApp();
const handler = new SlackExecApprovalHandler({
app,
accountId: "default",
config: buildConfig("dm").channels!.slack!.execApprovals!,
cfg: buildConfig("dm"),
});
await handler.handleApprovalRequested(
buildRequest({
ask: "always",
allowedDecisions: ["allow-once", "deny"],
}),
);
const dmCall = sendMessageSlackMock.mock.calls.find(([to]) => to === "user:U123APPROVER");
const blocks = dmCall?.[2]?.blocks as Array<Record<string, unknown>> | undefined;
const actionsBlock = blocks?.find((block) => block.type === "actions");
const buttons = Array.isArray(actionsBlock?.elements) ? actionsBlock.elements : [];
const buttonTexts = buttons.map((button) =>
typeof button === "object" && button && typeof button.text === "object" && button.text
? String((button.text as { text?: unknown }).text ?? "")
: "",
);
expect(buttonTexts).toContain("Allow Once");
expect(buttonTexts).toContain("Deny");
expect(buttonTexts).not.toContain("Allow Always");
});
it("updates the pending approval card in place after resolution", async () => {
const app = buildApp();
const update = app.client.chat.update as ReturnType<typeof vi.fn>;

View File

@@ -6,6 +6,7 @@ import {
createChannelNativeApprovalRuntime,
getExecApprovalApproverDmNoticeText,
resolveExecApprovalCommandDisplay,
resolveExecApprovalRequestAllowedDecisions,
type ExecApprovalChannelRuntime,
type ExecApprovalDecision,
type ExecApprovalRequest,
@@ -99,6 +100,8 @@ function buildSlackPendingApprovalBlocks(request: ExecApprovalRequest): SlackBlo
text: "",
interactive: buildApprovalInteractiveReply({
approvalId: request.id,
ask: request.request.ask,
allowedDecisions: resolveExecApprovalRequestAllowedDecisions(request.request),
}),
}) ?? [];
return [