mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-04 19:28:46 +01:00
test(runner): reserve owned credential quorum fixtures
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
021df20762
commit
271d434c17
2 files changed
+84
-13
No files matched your search
@@ -1,6 +1,34 @@
|
||||
# Runner defaults: staged delivery
|
||||
|
||||
Updated 2026-10-12.
|
||||
Updated 2026-10-13 UTC.
|
||||
|
||||
## Fresh cloud onboarding remains unqualified
|
||||
|
||||
The source audit found two ordinary-use gaps in the dependent release. Codex
|
||||
onboarding resolves Auto from saved environment facts before setup testing.
|
||||
The normal setup path does not perform the saved environment platform probe.
|
||||
An immutable OCI environment without prior facts therefore creates a Legacy
|
||||
agent. Existing managed E2E fixtures explicitly probe first; those fixtures do
|
||||
not prove fresh onboarding. A private UI correction is being tested against
|
||||
the existing onboarding suite. It uses the existing permission-gated saved
|
||||
probe on explicit Connect, refreshes company-scoped discovery, then tests the
|
||||
selected runtime. Creation and discovery still allocate nothing. Probe errors
|
||||
must stay actionable, and permissions must not broaden.
|
||||
|
||||
Cloud master `23531d729756ab0461a53f9358beb8df5c1781ed` distributes named
|
||||
Daytona snapshots. Its recorded runtime image digest identifies the app copied
|
||||
into that snapshot, not the final boot image. Current source does not bind a
|
||||
fresh company's qualification to a verified boot identity. The pinned official
|
||||
Daytona SDK accepts snapshot IDs, but does not guarantee a boot-verified digest.
|
||||
A read-only lookup of the existing snapshot was rejected before execution by
|
||||
automatic approval review because direct credential authorization was missing.
|
||||
The exact limited authorization is now requested. No key was read or request
|
||||
sent. Source audits and CLI version probes do not close live cloud acceptance.
|
||||
|
||||
These are release blockers for the Codex-default and actual Cloud distribution
|
||||
stages, not new runtime changes in this prerequisite. No source is merged or
|
||||
production-ready. The original budget holds, local preview, existing runners,
|
||||
remote-build boundary and no-production-deployment boundary remain intact.
|
||||
|
||||
## Held-authorization fixture correction
|
||||
|
||||
@@ -455,3 +483,24 @@ Next action: commit and push the narrowed candidate, rerun its checks and fresh
|
||||
review, then update the PR and existing evidence report. Start the Codex-default
|
||||
slice after the user chooses to proceed. Merging and deployment remain outside
|
||||
this task.
|
||||
|
||||
### Occupied credential fixture follow-up — 2026-10-12
|
||||
|
||||
Current-head `021df207` Runner Vitest 2 failed during fixture preparation with
|
||||
`EADDRINUSE`, before credential staging. Reused the shared correction from
|
||||
`50e7554069a31af72069e7632e9ae6151019f449`: prepare a fresh home with two
|
||||
deliberately occupied candidates, preserve the foreign listener, and retain the
|
||||
actual staging denial and unchanged auth-file assertion. The three-line code
|
||||
annotation was removed to follow CONTRIBUTING; its explanation lives here.
|
||||
|
||||
Only fixture preparation retries, up to eight fresh homes. It releases only its
|
||||
owned partial or unselected listeners, then runs credential staging once. A bind
|
||||
race during that production call remains a visible failure and receives no
|
||||
retry. No production credential or permission behavior changed.
|
||||
|
||||
A controlled occupied-port baseline reproduces the old setup failure. All 42
|
||||
existing credential controls pass on Node 24 with isolated synthetic data and
|
||||
zero provider calls or native builds. Comment-only removal preserves the tested
|
||||
executable structure; the suite was not repeated. Evidence is recorded in
|
||||
`/private/tmp/ci-final-021df2-shared-credential-quorum-receipt.json` and its
|
||||
comment-closure receipt. Fresh published-head CI and review remain required.
|
||||
@@ -245,13 +245,30 @@ describe("managed Codex credentials", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("prepares two occupied candidates without disturbing a foreign collision", async () => {
|
||||
const foreign = await silentPrimaryQuorumFixture();
|
||||
const nextFixture = vi.fn().mockResolvedValueOnce(foreign.fixture).mockImplementation(credentialFixture);
|
||||
let prepared: Awaited<ReturnType<typeof silentPrimaryQuorumFixture>> | undefined;
|
||||
try {
|
||||
prepared = await silentPrimaryQuorumFixture(nextFixture, "quorum");
|
||||
expect(nextFixture.mock.calls.length).toBeGreaterThanOrEqual(2);
|
||||
expect(nextFixture.mock.calls.length).toBeLessThanOrEqual(8);
|
||||
expect(prepared.fixture.home).not.toBe(foreign.fixture.home);
|
||||
await expect(listenSilently(credentialLeasePorts(foreign.fixture.home)[0])).rejects.toMatchObject({ code: "EADDRINUSE" });
|
||||
const destination = join(prepared.fixture.home, "auth.json");
|
||||
await writeFile(destination, '{"sentinel":true}', { mode: 0o600 });
|
||||
await expect(stageManagedCodexCredential({ agentHomeDirectory: prepared.fixture.home, environment: { PAPERCLIP_ACPX_CODEX_AUTH_JSON_SECRET: '{"owner":"contender"}' } })).rejects.toThrow("already has an active lease");
|
||||
await expect(readFile(destination, "utf8")).resolves.toBe('{"sentinel":true}');
|
||||
} finally {
|
||||
await prepared?.occupied.close();
|
||||
await foreign.occupied.close();
|
||||
}
|
||||
});
|
||||
|
||||
it("fails before auth mutation when two quorum candidates are occupied", async () => {
|
||||
const fixture = await credentialFixture();
|
||||
const { fixture, occupied } = await silentPrimaryQuorumFixture(credentialFixture, "quorum");
|
||||
const destination = join(fixture.home, "auth.json");
|
||||
await writeFile(destination, '{"sentinel":true}', { mode: 0o600 });
|
||||
const ports = credentialLeasePorts(await realpath(fixture.home));
|
||||
const first = await listenSilently(ports[0]);
|
||||
const second = await listenSilently(ports[1]);
|
||||
try {
|
||||
await expect(
|
||||
stageManagedCodexCredential({
|
||||
@@ -265,7 +282,7 @@ describe("managed Codex credentials", () => {
|
||||
'{"sentinel":true}',
|
||||
);
|
||||
} finally {
|
||||
await Promise.all([first.close(), second.close()]);
|
||||
await occupied.close();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1654,7 +1671,7 @@ async function credentialFixture(): Promise<{ root: string; home: string }> {
|
||||
|
||||
async function silentPrimaryQuorumFixture(
|
||||
nextFixture = credentialFixture,
|
||||
occupiedIndex: 0 | 1 = 0,
|
||||
occupiedIndex: 0 | 1 | "quorum" = 0,
|
||||
) {
|
||||
for (let attempt = 0; attempt < 8; attempt += 1) {
|
||||
const fixture = await nextFixture();
|
||||
@@ -1674,22 +1691,27 @@ async function silentPrimaryQuorumFixture(
|
||||
continue;
|
||||
throw error;
|
||||
}
|
||||
// Only fixture preparation may retry. Release the two free candidates
|
||||
// immediately before the caller stages once. A foreign bind racing this
|
||||
// handoff remains a visible production-call failure, never a hidden retry.
|
||||
const occupiedIndices = occupiedIndex === "quorum" ? [0, 1] : [occupiedIndex];
|
||||
const occupied = {
|
||||
close: async () => {
|
||||
const closed = await Promise.allSettled(owned.filter((_, index) => occupiedIndices.includes(index)).map(listener => listener.close()));
|
||||
const failure = closed.find(result => result.status === "rejected");
|
||||
if (failure?.status === "rejected") throw failure.reason;
|
||||
},
|
||||
};
|
||||
const released = await Promise.allSettled(
|
||||
owned
|
||||
.filter((_, index) => index !== occupiedIndex)
|
||||
.filter((_, index) => !occupiedIndices.includes(index))
|
||||
.map((listener) => listener.close()),
|
||||
);
|
||||
const releaseFailure = released.find(
|
||||
(result) => result.status === "rejected",
|
||||
);
|
||||
if (releaseFailure?.status === "rejected") {
|
||||
await owned[occupiedIndex]!.close();
|
||||
await occupied.close();
|
||||
throw releaseFailure.reason;
|
||||
}
|
||||
return { fixture, occupied: owned[occupiedIndex]! };
|
||||
return { fixture, occupied };
|
||||
}
|
||||
throw new Error("Silent-primary credential fixture reservation exhausted.");
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user