
























@@ -1,4 +1,4 @@
1-import { readFile, writeFile } from "node:fs/promises";
1+import { mkdir, readFile, writeFile } from "node:fs/promises";
22import { afterAll, beforeAll, describe, expect, test } from "vitest";
33import { PAIRING_SETUP_BOOTSTRAP_PROFILE } from "../shared/device-bootstrap-profile.js";
44import { createSuiteTempRootTracker } from "../test-helpers/temp-dir.js";
@@ -161,6 +161,42 @@ describe("device pairing tokens", () => {
161161expect(second.request.requestId).toBe(first.request.requestId);
162162});
163163164+test("recovers when pairing state files were written as arrays", async () => {
165+const baseDir = await makeDevicePairingDir();
166+const paths = resolvePairingPaths(baseDir, "devices");
167+await mkdir(paths.dir, { recursive: true });
168+await writeFile(paths.pendingPath, "[]", "utf8");
169+await writeFile(paths.pairedPath, "[]", "utf8");
170+171+const pending = await requestDevicePairing(
172+{
173+deviceId: "device-array-state",
174+publicKey: "public-key-array-state",
175+role: "operator",
176+scopes: ["operator.read"],
177+},
178+baseDir,
179+);
180+const approved = await approveDevicePairing(
181+pending.request.requestId,
182+{ callerScopes: ["operator.read"] },
183+baseDir,
184+);
185+186+expect(approved).toEqual(
187+expect.objectContaining({
188+status: "approved",
189+device: expect.objectContaining({ deviceId: "device-array-state" }),
190+}),
191+);
192+expect(Array.isArray(JSON.parse(await readFile(paths.pendingPath, "utf8")))).toBe(false);
193+expect(JSON.parse(await readFile(paths.pairedPath, "utf8"))).toEqual(
194+expect.objectContaining({
195+"device-array-state": expect.objectContaining({ deviceId: "device-array-state" }),
196+}),
197+);
198+});
199+164200test("re-requesting with identical params preserves the original ts to prevent queue-jumping", async () => {
165201// Regression: refreshPendingDevicePairingRequest must not bump ts to Date.now().
166202// An attacker who reconnects with the same key/role/scopes could otherwise
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。