






















@@ -333,6 +333,66 @@ describe("device pairing tokens", () => {
333333).resolves.toEqual({ ok: true });
334334});
335335336+test("preserves existing operator token scopes when approving a scope upgrade", async () => {
337+const baseDir = await makeDevicePairingDir();
338+await setupPairedOperatorDevice(baseDir, ["operator.read"]);
339+340+const upgrade = await requestDevicePairing(
341+{
342+deviceId: "device-1",
343+publicKey: "public-key-1",
344+role: "operator",
345+scopes: ["operator.write"],
346+},
347+baseDir,
348+);
349+350+await expect(
351+approveDevicePairing(
352+upgrade.request.requestId,
353+{ callerScopes: ["operator.read", "operator.write"] },
354+baseDir,
355+),
356+).resolves.toMatchObject({ status: "approved" });
357+358+const paired = await getPairedDevice("device-1", baseDir);
359+expect(paired?.approvedScopes).toEqual(["operator.read", "operator.write"]);
360+expect(paired?.tokens?.operator?.scopes).toEqual(["operator.read", "operator.write"]);
361+});
362+363+test("does not widen a down-scoped operator token when approving a scope upgrade", async () => {
364+const baseDir = await makeDevicePairingDir();
365+await setupPairedOperatorDevice(baseDir, ["operator.read", "operator.write"]);
366+await overwritePairedOperatorTokenScopes(baseDir, ["operator.read"]);
367+368+const upgrade = await requestDevicePairing(
369+{
370+deviceId: "device-1",
371+publicKey: "public-key-1",
372+role: "operator",
373+scopes: ["operator.talk.secrets"],
374+},
375+baseDir,
376+);
377+378+await expect(
379+approveDevicePairing(
380+upgrade.request.requestId,
381+{ callerScopes: ["operator.read", "operator.talk.secrets", "operator.write"] },
382+baseDir,
383+),
384+).resolves.toMatchObject({ status: "approved" });
385+386+const paired = await getPairedDevice("device-1", baseDir);
387+expect(paired?.approvedScopes).toEqual([
388+"operator.read",
389+"operator.write",
390+"operator.talk.secrets",
391+]);
392+expect(paired?.tokens?.operator?.scopes).toEqual(["operator.read", "operator.talk.secrets"]);
393+expect(paired?.tokens?.operator?.scopes).not.toContain("operator.write");
394+});
395+336396test("preserves requested non-operator scopes on newly minted role tokens", async () => {
337397const baseDir = await makeDevicePairingDir();
338398const request = await requestDevicePairing(
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。