feat: add memindadm runtime policy for agent code runs (Phase 1.5)
Persist code-run gates in admin DB and expose them via /auth/status so H5 can honor runtime policy without VITE rebuilds. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+42
-23
@@ -56,12 +56,32 @@ export function createPostAgentRunsHandler({
|
||||
sessionAccess = null,
|
||||
agentRunGateway,
|
||||
mindSpaceAssetAgent = null,
|
||||
codeRunPolicyService = null,
|
||||
codeRunsEnabled = envFlag(process.env.MEMIND_AGENT_CODE_RUNS_ENABLED),
|
||||
codeRunUserIds = parseUserIdSet(process.env.MEMIND_AGENT_CODE_RUNS_USER_IDS),
|
||||
codeRunTaskTypes = parseTaskTypeSet(process.env.MEMIND_AGENT_CODE_RUN_TASK_TYPES),
|
||||
requireCodeRunValidation = envFlag(process.env.MEMIND_AGENT_CODE_RUNS_REQUIRE_VALIDATION),
|
||||
}) {
|
||||
const sessionStore = sessionAccess ?? createSessionAccess({ userAuth, enabled: false });
|
||||
|
||||
async function resolveCodeRunPolicy(userId) {
|
||||
if (codeRunPolicyService?.getEffectivePolicy) {
|
||||
return codeRunPolicyService.getEffectivePolicy(userId);
|
||||
}
|
||||
return {
|
||||
source: 'env',
|
||||
enabled: codeRunsEnabled,
|
||||
clientEnabled: codeRunsEnabled,
|
||||
generalAutodetect: false,
|
||||
pageDataDevAutodetect: false,
|
||||
requireValidation: requireCodeRunValidation,
|
||||
userAllowlist: [...codeRunUserIds],
|
||||
taskTypeAllowlist: [...codeRunTaskTypes],
|
||||
userAllowed:
|
||||
!codeRunUserIds.size || codeRunUserIds.has(String(userId ?? '').trim()),
|
||||
};
|
||||
}
|
||||
|
||||
return async function postAgentRuns(request, response) {
|
||||
try {
|
||||
const sessionId = String(request.body?.session_id ?? '').trim() || null;
|
||||
@@ -87,29 +107,28 @@ export function createPostAgentRunsHandler({
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (toolMode === 'code' && !codeRunsEnabled) {
|
||||
response.status(403).json({ message: '代码任务灰度未开启' });
|
||||
return;
|
||||
}
|
||||
if (
|
||||
toolMode === 'code' &&
|
||||
codeRunUserIds.size > 0 &&
|
||||
!codeRunUserIds.has(request.currentUser.id)
|
||||
) {
|
||||
response.status(403).json({ message: '当前用户未开启代码任务灰度' });
|
||||
return;
|
||||
}
|
||||
if (
|
||||
toolMode === 'code' &&
|
||||
codeRunTaskTypes.size > 0 &&
|
||||
(!taskType || !codeRunTaskTypes.has(taskType.toLowerCase()))
|
||||
) {
|
||||
response.status(403).json({ message: '当前代码任务类型未开启灰度' });
|
||||
return;
|
||||
}
|
||||
if (toolMode === 'code' && requireCodeRunValidation && !hasExpectedFileValidation(userMessage)) {
|
||||
response.status(400).json({ message: '代码任务必须声明产物校验规则' });
|
||||
return;
|
||||
if (toolMode === 'code') {
|
||||
const codeRunPolicy = await resolveCodeRunPolicy(request.currentUser.id);
|
||||
if (!codeRunPolicy.enabled) {
|
||||
response.status(403).json({ message: '代码任务灰度未开启' });
|
||||
return;
|
||||
}
|
||||
if (!codeRunPolicy.userAllowed) {
|
||||
response.status(403).json({ message: '当前用户未开启代码任务灰度' });
|
||||
return;
|
||||
}
|
||||
const taskTypeAllowlist = codeRunPolicy.taskTypeAllowlist ?? [];
|
||||
if (
|
||||
taskTypeAllowlist.length > 0 &&
|
||||
(!taskType || !taskTypeAllowlist.map((item) => String(item).toLowerCase()).includes(taskType.toLowerCase()))
|
||||
) {
|
||||
response.status(403).json({ message: '当前代码任务类型未开启灰度' });
|
||||
return;
|
||||
}
|
||||
if (codeRunPolicy.requireValidation && !hasExpectedFileValidation(userMessage)) {
|
||||
response.status(400).json({ message: '代码任务必须声明产物校验规则' });
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (sessionId) {
|
||||
const owns = await sessionStore.validateOwnership(request.currentUser.id, sessionId);
|
||||
|
||||
Reference in New Issue
Block a user