吸收数字员工风险策略远端下发

This commit is contained in:
baiyanyun
2026-06-11 09:51:14 +08:00
parent 8ab3d73fb1
commit e9c76c59ca
15 changed files with 1175 additions and 192 deletions

View File

@@ -215,6 +215,88 @@ describe("digital employee sync service", () => {
});
});
it("pulls remote risk approval policy and records UI state", async () => {
mockState.fetch.mockResolvedValue(jsonResponse({
success: true,
data: {
risk_approval_policy: {
enabled: true,
approval_required_risk_levels: ["critical"],
approval_required_actions: ["governance.run_schedule_now"],
auto_reject_actions: ["artifact.access.open_location"],
updated_at: "2026-06-07T08:02:00.000Z",
},
},
}));
const { pullDigitalEmployeeRiskApprovalPolicy } = await import("./syncService");
const { readDigitalEmployeeUiState } = await import("./stateService");
const result = await pullDigitalEmployeeRiskApprovalPolicy({ force: true });
expect(result).toMatchObject({
ok: true,
endpoint: "https://manage.example.com/api/digital-employee/policies/risk-approval",
policy: {
source: "remote",
approval_required_risk_levels: ["critical"],
approval_required_actions: ["governance.run_schedule_now"],
auto_reject_actions: ["artifact.access.open_location"],
remote_updated_at: "2026-06-07T08:02:00.000Z",
last_pulled_at: "2026-06-07T08:00:00.000Z",
last_pull_error: null,
},
});
expect(mockState.fetch).toHaveBeenCalledWith(
"https://manage.example.com/api/digital-employee/policies/risk-approval",
expect.objectContaining({ method: "GET" }),
);
expect(readDigitalEmployeeUiState().riskApprovalPolicy).toMatchObject(result.policy);
expect(Array.from(mockState.db?.events.values() ?? [])).toEqual(expect.arrayContaining([
expect.objectContaining({ kind: "digital_workday_pull_risk_approval_policy" }),
]));
});
it("keeps current risk approval policy when pull fails", async () => {
mockState.fetch.mockResolvedValue({
ok: false,
status: 503,
text: vi.fn().mockResolvedValue(JSON.stringify({ message: "risk policy unavailable" })),
} as unknown as Response);
const { pullDigitalEmployeeRiskApprovalPolicy } = await import("./syncService");
const result = await pullDigitalEmployeeRiskApprovalPolicy({ force: true });
expect(result).toMatchObject({
ok: false,
error: "risk policy unavailable",
policy: {
source: "local",
approval_required_risk_levels: ["high", "critical"],
last_pulled_at: "2026-06-07T08:00:00.000Z",
last_pull_error: "risk policy unavailable",
},
});
});
it.each([
["riskApprovalPolicy"],
["policy"],
])("pulls remote risk approval policy from data.%s", async (fieldName) => {
mockState.fetch.mockResolvedValue(jsonResponse({
success: true,
data: {
[fieldName]: {
approvalRequiredActions: ["managed_service.restart.fileServer"],
},
},
}));
const { pullDigitalEmployeeRiskApprovalPolicy } = await import("./syncService");
const result = await pullDigitalEmployeeRiskApprovalPolicy({ force: true });
expect(result.policy.approval_required_actions).toEqual(["managed_service.restart.fileServer"]);
});
it.each([
["skillPolicies"],
["policies"],
@@ -1017,6 +1099,21 @@ describe("digital employee sync service", () => {
},
},
});
insertEventEntity("event-risk-approval", "risk_approval_required", {
action_kind: "managed_service.restart.crm-sync",
action_label: "重启 CRM 同步服务",
risk_level: "high",
decision: "approval_required",
status: "pending",
reason_codes: ["risk_level_requires_approval"],
policy_source: "remote",
approval_id: "risk-approval-1",
correlation_id: "restart-1",
actor: "operator",
plan_id: "plan-1",
task_id: "task-1",
run_id: "run-1",
});
mockState.fetch.mockResolvedValue(
jsonResponse({
success: true,
@@ -1037,6 +1134,7 @@ describe("digital employee sync service", () => {
{ entity_type: "event", entity_id: "event-approval-subscriptions" },
{ entity_type: "event", entity_id: "event-plan-step-policy" },
{ entity_type: "event", entity_id: "event-plan-step-policy-pull" },
{ entity_type: "event", entity_id: "event-risk-approval" },
],
}),
);
@@ -1219,6 +1317,22 @@ describe("digital employee sync service", () => {
remote_updated_at: "2026-06-07T08:08:00.000Z",
last_pulled_at: "2026-06-07T08:09:00.000Z",
});
expect(businessView("event-risk-approval")).toMatchObject({
category: "approval",
action_kind: "managed_service.restart.crm-sync",
action_label: "重启 CRM 同步服务",
risk_level: "high",
decision: "approval_required",
status: "pending",
reason_codes: ["risk_level_requires_approval"],
policy_source: "remote",
approval_id: "risk-approval-1",
correlation_id: "restart-1",
actor: "operator",
plan_id: "plan-1",
task_id: "task-1",
run_id: "run-1",
});
expect(readEntity("event", "event-route")).toMatchObject({
sync_status: "synced",
sync_error: null,