test: await verified ChatGPT storage recovery completion

This commit is contained in:
amosblomqvist
2026-10-25 02:45:13 +03:00
parent 9171a4f49c
commit 6ca4452719
+38 -6
View File
@@ -337,9 +337,25 @@ for (const holdVerification of [false, true]) test(`invalid rotating replacement
} finally { f.service.close(); }
});
test("observed file write failure invalidates all work; status, consent and resume cannot reload stale credentials or repair authority", async () => {
for (const holdVerification of [false, true]) test(`observed file write failure invalidates all work; status, consent and resume cannot reload stale credentials or repair authority${holdVerification ? " (held JWKS regression)" : ""}`, { timeout: 10000 }, async () => {
let lost = false, reads = 0; const pushes: any[] = [];
const f = await loggedIn({ read: () => { reads++; }, write: async () => { if (lost) throw Object.assign(new Error("storage"), { code: "storage" }); }, change: (push) => pushes.push(push) });
const reconnectComplete = deferred<any>();
const verificationEntered = deferred(), verificationRelease = deferred();
let reconnectArmed = false, sawPending = false, completed = false;
const f = await loggedIn({ read: () => { reads++; }, write: async () => { if (lost) throw Object.assign(new Error("storage"), { code: "storage" }); },
change: (push) => {
pushes.push(push);
if (!reconnectArmed) return;
if (push.status.pending) sawPending = true;
else if (sawPending) { completed = true; reconnectComplete.resolve(push.status); }
},
provider: async (url) => {
if (holdVerification && reconnectArmed && url.endsWith("jwks.json")) {
verificationEntered.resolve(); await verificationRelease.promise;
}
return undefined;
},
});
try {
await f.service.lease(false); const epoch = f.service.stamp().epoch;
lost = true;
@@ -351,10 +367,26 @@ test("observed file write failure invalidates all work; status, consent and resu
await assert.rejects(f.service.lease(false));
assert.equal((await f.service.status()).accounts[0].connected, false);
assert.equal(reads, 1, "a recovered disk never causes a stale credential reload");
await f.service.login(f.saved.activeId); await f.callback();
for (let i = 0; i < 100 && (await f.service.status()).pending; i++) await new Promise((resolve) => setImmediate(resolve));
assert.equal((await f.service.status()).accounts[0].connected, true, "verified login plus durable save can explicitly reconnect");
} finally { f.service.close(); }
const writesBeforeReconnect = f.writeCount;
// The initial login already settled fixture.changed; observe this attempt instead.
reconnectArmed = true;
await f.service.login(f.saved.activeId); assert.equal(sawPending, true); await f.callback();
if (holdVerification) {
await verificationEntered.promise;
assert.equal(completed, false, "HTTP acknowledgement cannot complete a pending identity verification");
const held = await f.service.status();
assert.equal(held.pending, true); assert.equal(held.error, null);
assert.equal(held.accounts[0].connected, false);
assert.equal(f.writeCount, writesBeforeReconnect, "unverified recovery cannot persist credentials");
}
verificationRelease.resolve();
const terminal = await reconnectComplete.promise;
assert.equal(terminal.pending, false); assert.equal(terminal.error, null);
assert.equal(terminal.accounts[0].connected, true, "verified login plus durable save can explicitly reconnect");
assert.equal(f.writeCount, writesBeforeReconnect + 1, "recovery requires a new durable credential write");
assert.equal(f.saved.activeId, terminal.activeId);
assert.equal(reads, 1, "explicit recovery still never reloads stale credentials");
} finally { verificationRelease.resolve(); f.service.close(); }
});
test("strict JSON schema rejects malformed marker/duplicates/token/active identity without changing original bytes", async () => {