Files
Agent-System/web/src/lib/currentDocRole.ts
T
weichenandCursor cf3d126436 feat(web): never name-escalate server controlled zero duty ids
Mark server summaries dutiesAuthoritative so id 0 stays fail-closed
viewer instead of matching names like a legacy local document.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-13 17:08:35 +00:00

46 lines
1.6 KiB
TypeScript

import type { UserRole } from '../types/docgov';
export type ResolveCurrentDocRoleInput = {
currentUser: { id: number; name: string };
authorId?: number;
reviewerId?: number;
approverId?: number;
author?: string;
reviewer?: string;
approver?: string;
projectPermission?: string;
isLegacyLocalDoc?: boolean;
dutiesAuthoritative?: boolean;
governanceMode?: 'controlled' | 'freeform';
};
function hasAuthoritativeDutyId(input: ResolveCurrentDocRoleInput): boolean {
return Boolean(input.authorId || input.reviewerId || input.approverId);
}
function isAuthoritativeDutySource(input: ResolveCurrentDocRoleInput): boolean {
return input.dutiesAuthoritative === true || input.governanceMode === 'controlled';
}
/**
* 按权威 user id 解析文档职责。未知身份 fail-closed 为 viewer。
* name 匹配仅用于真正旧本地文档;服务端受控即使 duty id 为 0 也不得按 name 提权。
*/
export function resolveCurrentDocRole(input: ResolveCurrentDocRoleInput): UserRole {
const uid = input.currentUser.id;
if (isAuthoritativeDutySource(input) || hasAuthoritativeDutyId(input)) {
if (input.authorId && input.authorId === uid) return 'author';
if (input.reviewerId && input.reviewerId === uid) return 'reviewer';
if (input.approverId && input.approverId === uid) return 'approver';
return 'viewer';
}
if (input.isLegacyLocalDoc) {
if (input.author && input.author === input.currentUser.name) return 'author';
if (input.reviewer && input.reviewer === input.currentUser.name) return 'reviewer';
if (input.approver && input.approver === input.currentUser.name) return 'approver';
}
return 'viewer';
}