diff --git a/src/cli/nodes-cli/register.status.ts b/src/cli/nodes-cli/register.status.ts index e7d0aa69505..2ae92afd04c 100644 --- a/src/cli/nodes-cli/register.status.ts +++ b/src/cli/nodes-cli/register.status.ts @@ -128,6 +128,7 @@ function shouldFallbackToPairList(error: unknown): boolean { message.includes("unknown method") || message.includes("method not found") || message.includes("invalid request") || + message.includes("missing scope: operator.read") || message.includes("not implemented") || message.includes("unsupported") ); diff --git a/src/cli/program.nodes-basic.e2e.test.ts b/src/cli/program.nodes-basic.e2e.test.ts index 80b5bb13305..13e4d97e218 100644 --- a/src/cli/program.nodes-basic.e2e.test.ts +++ b/src/cli/program.nodes-basic.e2e.test.ts @@ -211,6 +211,35 @@ describe("cli program (nodes basics)", () => { expect(output).toContain("One"); }); + it("runs nodes list and falls back to node.pair.list on missing read scope", async () => { + callGateway.mockImplementation(async (...args: unknown[]) => { + const opts = (args[0] ?? {}) as { method?: string }; + if (opts.method === "node.pair.list") { + return { + pending: [], + paired: [ + { + nodeId: "n1", + displayName: "One", + remoteIp: "10.0.0.1", + lastConnectedAtMs: Date.now() - 1_000, + }, + ], + }; + } + if (opts.method === "node.list") { + throw new Error("missing scope: operator.read"); + } + return { ok: true }; + }); + + await runProgram(["nodes", "list"]); + + const output = getRuntimeOutput(); + expect(output).toContain("Pending: 0 ยท Paired: 1"); + expect(output).toContain("One"); + }); + it("fails clearly for nodes list --connected when node.list is unavailable", async () => { callGateway.mockImplementation(async (...args: unknown[]) => { const opts = (args[0] ?? {}) as { method?: string };