Files
PaperClipAI/tests/runner-e2e/copilot-permission-target-origin.test.ts
T
DottaandPaperclip c48b89618f Add Copilot Product qualification and fixture ownership checks
Reviewed partition of the current-master Copilot integration. Complete v30 live qualification is retained; current v31 recovery compatibility, CI and review are tracked explicitly.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-08 07:35:27 -05:00

56 lines
4.4 KiB
TypeScript

import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
import { copilotEditOriginForPermission, readCopilotToolEvidence } from "./copilot-evidence.js";
import { observeActiveStopPending, readActiveStopCaller } from "./copilot-active-stop-evidence.js";
const retained = JSON.parse(readFileSync(new URL("./fixtures/copilot-patch-permission-target-v15.json", import.meta.url), "utf8"));
const caller = readActiveStopCaller({ deploymentMode: "local_trusted" }, { session: { userId: "local-board", id: "paperclip:local_implicit:local-board" } });
function fixture() {
const { rows: events, scope, run, issue } = structuredClone(retained);
const notices = readCopilotToolEvidence(events, run.id);
const read = () => observeActiveStopPending({ events, scope, run, issue, caller, cancellationRequestId: "11111111-2222-4333-8444-555555555555" });
return { events, scope, notices, read };
}
describe("pending patch target bound by its exact permission", () => {
it("calibrates the retained missing-notification path while keeping the actual card target", () => {
const f = fixture(), origin = copilotEditOriginForPermission(f.notices, f.scope.target)!;
expect(origin.target).toBeUndefined();
expect(origin.toolCallId).toBe("custom_call_jyQm34Kq61JjSxkZUXvPSNrh");
expect(f.read()).toMatchObject({ toolCallId: origin.toolCallId, scope: { target: f.scope.target }, requestId: "acpx-input-ccaa35c8d2130be28a27e1d3" });
expect(retained.outcome).toContain("calibration only");
});
it.each(["wrong-call", "foreign-session", "foreign-turn", "foreign-run", "conflicting-path", "conflicting-operation", "duplicate-pending", "duplicate-permission", "missing-permission"])("refuses %s", kind => {
const f = fixture();
const origin = copilotEditOriginForPermission(f.notices, f.scope.target)!;
const permission = f.notices.find(n => n.stage === "permission_requested" && n.toolCallId === origin.toolCallId)!;
if (kind === "wrong-call") permission.toolCallId = "unrelated";
if (kind === "foreign-session") permission.sessionId = "foreign";
if (kind === "foreign-turn") permission.turnId = "foreign";
if (kind === "foreign-run") permission.runId = "foreign";
if (kind === "conflicting-path") origin.target = "another.txt";
if (kind === "conflicting-operation") origin.operation = "execute";
if (kind === "duplicate-pending") f.notices.push({ ...origin, seq: origin.seq + 1 });
if (kind === "duplicate-permission") f.notices.push({ ...permission, seq: permission.seq + 1 });
if (kind === "missing-permission") f.notices.splice(f.notices.indexOf(permission), 1);
if (["wrong-call", "missing-permission"].includes(kind)) expect(copilotEditOriginForPermission(f.notices, f.scope.target)).toBeUndefined();
else expect(() => copilotEditOriginForPermission(f.notices, f.scope.target)).toThrow(/Copilot.*(?:origin|target)/);
});
it("cannot borrow a target from another native operation", () => {
const f = fixture();
expect(copilotEditOriginForPermission(f.notices, f.scope.target, "other-call")).toBeUndefined();
});
it.each(["card-call", "card-request", "card-source", "wrong-provider", "wrong-adapter", "wrong-method", "permission-path", "context-after-edit"])("keeps durable evidence guard for %s", kind => {
const f = fixture();
const row = (eventType: string, seq: number) => f.events.find((r: any) => r.eventType === eventType && r.seq === seq);
const payload = (r: any) => r.payload.prpEvent.payload;
if (kind === "card-call") payload(row("runtime_request.created", 134)).request.details.toolCallId = "other-call";
if (kind === "card-request") payload(row("runtime_request.created", 134)).request.requestId = "other-request";
if (kind === "wrong-provider") payload(row("runtime_request.created", 134)).request.origin.provider = "cursor";
if (kind === "wrong-adapter") payload(row("runtime_request.created", 134)).request.origin.adapter = "untrusted";
if (kind === "wrong-method") payload(row("runtime_request.created", 134)).request.origin.method = "other";
if (kind === "card-source") row("runtime_request.created", 134).payload.prpEvent.sourceInstanceId = "other-source";
if (kind === "permission-path") payload(row("provider.notice.recorded", 137)).details.find((d: any) => d.name === "target").value = "other.txt";
if (kind === "context-after-edit") row("tool.execution.completed", 130).seq = 136;
expect(f.read).toThrow();
});
});