吸收数字员工风险策略远端下发
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user