@stalfh233/omc-fake-platform 0.4.80 → 0.4.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -322,6 +322,15 @@ export const runtimeDataRoute = (ctx, input) => {
322
322
  const replayRefusal = verifyReplayToken(ctx.state, body);
323
323
  if (replayRefusal)
324
324
  return replayRefusal;
325
+ // Opt-in 40009 fidelity (real 1.1.25, WorkflowAspect.validateWorkflowPermission):
326
+ // starting a workflow requires a matching h_workflow_permission row, and
327
+ // publishing a flow creates none. Default off — the diagnostic test sets it.
328
+ if (ctx.state.enforceWorkflowStartPermission === true) {
329
+ const startCode = String(body.workflowCode ?? "");
330
+ const hasPermission = [...ctx.state.workflowPermissions.values()].some((row) => row.workflowCode === startCode);
331
+ if (!hasPermission)
332
+ return businessRefusal(40009, "流程发起权限不足");
333
+ }
325
334
  const bizObject = (body.bizObject ?? {});
326
335
  // WorkItemSubmitVO carries no top-level bizObjectId (ticket 22): the
327
336
  // created id comes from bizObject.id only — a top-level key is an
package/dist/state.d.ts CHANGED
@@ -380,6 +380,22 @@ export interface FakeState {
380
380
  roleIds: string[];
381
381
  deptIds?: string[];
382
382
  }>;
383
+ /** Workflow start permissions (h_workflow_permission): who may originate. */
384
+ workflowPermissions: Map<string, {
385
+ id: string;
386
+ workflowCode: string;
387
+ unitId: string;
388
+ unitType: string;
389
+ name: string | null;
390
+ code: string | null;
391
+ }>;
392
+ /**
393
+ * Opt-in fidelity: when true a workflow START submit answers 40009 unless the
394
+ * workflow has at least one start-permission row (real 1.1.25 requires a
395
+ * matching h_workflow_permission row, and publishing creates none). Default
396
+ * false so existing flows keep working; the 40009 diagnostic test sets it.
397
+ */
398
+ enforceWorkflowStartPermission: boolean;
383
399
  workflows: Map<string, FakeWorkflow>;
384
400
  workItems: Map<string, FakeWorkItem>;
385
401
  dataRows: Map<string, Record<string, unknown>>;
package/dist/state.js CHANGED
@@ -64,6 +64,8 @@ export function createFakeState(options = {}) {
64
64
  orgUsers: new Map(),
65
65
  orgRoles: new Map(),
66
66
  orgMembers: new Map(),
67
+ workflowPermissions: new Map(),
68
+ enforceWorkflowStartPermission: false,
67
69
  workflows: new Map(),
68
70
  workItems: new Map(),
69
71
  dataRows: new Map(),
package/dist/workflow.js CHANGED
@@ -314,6 +314,42 @@ export const workflowRoute = (ctx, input) => {
314
314
  wf.published = { ...body, templateType: "PUBLISH", workflowVersion: (wf.published ? Number(wf.published.workflowVersion ?? 1) : 0) + 1 };
315
315
  return { code, workflowVersion: wf.published.workflowVersion };
316
316
  }
317
+ case "/api/api/workflow/list_permission": {
318
+ const workflowCode = String(q.workflowCode ?? "");
319
+ const rows = [...ctx.state.workflowPermissions.values()].filter((row) => row.workflowCode === workflowCode);
320
+ // Live face (WorkflowTemplateController.listPermissions): id/name/unitType/
321
+ // fullName/corpId/code — unitId is deliberately NOT echoed.
322
+ return rows.map((row) => ({
323
+ id: row.id,
324
+ name: row.name ?? row.unitId,
325
+ unitType: row.unitType === "DEPARTMENT" ? 1 : row.unitType === "ROLE" ? 2 : 3,
326
+ fullName: row.name ?? row.unitId,
327
+ corpId: "corp-1",
328
+ code: row.code ?? row.unitId,
329
+ }));
330
+ }
331
+ case "/api/api/workflow/create_permission": {
332
+ const workflowCode = String(body.workflowCode ?? "");
333
+ const unitId = String(body.unitId ?? "");
334
+ if (!ctx.state.workflows.has(workflowCode))
335
+ return businessRefusal(401001, "流程不存在!");
336
+ if (!unitId)
337
+ return businessRefusal(40000, "id为空");
338
+ const unitType = Number(body.unitType ?? 0) === 1 ? "DEPARTMENT" : Number(body.unitType ?? 0) === 2 ? "ROLE" : "USER";
339
+ if ([...ctx.state.workflowPermissions.values()].some((row) => row.workflowCode === workflowCode && row.unitId === unitId))
340
+ return businessRefusal(402003, "流程发起权限已存在!");
341
+ const id = `wfp-${ctx.state.workflowPermissions.size + 1}`;
342
+ const name = unitType === "DEPARTMENT" ? (ctx.state.orgDepartments.get(unitId)?.name ?? "总所") : unitType === "ROLE" ? (ctx.state.orgRoles.get(unitId)?.name ?? null) : (ctx.state.orgUsers.get(unitId)?.name ?? null);
343
+ ctx.state.workflowPermissions.set(id, { id, workflowCode, unitId, unitType, name, code: unitId });
344
+ return null;
345
+ }
346
+ case "/api/api/workflow/delete_permission": {
347
+ const permissionId = String(q.permissionId ?? body.permissionId ?? "");
348
+ if (!permissionId)
349
+ return businessRefusal(40000, "权限id为空");
350
+ ctx.state.workflowPermissions.delete(permissionId);
351
+ return null;
352
+ }
317
353
  case "/api/api/workflow/delete":
318
354
  ctx.state.workflows.delete(String(body.workflowCode ?? q.workflowCode ?? q.code ?? ""));
319
355
  return null;
@@ -411,10 +447,17 @@ export const workflowRoute = (ctx, input) => {
411
447
  return dept;
412
448
  }
413
449
  case "/api/api/organization/department/get_dept_info": {
414
- const dept = ctx.state.orgDepartments.get(String(q.deptId ?? ""));
415
- if (!dept)
416
- return businessRefusal(10011, "部门不存在");
417
- return dept;
450
+ const wanted = String(q.deptId ?? "");
451
+ const dept = ctx.state.orgDepartments.get(wanted);
452
+ if (dept)
453
+ return dept;
454
+ // The static tree roots live outside `orgDepartments`; resolve them so a
455
+ // caller can name a real department (r11: workflow start permission needs
456
+ // the unit's display name, which reads this face).
457
+ const staticDept = [{ id: "dept-1", name: "总所", code: "1", corpId: "corp-1", parentId: null }, { id: "dept-2", name: "业务部", code: "1_1", corpId: "corp-1", parentId: "dept-1" }].find((entry) => entry.id === wanted);
458
+ if (staticDept)
459
+ return staticDept;
460
+ return businessRefusal(10011, "部门不存在");
418
461
  }
419
462
  case "/api/api/organization/department/strike_out": {
420
463
  const deptId = String(q.id ?? "");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stalfh233/omc-fake-platform",
3
- "version": "0.4.80",
3
+ "version": "0.4.82",
4
4
  "description": "OMC 的内存假 CloudPivot 平台(wire 接缝的第二个适配器)+ HTTP 假服务器——@stalfh233/omc-cli 的测试与 bench 基准基座",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -18,7 +18,7 @@
18
18
  "build": "tsc --project tsconfig.build.json"
19
19
  },
20
20
  "dependencies": {
21
- "omc-core": "0.4.80"
21
+ "omc-core": "0.4.82"
22
22
  },
23
23
  "engines": {
24
24
  "node": ">=22.13"