Follow current Copilot profile identity in native installation admission

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-09-29 10:04:53 -05:00
1 parent fa393bff17
commit 59bba28192
2 files changed
+13 -2

No files matched your search

@@ -10,6 +10,17 @@ import { QUALIFIED_ACPX_PROFILES } from "./qualified-profiles.js";
vi.mock("./installation-integrity.js", () => ({ verifyNativeAcpxInstallation: vi.fn() }));
describe("Copilot build-owned installation", () => {
it("admits the current v3 declaration and binds its source policy/patch hashes", () => {
const identity = JSON.parse(readFileSync(new URL("../../../test/fixtures/copilot-profile-v3-identity.json", import.meta.url), "utf8"));
expect(QUALIFIED_ACPX_PROFILES.copilot.agentProfileVersion).toBe(identity.declaration.agentProfileVersion);
expect(QUALIFIED_ACPX_PROFILES.copilot.commandDigest).toBe(identity.commandDigest);
const sorted = Object.fromEntries(Object.entries(identity.declaration).sort(([a], [b]) => a.localeCompare(b)));
expect(`sha256:${createHash("sha256").update(JSON.stringify(sorted)).digest("hex")}`).toBe(identity.commandDigest);
for (const [relative, field] of [["copilot-policy.ts", "policySha256"], ["../../../../../patches/acpx@0.13.1.patch", "acpxPatchSha256"]]) {
expect(createHash("sha256").update(readFileSync(new URL(relative!, import.meta.url))).digest("hex")).toBe(identity.declaration[field!]);
}
expect(readFileSync(new URL("../../../scripts/build-copilot-distribution.mjs", import.meta.url), "utf8")).toContain(identity.commandDigest);
});
it("pins the materializer's complete executable closure on every target platform", () => {
const script = readFileSync(new URL("../../../scripts/materialize-copilot-binary.mjs", import.meta.url), "utf8");
const records = [...script.matchAll(/"(darwin-arm64|darwin-x64|linux-x64)": Object\.freeze\(\{ packageName: "[^"]+", executableDigest: "([a-f0-9]+)", size: (\d+)/g)];
@@ -38,7 +49,7 @@ describe("Copilot build-owned installation", () => {
});
it("rejects changed profile identities before native file access", async () => {
vi.mocked(verifyNativeAcpxInstallation).mockClear();
for (const override of [{ agentServerVersion: "latest" }, { commandDigest: "sha256:untrusted" }, { agent: "cursor" }, { agentProfileVersion: 1 }]) {
for (const override of [{ agentServerVersion: "latest" }, { commandDigest: "sha256:untrusted" }, { agent: "cursor" }, { agentProfileVersion: 1 }, { agentProfileVersion: 2 }, { agentProfileVersion: 4 }]) {
await expect(verifyCopilotInstallation({ ...QUALIFIED_ACPX_PROFILES.copilot, ...override } as never)).rejects.toThrow("exact pinned");
}
expect(verifyNativeAcpxInstallation).not.toHaveBeenCalled();
@@ -13,7 +13,7 @@ export const COPILOT_CLOSURE_SHA256 = Object.freeze({
/** Admission primitive only. Pending candidates remain gated by qualification. */
export async function verifyCopilotInstallation(profile: QualifiedAcpxProfile): Promise<VerifiedAcpxInstallation> {
const expected = QUALIFIED_ACPX_PROFILES.copilot;
if (profile.agent !== "copilot" || profile.agentProfileVersion !== 2
if (profile.agent !== "copilot" || profile.agentProfileVersion !== expected.agentProfileVersion
|| profile.acpxVersion !== expected.acpxVersion || profile.agentServerPackage !== "@github/copilot"
|| profile.agentServerVersion !== COPILOT_VERSION || profile.commandDigest !== expected.commandDigest
|| profile.agentRuntimePackage !== null || profile.agentRuntimeVersion !== null) {