73 lines · 2.8 KB · TypeScript
RawDownload
import {  AuthOrchestrationOperateScope,  AuthOrchestrationReadScope,  AuthRelayReadScope,  AuthRelayWriteScope,  WS_METHODS,  WsRpcGroup,} from "@t3tools/contracts";import { describe, expect, it } from "@effect/vitest"; import { RPC_REQUIRED_SCOPES, requiredScopeForRpcMethod } from "./RpcAuthorization.ts"; describe("RPC authorization scopes", () => {  it("declares exactly one scope for every RPC in the server group", () => {    expect(new Set(Object.keys(RPC_REQUIRED_SCOPES))).toEqual(new Set(WsRpcGroup.requests.keys()));  });   it("authorizes background policy reporting and observation deliberately", () => {    expect(requiredScopeForRpcMethod(WS_METHODS.serverReportClientActivity)).toBe(      AuthOrchestrationReadScope,    );    expect(requiredScopeForRpcMethod(WS_METHODS.serverReportHostPowerState)).toBe(      AuthOrchestrationOperateScope,    );    expect(requiredScopeForRpcMethod(WS_METHODS.serverGetBackgroundPolicy)).toBe(      AuthOrchestrationReadScope,    );    expect(requiredScopeForRpcMethod(WS_METHODS.subscribeBackgroundPolicy)).toBe(      AuthOrchestrationReadScope,    );  });   it("allows relay status reads without granting relay installation access", () => {    expect(requiredScopeForRpcMethod(WS_METHODS.cloudGetRelayClientStatus)).toBe(      AuthRelayReadScope,    );    expect(requiredScopeForRpcMethod(WS_METHODS.cloudInstallRelayClient)).toBe(AuthRelayWriteScope);  });   it("requires permission to operate on a thread before uploading feedback", () => {    expect(requiredScopeForRpcMethod(WS_METHODS.providerUploadFeedback)).toBe(      AuthOrchestrationOperateScope,    );  });   it("requires write access to import agent session history", () => {    expect(requiredScopeForRpcMethod(WS_METHODS.agentSessionsScan)).toBe(      AuthOrchestrationReadScope,    );    expect(requiredScopeForRpcMethod(WS_METHODS.agentSessionsImport)).toBe(      AuthOrchestrationOperateScope,    );  });   it("reads the reviewer menu under the same scope as the pull request it belongs to", () => {    // The candidate list is a read like the detail beside it, and asking somebody for a review is    // a write like every other pull request operation.    expect(requiredScopeForRpcMethod(WS_METHODS.pullRequestsReviewerCandidates)).toBe(      requiredScopeForRpcMethod(WS_METHODS.pullRequestsDetail),    );    expect(requiredScopeForRpcMethod(WS_METHODS.pullRequestsRequestReviewers)).toBe(      requiredScopeForRpcMethod(WS_METHODS.pullRequestsComment),    );  });   it("rejects unknown RPC method names", () => {    for (const method of ["server.notRegistered", "toString", "constructor"]) {      expect(() => requiredScopeForRpcMethod(method)).toThrow(        `RPC method ${method} has no declared authorization scope.`,      );    }  });});