Ctrl K
ComunidadGuías…

electron/approval-trusted-mode.node-test.mjs

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import assert from "node:assert/strict";
import { test } from "node:test";

import approvalModule from "./approval-trusted-mode.cjs";
import nativeText from "./native-text.cjs";

test("trusted refusals translate only canonical whitelisted errors from the matching process", async () => {
  const text = nativeText.createNativeText({ saved: "pt-br" });
  for (const [errorKey, nativeKey] of [
    ["serverError.approval.allThreads", "native.approval.allThreads"],
    ["serverError.approval.pending", "native.approval.pending"],
    ["serverError.approval.provider", "native.approval.provider"],
  ]) {
    const english = nativeText.englishText.t(nativeKey);
    for (const [key, error, expected] of [
      [errorKey, english, text.t(nativeKey)],
      [errorKey, "Changed server wording", "Changed server wording"],
      ["native.update.installing", english, english],
      ["constructor", english, english],
      [undefined, english, english],
    ]) {
      const proc = fakeProcess();
      const coordinator = createTrustedApprovalModeCoordinator({ randomId: () => REQUEST_ID, t: text.t });
      const pending = coordinator.request(proc, "bot-1", "ask");
      const result = { type: "approval-trusted-mode-result", requestId: REQUEST_ID, ok: false, error, errorKey: key };
      coordinator.receive(fakeProcess(), result);
      coordinator.receive(proc, result);
      await assert.rejects(pending, { message: expected });
      assert.equal(proc.messages.length, 1);
    }
    const proc = fakeProcess();
    const coordinator = createTrustedApprovalModeCoordinator({ randomId: () => REQUEST_ID });
    const pending = coordinator.request(proc, "bot-1", "ask");
    coordinator.receive(proc, { type: "approval-trusted-mode-result", requestId: REQUEST_ID, ok: false, error: english, errorKey });
    await assert.rejects(pending, { message: english });
  }
});

const {
  createTrustedApprovalModeCoordinator,
  decodeTrustedApprovalModeResult,
  trustedApprovalModeActivation,
  trustedApprovalModeCommit,
  trustedApprovalModeConfirmation,
  trustedApprovalModeFinalization,
  trustedApprovalModeRequest,
} = approvalModule;
const REQUEST_ID = "123e4567-e89b-42d3-a456-426614174000";
const REQUEST_ID_2 = "123e4567-e89b-42d3-a456-426614174001";

test("all-thread grants wait for committed thread modes and compensate the same scope on failure", async () => {
  for (const valid of [true, false]) {
    const proc = fakeProcess();
    const coordinator = createTrustedApprovalModeCoordinator({ randomId: idSequence(REQUEST_ID, REQUEST_ID_2) });
    let settled = false;
    const pending = coordinator.request(proc, "bot-1", "full", { allThreads: true }).then(bot => { settled = true; return bot; });
    assert.equal(proc.messages[0].allThreads, true);
    const bot = { id: "bot-1", approvalMode: "full", tasks: [{ threadId: "old", approvalMode: "ask" }] };
    coordinator.receive(proc, { type: "approval-trusted-mode-result", requestId: REQUEST_ID, ok: true, bot });
    for (const phase of ["confirm", "activate", "finalize"]) coordinator.receive(proc, { type: `approval-trusted-mode-${phase}-result`, requestId: REQUEST_ID, ok: true });
    await Promise.resolve(); assert.equal(settled, false);
    coordinator.receive(proc, { type: "approval-trusted-mode-commit-result", requestId: REQUEST_ID, ok: true,
      bot: { ...bot, tasks: [{ threadId: "old", approvalMode: valid ? "full" : "ask" }] } });
    if (valid) assert.equal((await pending).tasks[0].approvalMode, "full");
    else {
      assert.equal(proc.messages.at(-1).allThreads, true);
      assert.equal(proc.messages.at(-1).mode, "ask");
      coordinator.receive(proc, { type: "approval-trusted-mode-result", requestId: REQUEST_ID_2, ok: true,
        bot: { ...bot, approvalMode: "ask" } });
      await assert.rejects(pending, /not committed/);
    }
  }
});

test("all-thread grants take every level but Custom, and reject mixed scopes", () => {
  for (const mode of ["ask", "edits", "auto", "full"]) {
    assert.equal(trustedApprovalModeRequest(REQUEST_ID, "bot-1", mode, false, undefined, undefined, undefined, false, true).allThreads, true);
  }
  assert.throws(() => trustedApprovalModeRequest(REQUEST_ID, "bot-1", "custom", false, undefined, undefined, undefined, false, true), /all-threads/);
  assert.throws(() => trustedApprovalModeRequest(REQUEST_ID, "bot-1", "full", false, "thread", undefined, undefined, false, true), /all-threads/);
});

test("an all-thread Auto leaving Custom settles on its one reply, with no grant phases", async () => {
  const proc = fakeProcess();
  const coordinator = createTrustedApprovalModeCoordinator({ randomId: () => REQUEST_ID });
  const pending = coordinator.request(proc, "bot-1", "auto", { allThreads: true, acknowledgeLocalAuto: true });
  assert.deepEqual(proc.messages[0], { type: "approval-trusted-mode-set", requestId: REQUEST_ID, botId: "bot-1", mode: "auto", acknowledgeLocalAuto: true, allThreads: true });
  const bot = { id: "bot-1", approvalMode: "auto", tasks: [{ threadId: "rules", approvalMode: "auto" }] };
  coordinator.receive(proc, { type: "approval-trusted-mode-result", requestId: REQUEST_ID, ok: true, bot });
  assert.deepEqual(await pending, bot);
  assert.equal(proc.messages.length, 1);
});

test("scoped composer grants wait for the real commit and keep the bot default", async () => {
  const proc = fakeProcess();
  const coordinator = createTrustedApprovalModeCoordinator({ randomId: () => REQUEST_ID });
  let settled = false;
  const pending = coordinator.request(proc, "bot-1", "full", { threadId: "thread-1", threadOnly: true }).then(bot => { settled = true; return bot; });
  const before = { id: "bot-1", approvalMode: "ask", tasks: [{ threadId: "thread-1", approvalMode: "ask" }] };
  coordinator.receive(proc, { type: "approval-trusted-mode-result", requestId: REQUEST_ID, ok: true, bot: before });
  for (const phase of ["confirm", "activate", "finalize"]) coordinator.receive(proc, { type: `approval-trusted-mode-${phase}-result`, requestId: REQUEST_ID, ok: true });
  await Promise.resolve(); assert.equal(settled, false);
  const after = { ...before, tasks: [{ threadId: "thread-1", approvalMode: "full" }] };
  coordinator.receive(proc, { type: "approval-trusted-mode-commit-result", requestId: REQUEST_ID, ok: true, bot: after });
  assert.deepEqual(await pending, after);
});

test("an uncertain scoped commit compensates only its own thread", async () => {
  const proc = fakeProcess();
  const coordinator = createTrustedApprovalModeCoordinator({ randomId: idSequence(REQUEST_ID, REQUEST_ID_2) });
  const pending = coordinator.request(proc, "bot-1", "full", { threadId: "thread-1", threadOnly: true });
  const before = { id: "bot-1", approvalMode: "custom", tasks: [{ threadId: "thread-1", approvalMode: "ask" }] };
  coordinator.receive(proc, { type: "approval-trusted-mode-result", requestId: REQUEST_ID, ok: true, bot: before });
  for (const phase of ["confirm", "activate", "finalize"]) coordinator.receive(proc, { type: `approval-trusted-mode-${phase}-result`, requestId: REQUEST_ID, ok: true });
  coordinator.receive(proc, { type: "approval-trusted-mode-commit-result", requestId: REQUEST_ID, ok: false });
  assert.deepEqual(proc.messages.at(-1), { type: "approval-trusted-mode-set", requestId: REQUEST_ID_2, botId: "bot-1", mode: "ask", threadId: "thread-1", threadOnly: true });
  coordinator.receive(proc, { type: "approval-trusted-mode-result", requestId: REQUEST_ID_2, ok: true, bot: before });
  await assert.rejects(pending, /not committed/);
});

test("thread-only options reject missing or mixed scopes", () => {
  for (const mode of ["ask", "edits", "auto", "full", "custom"]) assert.equal(trustedApprovalModeRequest(REQUEST_ID, "bot-1", mode, false, "thread-1", undefined, undefined, true).threadOnly, true);
  assert.throws(() => trustedApprovalModeRequest(REQUEST_ID, "bot-1", "full", false, undefined, undefined, undefined, true), /thread-only/);
  assert.throws(() => trustedApprovalModeRequest(REQUEST_ID, "bot-1", "full", false, "thread-1", undefined, true, true), /thread-only/);
});

test("permission refresh stays on one thread", () => {
  const message = trustedApprovalModeRequest(REQUEST_ID, "bot-1", "auto", false, "thread-1", undefined, undefined, true, false, true);
  assert.equal(message.refreshPermissions, true);
  assert.equal(message.threadOnly, true);
  assert.equal(message.threadId, "thread-1");
  assert.throws(() => trustedApprovalModeRequest(REQUEST_ID, "bot-1", "full", false, "thread-1", undefined, undefined, false, false, true), /permission refresh/);
  assert.throws(() => trustedApprovalModeRequest(REQUEST_ID, "bot-1", "full", false, undefined, undefined, undefined, false, true, true), /permission refresh/);
  assert.throws(() => trustedApprovalModeRequest(REQUEST_ID, "bot-1", "ask", false, undefined, undefined, undefined, false, false, "yes"), /permission refresh/);
});

function idSequence(...ids) {
  let index = 0;
  return () => ids[index++] ?? (() => { throw new Error("test request id sequence exhausted"); })();
}

function fakeProcess() {
  const messages = [];
  return { messages, postMessage: (message) => messages.push(message) };
}

test("confirmed model switches use only scoped Ask requests", () => {
  const selection = { instanceId: "claude", model: "sonnet" };
  assert.deepEqual(trustedApprovalModeRequest(REQUEST_ID, "bot-1", "ask", false, "thread-1", selection, false), {
    type: "approval-trusted-mode-set", requestId: REQUEST_ID, botId: "bot-1", mode: "ask",
    threadId: "thread-1", modelSelection: selection, updateBotDefault: false,
  });
  for (const mode of ["full", "custom", "auto"]) {
    assert.throws(() => trustedApprovalModeRequest(REQUEST_ID, "bot-1", mode, false, "thread-1", selection, true), /invalid confirmed model switch/);
  }
  assert.throws(() => trustedApprovalModeRequest(REQUEST_ID, "bot-1", "ask", false, undefined, selection, true), /invalid confirmed model switch/);
  assert.throws(() => trustedApprovalModeRequest(REQUEST_ID, "bot-1", "ask", false, "thread-1", selection, "yes"), /invalid confirmed model switch/);
});

test("a thread-only switch verifies the thread mode without changing the bot default", async () => {
  const proc = fakeProcess();
  const coordinator = createTrustedApprovalModeCoordinator({ randomId: () => REQUEST_ID });
  const pending = coordinator.request(proc, "bot-1", "ask", {
    threadId: "thread-1", modelSelection: { instanceId: "claude", model: "sonnet" }, updateBotDefault: false,
  });
  const bot = { id: "bot-1", approvalMode: "custom", tasks: [{ threadId: "thread-1", approvalMode: "ask" }] };
  coordinator.receive(proc, { type: "approval-trusted-mode-result", requestId: REQUEST_ID, ok: true, bot });
  assert.deepEqual(await pending, bot);
  assert.equal(proc.messages.length, 1);
});

test("builds only bounded bot-scoped approval-mode requests", () => {
  assert.equal(trustedApprovalModeRequest(REQUEST_ID, "bot-1", "full", false, "thread-1").threadId, "thread-1");
  for (const threadId of ["", "../another-thread", null, 42]) {
    assert.throws(() => trustedApprovalModeRequest(REQUEST_ID, "bot-1", "full", false, threadId), /invalid thread/);
  }
  assert.throws(() => trustedApprovalModeRequest(REQUEST_ID, "bot-1", "ask", false, "thread-1"), /invalid thread/);
  assert.deepEqual(trustedApprovalModeRequest(REQUEST_ID, "bot-1", "full"), {
    type: "approval-trusted-mode-set",
    requestId: REQUEST_ID,
    botId: "bot-1",
    mode: "full",
  });
  assert.equal(trustedApprovalModeRequest(REQUEST_ID, "bot-1", "custom").mode, "custom");
  assert.equal(trustedApprovalModeRequest(REQUEST_ID, "bot-1", "ask").mode, "ask");
  assert.deepEqual(trustedApprovalModeRequest(REQUEST_ID, "bot-1", "auto", true), {
    type: "approval-trusted-mode-set",
    requestId: REQUEST_ID,
    botId: "bot-1",
    mode: "auto",
    acknowledgeLocalAuto: true,
  });
  assert.throws(() => trustedApprovalModeRequest("request-1", "bot-1", "full"), /request id/);
  assert.throws(() => trustedApprovalModeRequest(REQUEST_ID, "../another-bot", "full"), /bot id/);
  assert.throws(() => trustedApprovalModeRequest(REQUEST_ID, "bot-1", "unsafe"), /approval mode/);
  assert.throws(() => trustedApprovalModeRequest(REQUEST_ID, "bot-1", "auto", "yes"), /acknowledgement/);
  assert.deepEqual(trustedApprovalModeConfirmation(REQUEST_ID, "bot-1", "full"), {
    type: "approval-trusted-mode-confirm",
    requestId: REQUEST_ID,
    botId: "bot-1",
    mode: "full",
  });
  assert.deepEqual(trustedApprovalModeActivation(REQUEST_ID, "bot-1", "custom"), {
    type: "approval-trusted-mode-activate",
    requestId: REQUEST_ID,
    botId: "bot-1",
    mode: "custom",
  });
  assert.deepEqual(trustedApprovalModeFinalization(REQUEST_ID, "bot-1", "full"), {
    type: "approval-trusted-mode-finalize",
    requestId: REQUEST_ID,
    botId: "bot-1",
    mode: "full",
  });
  assert.deepEqual(trustedApprovalModeCommit(REQUEST_ID, "bot-1", "full"), {
    type: "approval-trusted-mode-commit",
    requestId: REQUEST_ID,
    botId: "bot-1",
    mode: "full",
  });
  assert.throws(() => trustedApprovalModeConfirmation(REQUEST_ID, "bot-1", "ask"), /elevated/);
});

test("validates successful and failed trusted approval-mode results", () => {
  const bot = { id: "bot-1", approvalMode: "custom", name: "Operator" };
  assert.deepEqual(decodeTrustedApprovalModeResult({
    type: "approval-trusted-mode-result",
    requestId: REQUEST_ID,
    ok: true,
    bot,
  }), { requestId: REQUEST_ID, ok: true, bot });
  assert.deepEqual(decodeTrustedApprovalModeResult({
    type: "approval-trusted-mode-result",
    requestId: REQUEST_ID,
    ok: false,
    error: "Bot not found",
  }), { requestId: REQUEST_ID, ok: false, error: "Bot not found" });
  assert.throws(() => decodeTrustedApprovalModeResult({
    type: "approval-trusted-mode-result",
    requestId: REQUEST_ID,
    ok: true,
    bot: { id: "bot-1", approvalMode: "unsafe" },
  }), /invalid bot/);
});

test("carries the local Auto warning acknowledgement through the private channel", async () => {
  const proc = fakeProcess();
  const coordinator = createTrustedApprovalModeCoordinator({ randomId: () => REQUEST_ID, timeoutMs: 100 });
  const pending = coordinator.request(proc, "bot-1", "auto", { acknowledgeLocalAuto: true });
  assert.deepEqual(proc.messages[0], {
    type: "approval-trusted-mode-set",
    requestId: REQUEST_ID,
    botId: "bot-1",
    mode: "auto",
    acknowledgeLocalAuto: true,
  });
  coordinator.receive(proc, {
    type: "approval-trusted-mode-result",
    requestId: REQUEST_ID,
    ok: true,
    bot: { id: "bot-1", approvalMode: "auto" },
  });
  assert.equal((await pending).approvalMode, "auto");
});

test("sends through one utility process and returns the matching server bot", async () => {
  const proc = fakeProcess();
  const coordinator = createTrustedApprovalModeCoordinator({ randomId: () => REQUEST_ID, timeoutMs: 100 });
  const pending = coordinator.request(proc, "bot-1", "custom");
  assert.deepEqual(proc.messages, [{
    type: "approval-trusted-mode-set",
    requestId: REQUEST_ID,
    botId: "bot-1",
    mode: "custom",
  }]);

  const bot = { id: "bot-1", approvalMode: "custom", name: "Operator" };
  assert.equal(coordinator.receive(proc, {
    type: "approval-trusted-mode-result",
    requestId: REQUEST_ID,
    ok: true,
    bot,
  }), true);
  assert.deepEqual(proc.messages[1], {
    type: "approval-trusted-mode-confirm",
    requestId: REQUEST_ID,
    botId: "bot-1",
    mode: "custom",
  });
  assert.equal(coordinator.receive(proc, {
    type: "approval-trusted-mode-confirm-result",
    requestId: REQUEST_ID,
    ok: true,
  }), true);
  assert.deepEqual(proc.messages[2], {
    type: "approval-trusted-mode-activate",
    requestId: REQUEST_ID,
    botId: "bot-1",
    mode: "custom",
  });
  assert.equal(coordinator.receive(proc, {
    type: "approval-trusted-mode-activate-result",
    requestId: REQUEST_ID,
    ok: true,
  }), true);
  assert.deepEqual(proc.messages[3], {
    type: "approval-trusted-mode-finalize",
    requestId: REQUEST_ID,
    botId: "bot-1",
    mode: "custom",
  });
  assert.equal(coordinator.receive(proc, {
    type: "approval-trusted-mode-finalize-result",
    requestId: REQUEST_ID,
    ok: true,
  }), true);
  assert.deepEqual(proc.messages[4], {
    type: "approval-trusted-mode-commit",
    requestId: REQUEST_ID,
    botId: "bot-1",
    mode: "custom",
  });
  assert.deepEqual(await pending, bot);
});

test("rejects a response for another trusted mode", async () => {
  const proc = fakeProcess();
  const coordinator = createTrustedApprovalModeCoordinator({
    randomId: idSequence(REQUEST_ID, REQUEST_ID_2),
    timeoutMs: 100,
  });
  const pending = coordinator.request(proc, "bot-1", "custom");
  assert.equal(coordinator.receive(proc, {
    type: "approval-trusted-mode-result",
    requestId: REQUEST_ID,
    ok: true,
    bot: { id: "bot-1", approvalMode: "full" },
  }), true);
  assert.equal(proc.messages[1].mode, "ask");
  coordinator.receive(proc, {
    type: "approval-trusted-mode-result",
    requestId: REQUEST_ID_2,
    ok: true,
    bot: { id: "bot-1", approvalMode: "ask" },
  });
  await assert.rejects(pending, /did not match/);
});

test("revokes an elevated grant before rejecting a malformed matching reply", async () => {
  const proc = fakeProcess();
  const coordinator = createTrustedApprovalModeCoordinator({
    randomId: idSequence(REQUEST_ID, REQUEST_ID_2),
    timeoutMs: 100,
  });
  const pending = coordinator.request(proc, "bot-1", "full");
  assert.equal(coordinator.receive(proc, {
    type: "approval-trusted-mode-result",
    requestId: REQUEST_ID,
    ok: "yes",
  }), true);
  assert.deepEqual(proc.messages[1], {
    type: "approval-trusted-mode-set",
    requestId: REQUEST_ID_2,
    botId: "bot-1",
    mode: "ask",
  });
  coordinator.receive(proc, {
    type: "approval-trusted-mode-result",
    requestId: REQUEST_ID_2,
    ok: true,
    bot: { id: "bot-1", approvalMode: "ask" },
  });
  await assert.rejects(pending, /invalid trusted approval-mode result status/);
});

test("another utility process cannot resolve a pending request", async () => {
  const proc = fakeProcess();
  const replacement = fakeProcess();
  const coordinator = createTrustedApprovalModeCoordinator({ randomId: () => REQUEST_ID, timeoutMs: 100 });
  const pending = coordinator.request(proc, "bot-1", "full");
  const result = {
    type: "approval-trusted-mode-result",
    requestId: REQUEST_ID,
    ok: true,
    bot: { id: "bot-1", approvalMode: "full" },
  };
  assert.equal(coordinator.receive(replacement, result), true);
  assert.equal(coordinator.receive(proc, result), true);
  assert.equal(coordinator.receive(replacement, {
    type: "approval-trusted-mode-confirm-result",
    requestId: REQUEST_ID,
    ok: true,
  }), true);
  assert.equal(coordinator.receive(proc, {
    type: "approval-trusted-mode-confirm-result",
    requestId: REQUEST_ID,
    ok: true,
  }), true);
  assert.equal(coordinator.receive(replacement, {
    type: "approval-trusted-mode-activate-result",
    requestId: REQUEST_ID,
    ok: true,
  }), true);
  assert.equal(coordinator.receive(proc, {
    type: "approval-trusted-mode-activate-result",
    requestId: REQUEST_ID,
    ok: true,
  }), true);
  assert.equal(coordinator.receive(replacement, {
    type: "approval-trusted-mode-finalize-result",
    requestId: REQUEST_ID,
    ok: true,
  }), true);
  assert.equal(coordinator.receive(proc, {
    type: "approval-trusted-mode-finalize-result",
    requestId: REQUEST_ID,
    ok: true,
  }), true);
  assert.equal(proc.messages[4].type, "approval-trusted-mode-commit");
  assert.equal((await pending).approvalMode, "full");
});

test("does not resolve an elevated selection when server confirmation is refused", async () => {
  const proc = fakeProcess();
  const coordinator = createTrustedApprovalModeCoordinator({ randomId: () => REQUEST_ID, timeoutMs: 100 });
  const pending = coordinator.request(proc, "bot-1", "full");
  coordinator.receive(proc, {
    type: "approval-trusted-mode-result",
    requestId: REQUEST_ID,
    ok: true,
    bot: { id: "bot-1", approvalMode: "full" },
  });
  coordinator.receive(proc, {
    type: "approval-trusted-mode-confirm-result",
    requestId: REQUEST_ID,
    ok: false,
    error: "The bot changed providers",
  });
  await assert.rejects(pending, /changed providers/);
  assert.equal(proc.messages.some((message) => message.type === "approval-trusted-mode-activate"), false);
});

test("rejects pending grants immediately when their utility process exits", async () => {
  const proc = fakeProcess();
  const coordinator = createTrustedApprovalModeCoordinator({ randomId: () => REQUEST_ID, timeoutMs: 100 });
  const pending = coordinator.request(proc, "bot-1", "full");
  coordinator.rejectProcess(proc, "server exited");
  await assert.rejects(pending, /server exited/);
  assert.equal(proc.messages.length, 1);
});

test("times out only after an ambiguous elevated grant is revoked", async () => {
  const proc = fakeProcess();
  const coordinator = createTrustedApprovalModeCoordinator({
    randomId: idSequence(REQUEST_ID, REQUEST_ID_2),
    timeoutMs: 100,
  });
  const pending = coordinator.request(proc, "bot-1", "custom");
  await new Promise((resolve) => setTimeout(resolve, 110));
  assert.equal(proc.messages[1].mode, "ask");
  coordinator.receive(proc, {
    type: "approval-trusted-mode-result",
    requestId: REQUEST_ID_2,
    ok: true,
    bot: { id: "bot-1", approvalMode: "ask" },
  });
  await assert.rejects(pending, /did not answer/);
});

test("safe Ask timeouts do not enqueue a redundant recovery", async () => {
  const proc = fakeProcess();
  const coordinator = createTrustedApprovalModeCoordinator({ randomId: () => REQUEST_ID, timeoutMs: 5 });
  await assert.rejects(coordinator.request(proc, "bot-1", "ask"), /did not answer/);
  assert.equal(proc.messages.length, 1);
});