t3-code-android-nightly/packages/contracts/src/clientRpcPermissions.ts
Julius Marminge 2eda8ac6a3
feat(auth): separate source control write permissions (#9787)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-10-06 20:30:11 -07:00

59 lines
3 KiB
TypeScript

import * as Schema from "effect/Schema";
import { GitPreparePullRequestThreadInput } from "./git.ts";
import {
AuthOrchestrationOperateScope,
AuthSourceControlWriteScope,
type AuthEnvironmentScope,
} from "./auth.ts";
import { WS_METHODS } from "./rpc.ts";
/** Incremental client enforcement; the server still authorizes every request. */
export const CLIENT_GUARDED_RPC_SCOPES = {
[WS_METHODS.pullRequestsRunAction]: AuthSourceControlWriteScope,
[WS_METHODS.pullRequestsUpdate]: AuthSourceControlWriteScope,
[WS_METHODS.pullRequestsComment]: AuthSourceControlWriteScope,
[WS_METHODS.pullRequestsUpdateComment]: AuthSourceControlWriteScope,
[WS_METHODS.pullRequestsSubmitReview]: AuthSourceControlWriteScope,
[WS_METHODS.pullRequestsReplyToThread]: AuthSourceControlWriteScope,
[WS_METHODS.pullRequestsSetThreadResolution]: AuthSourceControlWriteScope,
[WS_METHODS.pullRequestsSetReaction]: AuthSourceControlWriteScope,
[WS_METHODS.pullRequestsSetFilesViewed]: AuthSourceControlWriteScope,
[WS_METHODS.pullRequestsRequestReviewers]: AuthSourceControlWriteScope,
[WS_METHODS.pullRequestsSetLabels]: AuthSourceControlWriteScope,
[WS_METHODS.sourceControlCloneRepository]: AuthSourceControlWriteScope,
[WS_METHODS.sourceControlPublishRepository]: AuthSourceControlWriteScope,
[WS_METHODS.projectCloneStart]: AuthSourceControlWriteScope,
[WS_METHODS.projectCloneCancel]: AuthSourceControlWriteScope,
[WS_METHODS.projectCloneRetry]: AuthSourceControlWriteScope,
[WS_METHODS.vcsPull]: AuthSourceControlWriteScope,
[WS_METHODS.gitRunStackedAction]: AuthSourceControlWriteScope,
[WS_METHODS.gitPreparePullRequestThread]: AuthSourceControlWriteScope,
[WS_METHODS.vcsCreateWorktree]: AuthSourceControlWriteScope,
[WS_METHODS.vcsRemoveWorktree]: AuthSourceControlWriteScope,
[WS_METHODS.vcsCreateRef]: AuthSourceControlWriteScope,
[WS_METHODS.vcsSwitchRef]: AuthSourceControlWriteScope,
[WS_METHODS.vcsInit]: AuthSourceControlWriteScope,
[WS_METHODS.scheduledTasksUpsert]: AuthOrchestrationOperateScope,
[WS_METHODS.scheduledTasksSetEnabled]: AuthOrchestrationOperateScope,
[WS_METHODS.scheduledTasksDelete]: AuthOrchestrationOperateScope,
[WS_METHODS.scheduledTasksRunNow]: AuthOrchestrationOperateScope,
[WS_METHODS.scheduledTasksRotateWebhookToken]: AuthOrchestrationOperateScope,
} as const;
export type ClientGuardedRpcTag = keyof typeof CLIENT_GUARDED_RPC_SCOPES;
const decodePrepareThread = Schema.decodeUnknownSync(GitPreparePullRequestThreadInput);
export function clientRpcRequiredScopes(
method: string,
input: unknown,
): readonly AuthEnvironmentScope[] {
if (method === WS_METHODS.gitPreparePullRequestThread && input !== undefined) {
const payload = decodePrepareThread(input);
if (payload.mode === "worktree" && payload.threadId !== undefined)
return [AuthSourceControlWriteScope, AuthOrchestrationOperateScope];
}
return Object.hasOwn(CLIENT_GUARDED_RPC_SCOPES, method)
? [CLIENT_GUARDED_RPC_SCOPES[method as ClientGuardedRpcTag]]
: [];
}