fix(runner): label credential validation before configuration

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-10-27 20:40:15 -05:00
1 parent cb8f9025e4
commit 654bc5aa21
7 files changed
+30 -6

No files matched your search

+1 -1
View File
@@ -37,7 +37,7 @@
"agentServerVersion": "1.0.88",
"agentRuntimePackage": null,
"agentRuntimeVersion": null,
"commandDigest": "sha256:754e74c58bc9b22b49d38e0b9ff0a4708caff46abf6ac531975ea2d91c27de41",
"commandDigest": "sha256:618c3b69bc98b9a7e3c1b3411700eab8b90fd9245ba35d0bc85484319247fdbc",
"requiresProviderPolicy": true
},
"claude": {
@@ -47,7 +47,7 @@ pub(crate) fn acpx_release_profile(agent: &str) -> Option<AcpxReleaseProfile> {
agent_runtime_package: None,
agent_runtime_version: None,
command_digest:
"sha256:754e74c58bc9b22b49d38e0b9ff0a4708caff46abf6ac531975ea2d91c27de41",
"sha256:618c3b69bc98b9a7e3c1b3411700eab8b90fd9245ba35d0bc85484319247fdbc",
requires_provider_policy: true,
},
"claude" => AcpxReleaseProfile {
@@ -89,7 +89,7 @@ describe("Copilot build-owned installation", () => {
it("admits the current profile with environment launch preparation", () => {
expect(QUALIFIED_ACPX_PROFILES.copilot.agentProfileVersion).toBe(70);
expect(QUALIFIED_ACPX_PROFILES.copilot.qualificationStatus).toBeUndefined();
expect(QUALIFIED_ACPX_PROFILES.copilot.commandDigest).toBe("sha256:754e74c58bc9b22b49d38e0b9ff0a4708caff46abf6ac531975ea2d91c27de41");
expect(QUALIFIED_ACPX_PROFILES.copilot.commandDigest).toBe("sha256:618c3b69bc98b9a7e3c1b3411700eab8b90fd9245ba35d0bc85484319247fdbc");
});
it("preserves v69 while binding closed startup diagnostics in v70", async () => {
@@ -53,7 +53,7 @@ export const QUALIFIED_ACPX_PROFILE_DATA = {
"agentServerVersion": "1.0.88",
"agentRuntimePackage": null,
"agentRuntimeVersion": null,
"commandDigest": "sha256:754e74c58bc9b22b49d38e0b9ff0a4708caff46abf6ac531975ea2d91c27de41",
"commandDigest": "sha256:618c3b69bc98b9a7e3c1b3411700eab8b90fd9245ba35d0bc85484319247fdbc",
"permissionPolicy": "interactive"
},
"claude": {
@@ -203,6 +203,28 @@ afterEach(async () => {
});
describe("ACPX runtime host", () => {
it.each(["copilot", "cursor"] as const)("reports missing %s credentials as credential admission", async agent => {
const fixture = await hostFixture();
const openRuntime = vi.fn(async () => runtimePort());
const failure = await AcpxRuntimeHost.open({ ...fixture.options, agent, model:"gpt-5.6-sol",
permissionMode:"approve-all",environment:{} }, fixture.dependencies({openRuntime})).catch(error => error);
expect(failure).toMatchObject({code:agent === "copilot" ? "COPILOT_AUTH_REQUIRED" : "CURSOR_CREDENTIALS_MISSING"});
expect(acpxSidecarErrorCode(failure)).toBe("ACPX_ADMISSION_CREDENTIAL");
expect(openRuntime).not.toHaveBeenCalled();
expect(fixture.commandClose).not.toHaveBeenCalled();
});
it("retains binding admission when the selected workspace is missing", async () => {
const fixture = await hostFixture();
await rm(fixture.options.workingDirectory,{recursive:true});
const openRuntime = vi.fn(async () => runtimePort());
const dependencies = fixture.dependencies({openRuntime});
const verifyInstallation = vi.fn(dependencies.verifyInstallation!);
const failure = await AcpxRuntimeHost.open({ ...fixture.options,agent:"codex",model:"gpt-5.6-sol",
permissionMode:"approve-all" }, {...dependencies,verifyInstallation}).catch(error => error);
expect(acpxSidecarErrorCode(failure)).toBe("ACPX_ADMISSION_BINDING");
expect(verifyInstallation).not.toHaveBeenCalled();
expect(openRuntime).not.toHaveBeenCalled();
});
it("retains the admission stage when provider classification replaces the error", async () => {
const fixture = await hostFixture();
const openRuntime = vi.fn(async () => { throw new Error("Unauthorized private-token-canary"); });
@@ -526,7 +526,9 @@ export class AcpxRuntimeHost {
},
);
options.signal?.throwIfAborted();
admissionStage = "credential";
assertAcpxProfileEnvironment(options.agent, sandbox.launchEnvironment);
admissionStage = "configuration";
let launchEnvironment = sandbox.launchEnvironment;
// This copy is registered by the authenticated controller for its company,
// agent and run. Environment/config values cannot widen the grant. Each
@@ -1,5 +1,5 @@
{
"commandDigest": "sha256:754e74c58bc9b22b49d38e0b9ff0a4708caff46abf6ac531975ea2d91c27de41",
"commandDigest": "sha256:618c3b69bc98b9a7e3c1b3411700eab8b90fd9245ba35d0bc85484319247fdbc",
"declaration": {
"schema": "paperclip.acpx_profile_declaration.v1",
"agent": "copilot",
@@ -77,7 +77,7 @@
"metadataProbeSourceSha256": "be4c8416edd27061109bc1f33d0c26071b4facbb3f651beaae6b3c0275cce727",
"permissionToolIdentitySourceSha256": "770b47305e571a81f344883057d0e4a482a1cd59ac77d045836593a8e739deb1",
"semanticContinuationSourceSha256": "c9cc0fd516b3df92a6655f56ee9bef37615a889c371e2e137d8ac5c1176de811",
"runtimeHostSourceSha256": "be14218ad4477e083cfc32f6680fcfed776056a4084615d6b0efd1e521e66232",
"runtimeHostSourceSha256": "c779acab9ae4bbab4a13002d2e12c8c1acb208d0c4b575e7c5697fc3e7bb44c3",
"runtimeAdapterSourceSha256": "7c47c05306ebe7d1ca6b5d046a96f5726a48adec4d27e7c16788f505f25b5db2",
"runtimeSandboxSourceSha256": "981449a4c6d10f682ecf86d834eed07faca30a7d9b419fb8db4973a442a343ec",
"cancellationSourceSha256": "a07d1a9e982dec0ae130c1ad1efa5bc75c6a39e013b730ba3ee45256f09ceeca",