@hotmeshio/long-tail 0.22.0 → 0.22.1
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.
- package/build/api/escalations/accumulate.d.ts +10 -1
- package/build/api/escalations/accumulate.js +83 -15
- package/build/api/escalations/metadata.d.ts +5 -0
- package/build/api/escalations/metadata.js +6 -2
- package/build/api/scan-codes/choice.js +3 -2
- package/build/api/scan-codes/verbs.d.ts +6 -1
- package/build/api/scan-codes/verbs.js +13 -3
- package/build/api/workflows/invocation.d.ts +8 -4
- package/build/api/workflows/invocation.js +26 -9
- package/build/lib/cli/commands/workflows.js +9 -4
- package/build/routes/escalations/accumulate.js +13 -6
- package/build/sdk/index.d.ts +3 -0
- package/build/services/escalation/crud.d.ts +2 -2
- package/build/services/escalation/crud.js +4 -2
- package/build/services/escalation/facet-sql.js +8 -0
- package/build/services/escalation/sql.d.ts +4 -2
- package/build/services/escalation/sql.js +10 -2
- package/build/services/export/index.d.ts +8 -3
- package/build/services/export/index.js +15 -21
- package/build/services/pipelines/events.js +2 -1
- package/build/services/pipelines/execution-builder.js +2 -1
- package/build/services/pipelines/queries.js +2 -1
- package/build/services/scan-code/validate.js +19 -0
- package/build/services/workflow-state.d.ts +21 -0
- package/build/services/workflow-state.js +39 -0
- package/build/shared/workflow-state.d.ts +17 -0
- package/build/shared/workflow-state.js +29 -0
- package/build/system/mcp-servers/admin/escalations.js +8 -4
- package/build/system/mcp-servers/admin/schemas.d.ts +38 -0
- package/build/system/mcp-servers/admin/schemas.js +4 -0
- package/build/system/mcp-servers/admin/workflows.js +20 -31
- package/build/system/seed/tool-manifests-admin.d.ts +94 -0
- package/build/system/seed/tool-manifests-admin.js +3 -3
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/facets.d.ts +14 -0
- package/build/types/index.d.ts +1 -1
- package/build/types/scan-code.d.ts +10 -1
- package/build/types/scan-code.js +0 -11
- package/dashboard/dist/assets/{AdminDashboard-Covdam48.js → AdminDashboard-BbWve-Ax.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-Covdam48.js.map → AdminDashboard-BbWve-Ax.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-CE1k6J5r.js → AgentConfigPage-M-9eTKhP.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-CE1k6J5r.js.map → AgentConfigPage-M-9eTKhP.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-CWJZIZP1.js → AgentDetailPage-CsakSlx5.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-CWJZIZP1.js.map → AgentDetailPage-CsakSlx5.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage---Dg5ufF.js → AgentsPage-Cj_cRTT1.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage---Dg5ufF.js.map → AgentsPage-Cj_cRTT1.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-BXJmMBM1.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-BXJmMBM1.js.map +1 -0
- package/dashboard/dist/assets/{BotPicker-D3drO3-T.js → BotPicker-CGB16rYU.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-D3drO3-T.js.map → BotPicker-CGB16rYU.js.map} +1 -1
- package/dashboard/dist/assets/{BulkAssignModal-BOAWsViq.js → BulkAssignModal-MjxcU7N1.js} +2 -2
- package/dashboard/dist/assets/{BulkAssignModal-BOAWsViq.js.map → BulkAssignModal-MjxcU7N1.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-RGgD3YZO.js → CapabilitiesPage-BxadotXn.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-RGgD3YZO.js.map → CapabilitiesPage-BxadotXn.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-DNkZn87n.js → CollapsibleSection-BBNpP-6h.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-DNkZn87n.js.map → CollapsibleSection-BBNpP-6h.js.map} +1 -1
- package/dashboard/dist/assets/{ConfirmDeleteModal-BqzOwhPr.js → ConfirmDeleteModal-D_kAbT_D.js} +2 -2
- package/dashboard/dist/assets/{ConfirmDeleteModal-BqzOwhPr.js.map → ConfirmDeleteModal-D_kAbT_D.js.map} +1 -1
- package/dashboard/dist/assets/{CountdownTimer-BaexQMK6.js → CountdownTimer-CI_JOAvk.js} +2 -2
- package/dashboard/dist/assets/{CountdownTimer-BaexQMK6.js.map → CountdownTimer-CI_JOAvk.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-D7abp0aS.js → CredentialsPage-C9OA1Q2J.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-D7abp0aS.js.map → CredentialsPage-C9OA1Q2J.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-DZiWmTwJ.js → CronLabel-sxLLBf2I.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-DZiWmTwJ.js.map → CronLabel-sxLLBf2I.js.map} +1 -1
- package/dashboard/dist/assets/{DropZone-f1o-GLM8.js → DropZone-B1Tdfddc.js} +2 -2
- package/dashboard/dist/assets/{DropZone-f1o-GLM8.js.map → DropZone-B1Tdfddc.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-BdGO_w4v.js → ElapsedCell-jH9m8Dgl.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-BdGO_w4v.js.map → ElapsedCell-jH9m8Dgl.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-DIDcF5Yu.js → EntityTimelinePanel-Dl3Nr2kk.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-DIDcF5Yu.js.map → EntityTimelinePanel-Dl3Nr2kk.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-C28rn9XC.js → EscalationListSchemaPage-DAK6It5J.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-C28rn9XC.js.map → EscalationListSchemaPage-DAK6It5J.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListView-CkBnkpDJ.js → EscalationListView-CAHbdxKR.js} +2 -2
- package/dashboard/dist/assets/{EscalationListView-CkBnkpDJ.js.map → EscalationListView-CAHbdxKR.js.map} +1 -1
- package/dashboard/dist/assets/EscalationSchemaPage-DotfAMCL.js +9 -0
- package/dashboard/dist/assets/EscalationSchemaPage-DotfAMCL.js.map +1 -0
- package/dashboard/dist/assets/EscalationTimeline-DqmFydnU.js +2 -0
- package/dashboard/dist/assets/EscalationTimeline-DqmFydnU.js.map +1 -0
- package/dashboard/dist/assets/{EscalationTitleSelect-CzKfavri.js → EscalationTitleSelect-BpRquguO.js} +2 -2
- package/dashboard/dist/assets/{EscalationTitleSelect-CzKfavri.js.map → EscalationTitleSelect-BpRquguO.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-Tdu3Yx2c.js → EscalationsOverview-DtGOqnP4.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-Tdu3Yx2c.js.map → EscalationsOverview-DtGOqnP4.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-DiIxOJwO.js → EventTable-DSHqKyX2.js} +2 -2
- package/dashboard/dist/assets/{EventTable-DiIxOJwO.js.map → EventTable-DSHqKyX2.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-CvMBCVIo.js → FilterBar-Dxd0wNSW.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-CvMBCVIo.js.map → FilterBar-Dxd0wNSW.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-DO-yyhi6.js → GraphInvokePage-ChqqGkro.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-DO-yyhi6.js.map → GraphInvokePage-ChqqGkro.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-DSS3eHR2.js → HomePage-ByKesG8w.js} +2 -2
- package/dashboard/dist/assets/{HomePage-DSS3eHR2.js.map → HomePage-ByKesG8w.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-C3-Tqqub.js → ListToolbar-Ddz_S2av.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-C3-Tqqub.js.map → ListToolbar-Ddz_S2av.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-DEJmsdVi.js → McpOverview-CVe13tEv.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-DEJmsdVi.js.map → McpOverview-CVe13tEv.js.map} +1 -1
- package/dashboard/dist/assets/McpQueryDetailPage-BQYF2Mjq.js +5 -0
- package/dashboard/dist/assets/McpQueryDetailPage-BQYF2Mjq.js.map +1 -0
- package/dashboard/dist/assets/{McpQueryPage-BBcG_UuU.js → McpQueryPage-DZi5lm7s.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-BBcG_UuU.js.map → McpQueryPage-DZi5lm7s.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-C6xw0kBg.js → McpRunDetailPage-DreARTE1.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-C6xw0kBg.js.map → McpRunDetailPage-DreARTE1.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-CRQqrF4Q.js → McpRunsPage-DmO0YVhT.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-CRQqrF4Q.js.map → McpRunsPage-DmO0YVhT.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-DADRJOUl.js → NamespacePill-DwM5pNA4.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-DADRJOUl.js.map → NamespacePill-DwM5pNA4.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-Dlfwzf-0.js → OperationsPage-DpjCO85T.js} +2 -2
- package/dashboard/dist/assets/{OperationsPage-Dlfwzf-0.js.map → OperationsPage-DpjCO85T.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-DoiDGZ9R.js → OperatorDashboard-Vv_MEBkv.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-DoiDGZ9R.js.map → OperatorDashboard-Vv_MEBkv.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-Csq434-v.js → PageHeader-CMd3f4bz.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-Csq434-v.js.map → PageHeader-CMd3f4bz.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-CSnk1p5A.js → PageHeaderWithStats-DHj8Mqox.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-CSnk1p5A.js.map → PageHeaderWithStats-DHj8Mqox.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-BzbA4Prr.js → PersonaDetailPage-CW-2uBHY.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-BzbA4Prr.js.map → PersonaDetailPage-CW-2uBHY.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-B36yn4hU.js → PersonasPage-CO6yYQdm.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-B36yn4hU.js.map → PersonasPage-CO6yYQdm.js.map} +1 -1
- package/dashboard/dist/assets/{PortalPage-BkD4YfDf.js → PortalPage-DcNqhBlg.js} +2 -2
- package/dashboard/dist/assets/{PortalPage-BkD4YfDf.js.map → PortalPage-DcNqhBlg.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-BT0eiBWY.js → ProcessDetailPage-BuipGZcC.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-BT0eiBWY.js.map → ProcessDetailPage-BuipGZcC.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-BEqeeNae.js → ProcessesListPage-D9DYntvl.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-BEqeeNae.js.map → ProcessesListPage-D9DYntvl.js.map} +1 -1
- package/dashboard/dist/assets/ResolverForm-BVG8X0sS.js +8 -0
- package/dashboard/dist/assets/ResolverForm-BVG8X0sS.js.map +1 -0
- package/dashboard/dist/assets/{RoleDetailPage-BFuLNJXa.js → RoleDetailPage-KCXDqoJz.js} +3 -3
- package/dashboard/dist/assets/{RoleDetailPage-BFuLNJXa.js.map → RoleDetailPage-KCXDqoJz.js.map} +1 -1
- package/dashboard/dist/assets/{RolePill-BafrASDX.js → RolePill-Di2CAHuD.js} +2 -2
- package/dashboard/dist/assets/{RolePill-BafrASDX.js.map → RolePill-Di2CAHuD.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-80quJU5-.js → RolesPage-0QJOBSzF.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-80quJU5-.js.map → RolesPage-0QJOBSzF.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-BoePhWVD.js → RunAsSelector-Dh4lyyRo.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-BoePhWVD.js.map → RunAsSelector-Dh4lyyRo.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-Cu1bKEix.js → ScanCodesPage-CUhCz-Yr.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-Cu1bKEix.js.map → ScanCodesPage-CUhCz-Yr.js.map} +1 -1
- package/dashboard/dist/assets/{ScanSchemeDetailPage-D9AbS6UY.js → ScanSchemeDetailPage-qzXKNqJK.js} +2 -2
- package/dashboard/dist/assets/{ScanSchemeDetailPage-D9AbS6UY.js.map → ScanSchemeDetailPage-qzXKNqJK.js.map} +1 -1
- package/dashboard/dist/assets/{ScanStationPage-gcZGefvT.js → ScanStationPage-D8e8cG3t.js} +2 -2
- package/dashboard/dist/assets/{ScanStationPage-gcZGefvT.js.map → ScanStationPage-D8e8cG3t.js.map} +1 -1
- package/dashboard/dist/assets/{ScopeBadge-b6MIBiYD.js → ScopeBadge-CSItPVOH.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-b6MIBiYD.js.map → ScopeBadge-CSItPVOH.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-9ITrei_d.js → StickyPagination-BSUyf5ja.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-9ITrei_d.js.map → StickyPagination-BSUyf5ja.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-BkYvEHFY.js → StreamMessageDetail--tp7l2Sd.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-BkYvEHFY.js.map → StreamMessageDetail--tp7l2Sd.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-B1rotFix.js → SwimlaneTimeline-CxBZ2THh.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-B1rotFix.js.map → SwimlaneTimeline-CxBZ2THh.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-ZrIIrEUP.js → TagInput-CAgdLN_b.js} +2 -2
- package/dashboard/dist/assets/{TagInput-ZrIIrEUP.js.map → TagInput-CAgdLN_b.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-zhn_U_eC.js → TaskDetailPage-BJ1QrmPH.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-zhn_U_eC.js.map → TaskDetailPage-BJ1QrmPH.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-DkQ1uc6y.js → TaskQueuePill-h0oorVMe.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-DkQ1uc6y.js.map → TaskQueuePill-h0oorVMe.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-CNbNeagx.js → TasksListPage-5BydGWmt.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-CNbNeagx.js.map → TasksListPage-5BydGWmt.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-0YVMBwls.js → TimeAgo-CCnz84Y4.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-0YVMBwls.js.map → TimeAgo-CCnz84Y4.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-DB7r3np8.js → TimestampCell-D0ru7Lya.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-DB7r3np8.js.map → TimestampCell-D0ru7Lya.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-Baxm02L6.js → ToolPill-CQCsVdzD.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-Baxm02L6.js.map → ToolPill-CQCsVdzD.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-BLfA02wv.js → ToolTestPanel-3Kpofmen.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-BLfA02wv.js.map → ToolTestPanel-3Kpofmen.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-eAqPKShq.js → TopicDetailPage-BaBXD_AK.js} +4 -4
- package/dashboard/dist/assets/{TopicDetailPage-eAqPKShq.js.map → TopicDetailPage-BaBXD_AK.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-BNNWD-zl.js → TopicsPage-Cnm1AAjh.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-BNNWD-zl.js.map → TopicsPage-Cnm1AAjh.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-Pw46tO_k.js → UserName-CXsdPiMZ.js} +2 -2
- package/dashboard/dist/assets/{UserName-Pw46tO_k.js.map → UserName-CXsdPiMZ.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-DvA51lT3.js → WorkflowExecutionPage-zx3AUJFd.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-DvA51lT3.js.map → WorkflowExecutionPage-zx3AUJFd.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill-ZepbO_ny.js → WorkflowPill-Dg7BDTyM.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-ZepbO_ny.js.map → WorkflowPill-Dg7BDTyM.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-DFDTwnhn.js → WorkflowsDashboard-DfAGK1l7.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-DFDTwnhn.js.map → WorkflowsDashboard-DfAGK1l7.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-5i2Tcy-p.js → WorkflowsOverview-QIYvoa13.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-5i2Tcy-p.js.map → WorkflowsOverview-QIYvoa13.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-p4VEYZS0.js → YamlWorkflowDetailPage-DGgO3hyB.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-p4VEYZS0.js.map → YamlWorkflowDetailPage-DGgO3hyB.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-Cq-hMVxl.js → YamlWorkflowsPage-CEsHm0B9.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-Cq-hMVxl.js.map → YamlWorkflowsPage-CEsHm0B9.js.map} +1 -1
- package/dashboard/dist/assets/{agents-EyBPJMYa.js → agents-v_HH3Rji.js} +2 -2
- package/dashboard/dist/assets/{agents-EyBPJMYa.js.map → agents-v_HH3Rji.js.map} +1 -1
- package/dashboard/dist/assets/{bots-DX6jjqtF.js → bots-bwvWYrXz.js} +2 -2
- package/dashboard/dist/assets/{bots-DX6jjqtF.js.map → bots-bwvWYrXz.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-ZdLv9xBQ.js → capabilities-D4vaw_nQ.js} +2 -2
- package/dashboard/dist/assets/{capabilities-ZdLv9xBQ.js.map → capabilities-D4vaw_nQ.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-CpvZaJuw.js → controlplane-CiiZ6LJF.js} +2 -2
- package/dashboard/dist/assets/{controlplane-CpvZaJuw.js.map → controlplane-CiiZ6LJF.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-Mvsze5eV.js → escalation-columns-Dv-MB3eC.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-Mvsze5eV.js.map → escalation-columns-Dv-MB3eC.js.map} +1 -1
- package/dashboard/dist/assets/{index-oFKUFGQL.js → index-2tzsxFat.js} +2 -2
- package/dashboard/dist/assets/{index-oFKUFGQL.js.map → index-2tzsxFat.js.map} +1 -1
- package/dashboard/dist/assets/{index-DZhtP2Ok.js → index-BLB77tc8.js} +2 -2
- package/dashboard/dist/assets/{index-DZhtP2Ok.js.map → index-BLB77tc8.js.map} +1 -1
- package/dashboard/dist/assets/{index-PfSRKerc.js → index-C3WutFpT.js} +2 -2
- package/dashboard/dist/assets/{index-PfSRKerc.js.map → index-C3WutFpT.js.map} +1 -1
- package/dashboard/dist/assets/{index-DkrBFFSO.js → index-C4Lce2ET.js} +2 -2
- package/dashboard/dist/assets/{index-DkrBFFSO.js.map → index-C4Lce2ET.js.map} +1 -1
- package/dashboard/dist/assets/index-CT-FN6CW.js +3 -0
- package/dashboard/dist/assets/index-CT-FN6CW.js.map +1 -0
- package/dashboard/dist/assets/{index-Eo-l3Lqo.js → index-C_ISDOWJ.js} +2 -2
- package/dashboard/dist/assets/{index-Eo-l3Lqo.js.map → index-C_ISDOWJ.js.map} +1 -1
- package/dashboard/dist/assets/{index-Bhb89oHH.js → index-CcuvGdvf.js} +2 -2
- package/dashboard/dist/assets/{index-Bhb89oHH.js.map → index-CcuvGdvf.js.map} +1 -1
- package/dashboard/dist/assets/{index-BbCjGO3M.js → index-CjenRVX_.js} +2 -2
- package/dashboard/dist/assets/{index-BbCjGO3M.js.map → index-CjenRVX_.js.map} +1 -1
- package/dashboard/dist/assets/{index-DGmzBY9D.js → index-CzjUgFt_.js} +2 -2
- package/dashboard/dist/assets/{index-DGmzBY9D.js.map → index-CzjUgFt_.js.map} +1 -1
- package/dashboard/dist/assets/{index-D-Xs4rAW.js → index-D2VKBMng.js} +2 -2
- package/dashboard/dist/assets/{index-D-Xs4rAW.js.map → index-D2VKBMng.js.map} +1 -1
- package/dashboard/dist/assets/{index-z5Hpeidu.js → index-D6pBLZFu.js} +2 -2
- package/dashboard/dist/assets/{index-z5Hpeidu.js.map → index-D6pBLZFu.js.map} +1 -1
- package/dashboard/dist/assets/{index-Cn8uJsd7.js → index-IJmtbuLh.js} +2 -2
- package/dashboard/dist/assets/{index-Cn8uJsd7.js.map → index-IJmtbuLh.js.map} +1 -1
- package/dashboard/dist/assets/{index-CgUcYveM.js → index-N71QQ3J5.js} +5 -5
- package/dashboard/dist/assets/index-N71QQ3J5.js.map +1 -0
- package/dashboard/dist/assets/{knowledge-CgloEkaf.js → knowledge-D1YP2NzS.js} +2 -2
- package/dashboard/dist/assets/{knowledge-CgloEkaf.js.map → knowledge-D1YP2NzS.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-Bix7QYO7.js → mcp-Bb5psC61.js} +2 -2
- package/dashboard/dist/assets/{mcp-Bix7QYO7.js.map → mcp-Bb5psC61.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-o-sGX2ST.js → mcp-query-D5jUdZwN.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-o-sGX2ST.js.map → mcp-query-D5jUdZwN.js.map} +1 -1
- package/dashboard/dist/assets/{personas-30azkJ_s.js → personas-CDndbkp4.js} +2 -2
- package/dashboard/dist/assets/{personas-30azkJ_s.js.map → personas-CDndbkp4.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-Bfk2GFK7.js → pipelines-Dq3kNhKu.js} +2 -2
- package/dashboard/dist/assets/{pipelines-Bfk2GFK7.js.map → pipelines-Dq3kNhKu.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-CpdopewW.js → tasks-BlpDsWCy.js} +2 -2
- package/dashboard/dist/assets/{tasks-CpdopewW.js.map → tasks-BlpDsWCy.js.map} +1 -1
- package/dashboard/dist/assets/{topics--bvCV9Yp.js → topics-C0YaR9fu.js} +2 -2
- package/dashboard/dist/assets/{topics--bvCV9Yp.js.map → topics-C0YaR9fu.js.map} +1 -1
- package/dashboard/dist/assets/{useDebouncedValue-Da0lPmj3.js → useDebouncedValue-B-KC5ba3.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-Da0lPmj3.js.map → useDebouncedValue-B-KC5ba3.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-DD_Esl6n.js → useNamespace-Dkr5g2Ac.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-DD_Esl6n.js.map → useNamespace-Dkr5g2Ac.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-AeAhZJJk.js → useYamlActivityEvents-BANBOshA.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-AeAhZJJk.js.map → useYamlActivityEvents-BANBOshA.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-B7OcUM6b.js → vendor-icons-CeVtUKyP.js} +2 -2
- package/dashboard/dist/assets/{vendor-icons-B7OcUM6b.js.map → vendor-icons-CeVtUKyP.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-BHAOOGvn.js → yaml-workflows-BLYoJfmB.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-BHAOOGvn.js.map → yaml-workflows-BLYoJfmB.js.map} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/docs/accumulator.md +37 -1
- package/docs/api/mcp/admin.md +3 -2
- package/docs/api/sdk/escalations.md +6 -0
- package/docs/api/sdk/exports.md +1 -1
- package/docs/api/sdk/workflows.md +23 -4
- package/docs/cli.md +1 -1
- package/docs/dashboard.md +1 -1
- package/docs/faceted-routing.md +2 -0
- package/docs/hitl/x-lt-widget.md +5 -0
- package/docs/scan-codes.md +40 -7
- package/package.json +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-CpbC8oTN.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-CpbC8oTN.js.map +0 -1
- package/dashboard/dist/assets/EscalationSchemaPage-W5r0A1kj.js +0 -9
- package/dashboard/dist/assets/EscalationSchemaPage-W5r0A1kj.js.map +0 -1
- package/dashboard/dist/assets/EscalationTimeline-DKyTz6sM.js +0 -2
- package/dashboard/dist/assets/EscalationTimeline-DKyTz6sM.js.map +0 -1
- package/dashboard/dist/assets/McpQueryDetailPage-DYJr16l7.js +0 -5
- package/dashboard/dist/assets/McpQueryDetailPage-DYJr16l7.js.map +0 -1
- package/dashboard/dist/assets/ResolverForm-BwgjIX97.js +0 -7
- package/dashboard/dist/assets/ResolverForm-BwgjIX97.js.map +0 -1
- package/dashboard/dist/assets/index-B_GT23TE.js +0 -3
- package/dashboard/dist/assets/index-B_GT23TE.js.map +0 -1
- package/dashboard/dist/assets/index-CgUcYveM.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AccumulatedItem, LTEscalationRecord } from '../../types';
|
|
1
|
+
import type { AccumulatedItem, ContainerSelector, LTEscalationRecord } from '../../types';
|
|
2
2
|
import type { LTApiAuth, LTApiResult } from '../../types/sdk';
|
|
3
3
|
/** Names the second row of a reciprocal add or removal. Exactly one selector. */
|
|
4
4
|
export interface ReciprocalInput {
|
|
@@ -16,6 +16,11 @@ export interface AccumulateItemInput {
|
|
|
16
16
|
metadata?: Record<string, any>;
|
|
17
17
|
assertClaim?: boolean;
|
|
18
18
|
reciprocal?: ReciprocalInput;
|
|
19
|
+
/**
|
|
20
|
+
* The person who caused the add, when a trusted service performs it for
|
|
21
|
+
* them. Recorded as the entry's actor; the caller's rights still gate the write.
|
|
22
|
+
*/
|
|
23
|
+
initiatedBy?: string;
|
|
19
24
|
}
|
|
20
25
|
/**
|
|
21
26
|
* Add ONE item to an accumulator escalation (a `conditional` wait declared
|
|
@@ -59,10 +64,14 @@ export declare function accumulateItemByMetadata(input: {
|
|
|
59
64
|
key: string;
|
|
60
65
|
value: string;
|
|
61
66
|
restrictRoles?: string[];
|
|
67
|
+
/** Narrows the container beyond the facet: type, subtype, extra facet guards. */
|
|
68
|
+
container?: ContainerSelector;
|
|
62
69
|
} & Omit<AccumulateItemInput, 'assertClaim'>, auth: LTApiAuth): Promise<LTApiResult>;
|
|
63
70
|
export interface RemoveItemInput {
|
|
64
71
|
itemKey: string;
|
|
65
72
|
reciprocal?: Omit<ReciprocalInput, 'payload'>;
|
|
73
|
+
/** The person who caused the removal; see {@link AccumulateItemInput.initiatedBy}. */
|
|
74
|
+
initiatedBy?: string;
|
|
66
75
|
}
|
|
67
76
|
/**
|
|
68
77
|
* Remove ONE held item from a pending accumulator escalation, one guarded
|
|
@@ -44,6 +44,8 @@ exports.getEscalationItems = getEscalationItems;
|
|
|
44
44
|
exports.getEscalationItemsBySignalKey = getEscalationItemsBySignalKey;
|
|
45
45
|
const escalationService = __importStar(require("../../services/escalation"));
|
|
46
46
|
const resolver_validation_1 = require("../../services/escalation/resolver-validation");
|
|
47
|
+
const userService = __importStar(require("../../services/user"));
|
|
48
|
+
const uuid_1 = require("../../lib/uuid");
|
|
47
49
|
const enforcement_cache_1 = require("../../services/role/enforcement-cache");
|
|
48
50
|
const escalation_1 = require("../../types/escalation");
|
|
49
51
|
const helpers_1 = require("./helpers");
|
|
@@ -69,20 +71,61 @@ const NO_ACCUMULATOR_FOR_FACET = 'No pending accumulator found for this metadata
|
|
|
69
71
|
/**
|
|
70
72
|
* The container a facet names: the highest priority pending row that carries
|
|
71
73
|
* the facet AND the accumulator declaration, within the given roles (null =
|
|
72
|
-
* unscoped). A release or remediation row sharing
|
|
73
|
-
*
|
|
74
|
+
* unscoped) and the selector's guards. A release or remediation row sharing
|
|
75
|
+
* the facet is never a candidate, and neither is the add's own reciprocal row,
|
|
76
|
+
* so a by-facet add lands on the open container or nowhere.
|
|
74
77
|
*/
|
|
75
|
-
async function pickAccumulatorByFacet(key, value, roles) {
|
|
78
|
+
async function pickAccumulatorByFacet(key, value, roles, selector, excludeId) {
|
|
76
79
|
if (roles !== null && roles.length === 0)
|
|
77
80
|
return null;
|
|
78
81
|
const found = await escalationService.searchByFacets({
|
|
79
82
|
roles: roles ?? undefined,
|
|
80
|
-
|
|
83
|
+
types: selector?.types,
|
|
84
|
+
subtypes: selector?.subtypes,
|
|
85
|
+
facets: { ...selector?.facets, [key]: value },
|
|
81
86
|
status: 'pending',
|
|
82
87
|
exists: [escalation_1.ESCALATION_ACCUMULATE_KEYS.COUNT],
|
|
83
|
-
limit: 1,
|
|
88
|
+
limit: excludeId ? 2 : 1,
|
|
84
89
|
});
|
|
85
|
-
return found.escalations
|
|
90
|
+
return found.escalations.find((row) => row.id !== excludeId) ?? null;
|
|
91
|
+
}
|
|
92
|
+
const isStringList = (v) => Array.isArray(v) && v.every((s) => typeof s === 'string' && s.length > 0);
|
|
93
|
+
/** The selector's shape error, or null when it is absent or well formed. */
|
|
94
|
+
function containerSelectorError(selector) {
|
|
95
|
+
if (selector === undefined)
|
|
96
|
+
return null;
|
|
97
|
+
if (!selector || typeof selector !== 'object' || Array.isArray(selector))
|
|
98
|
+
return 'container must be an object';
|
|
99
|
+
if (selector.types !== undefined && !isStringList(selector.types))
|
|
100
|
+
return 'container.types must be an array of strings';
|
|
101
|
+
if (selector.subtypes !== undefined && !isStringList(selector.subtypes))
|
|
102
|
+
return 'container.subtypes must be an array of strings';
|
|
103
|
+
if (selector.facets !== undefined && (!selector.facets || typeof selector.facets !== 'object' || Array.isArray(selector.facets))) {
|
|
104
|
+
return 'container.facets must be an object';
|
|
105
|
+
}
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
function isNarrowed(selector) {
|
|
109
|
+
return !!(selector?.types?.length || selector?.subtypes?.length
|
|
110
|
+
|| (selector?.facets && Object.keys(selector.facets).length));
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The entry's actor: the caller, or the user a global-access caller names as
|
|
114
|
+
* the initiator. Attribution only; it never widens what the caller may write.
|
|
115
|
+
*/
|
|
116
|
+
async function resolveActor(initiatedBy, auth) {
|
|
117
|
+
if (initiatedBy === undefined || initiatedBy === auth.userId)
|
|
118
|
+
return { actor: auth.userId };
|
|
119
|
+
if (typeof initiatedBy !== 'string' || !(0, uuid_1.isUuid)(initiatedBy)) {
|
|
120
|
+
return { error: { status: 400, error: 'initiatedBy must be a user id' } };
|
|
121
|
+
}
|
|
122
|
+
if (!(await userService.hasGlobalEscalationAccess(auth.userId))) {
|
|
123
|
+
return { error: { status: 403, error: 'initiatedBy requires global escalation access' } };
|
|
124
|
+
}
|
|
125
|
+
if (!(await userService.getUser(initiatedBy))) {
|
|
126
|
+
return { error: { status: 400, error: 'initiatedBy names no user' } };
|
|
127
|
+
}
|
|
128
|
+
return { actor: initiatedBy };
|
|
86
129
|
}
|
|
87
130
|
function reciprocalSelectorCount(r) {
|
|
88
131
|
return (r.id ? 1 : 0) + (r.signalKey ? 1 : 0) + (r.key !== undefined ? 1 : 0);
|
|
@@ -158,6 +201,9 @@ async function accumulateItem(input, auth) {
|
|
|
158
201
|
const { id, itemKey, metadata } = input;
|
|
159
202
|
if (!itemKey)
|
|
160
203
|
return { status: 400, error: 'itemKey is required' };
|
|
204
|
+
const initiator = await resolveActor(input.initiatedBy, auth);
|
|
205
|
+
if ('error' in initiator)
|
|
206
|
+
return initiator.error;
|
|
161
207
|
const escalation = await escalationService.getEscalation(id);
|
|
162
208
|
if (!escalation)
|
|
163
209
|
return { status: 404, error: 'Escalation not found' };
|
|
@@ -183,7 +229,7 @@ async function accumulateItem(input, auth) {
|
|
|
183
229
|
itemKey,
|
|
184
230
|
payload: payload.payload,
|
|
185
231
|
metadata: { ...metadata, resolved_by: auth.userId },
|
|
186
|
-
actor:
|
|
232
|
+
actor: initiator.actor,
|
|
187
233
|
assertClaim: input.assertClaim ? auth.userId : undefined,
|
|
188
234
|
resolvedBy: await (0, resolve_1.resolverIdentity)(auth),
|
|
189
235
|
reciprocal: reciprocal.reciprocal,
|
|
@@ -206,6 +252,9 @@ async function accumulateItemBySignalKey(input, auth) {
|
|
|
206
252
|
return { status: 400, error: 'signalKey is required' };
|
|
207
253
|
if (!itemKey)
|
|
208
254
|
return { status: 400, error: 'itemKey is required' };
|
|
255
|
+
const initiator = await resolveActor(input.initiatedBy, auth);
|
|
256
|
+
if ('error' in initiator)
|
|
257
|
+
return initiator.error;
|
|
209
258
|
const escalation = await escalationService.getEscalationBySignalKey(signalKey);
|
|
210
259
|
if (!escalation)
|
|
211
260
|
return { status: 404, error: 'Escalation not found' };
|
|
@@ -226,7 +275,7 @@ async function accumulateItemBySignalKey(input, auth) {
|
|
|
226
275
|
itemKey,
|
|
227
276
|
payload: payload.payload,
|
|
228
277
|
metadata: { ...metadata, resolved_by: auth.userId },
|
|
229
|
-
actor:
|
|
278
|
+
actor: initiator.actor,
|
|
230
279
|
resolvedBy: await (0, resolve_1.resolverIdentity)(auth),
|
|
231
280
|
reciprocal: reciprocal.reciprocal,
|
|
232
281
|
});
|
|
@@ -254,6 +303,12 @@ async function accumulateItemByMetadata(input, auth) {
|
|
|
254
303
|
return { status: 400, error: 'key and value are required' };
|
|
255
304
|
if (!itemKey)
|
|
256
305
|
return { status: 400, error: 'itemKey is required' };
|
|
306
|
+
const initiator = await resolveActor(input.initiatedBy, auth);
|
|
307
|
+
if ('error' in initiator)
|
|
308
|
+
return initiator.error;
|
|
309
|
+
const selectorError = containerSelectorError(input.container);
|
|
310
|
+
if (selectorError)
|
|
311
|
+
return { status: 400, error: selectorError };
|
|
257
312
|
const writeScope = await (0, helpers_1.getEscalationWriteScope)(auth.userId);
|
|
258
313
|
const allowedRoles = (0, metadata_1.restrictScopeRoles)(writeScope.allRoles, writeScope.global, input.restrictRoles);
|
|
259
314
|
const reciprocal = await gateReciprocal(input.reciprocal, auth);
|
|
@@ -261,13 +316,17 @@ async function accumulateItemByMetadata(input, auth) {
|
|
|
261
316
|
return reciprocal.error;
|
|
262
317
|
const resolvedBy = await (0, resolve_1.resolverIdentity)(auth);
|
|
263
318
|
const outcome = { ...metadata, resolved_by: auth.userId };
|
|
319
|
+
// A narrowed selector picks in Long Tail, then adds by id; the by-id
|
|
320
|
+
// statement re-checks pending under its lock, and type, subtype and the
|
|
321
|
+
// accumulator declaration are fixed at creation.
|
|
264
322
|
const enforcing = await (0, enforcement_cache_1.getEnforcingRoles)();
|
|
265
|
-
|
|
323
|
+
const narrowed = isNarrowed(input.container);
|
|
324
|
+
if (!narrowed && (enforcing.size === 0 || input.payload === undefined)) {
|
|
266
325
|
const result = await escalationService.accumulateItemByMetadata(key, value, {
|
|
267
326
|
itemKey,
|
|
268
327
|
payload: input.payload,
|
|
269
328
|
metadata: outcome,
|
|
270
|
-
actor:
|
|
329
|
+
actor: initiator.actor,
|
|
271
330
|
resolvedBy,
|
|
272
331
|
roles: allowedRoles ?? undefined,
|
|
273
332
|
reciprocal: reciprocal.reciprocal,
|
|
@@ -276,7 +335,7 @@ async function accumulateItemByMetadata(input, auth) {
|
|
|
276
335
|
return { status: 404, error: NO_ACCUMULATOR_FOR_FACET };
|
|
277
336
|
return accumulateOutcomeResult(result, itemKey, result.escalation?.workflow_id ?? null);
|
|
278
337
|
}
|
|
279
|
-
const row = await pickAccumulatorByFacet(key, value, allowedRoles);
|
|
338
|
+
const row = await pickAccumulatorByFacet(key, value, allowedRoles, input.container, reciprocal.reciprocal?.id);
|
|
280
339
|
if (!row)
|
|
281
340
|
return { status: 404, error: NO_ACCUMULATOR_FOR_FACET };
|
|
282
341
|
if (!isAccumulator(row))
|
|
@@ -288,7 +347,7 @@ async function accumulateItemByMetadata(input, auth) {
|
|
|
288
347
|
itemKey,
|
|
289
348
|
payload: payload.payload,
|
|
290
349
|
metadata: outcome,
|
|
291
|
-
actor:
|
|
350
|
+
actor: initiator.actor,
|
|
292
351
|
resolvedBy,
|
|
293
352
|
reciprocal: reciprocal.reciprocal,
|
|
294
353
|
});
|
|
@@ -311,6 +370,9 @@ async function removeItem(input, auth) {
|
|
|
311
370
|
const { id, itemKey } = input;
|
|
312
371
|
if (!itemKey)
|
|
313
372
|
return { status: 400, error: 'itemKey is required' };
|
|
373
|
+
const initiator = await resolveActor(input.initiatedBy, auth);
|
|
374
|
+
if ('error' in initiator)
|
|
375
|
+
return initiator.error;
|
|
314
376
|
const escalation = await escalationService.getEscalation(id);
|
|
315
377
|
if (!escalation)
|
|
316
378
|
return { status: 404, error: 'Escalation not found' };
|
|
@@ -328,7 +390,7 @@ async function removeItem(input, auth) {
|
|
|
328
390
|
if ('error' in reciprocal)
|
|
329
391
|
return reciprocal.error;
|
|
330
392
|
const result = await escalationService.removeAccumulatedItem(escalation.id, {
|
|
331
|
-
itemKey, actor:
|
|
393
|
+
itemKey, actor: initiator.actor, reciprocal: reciprocal.reciprocal,
|
|
332
394
|
});
|
|
333
395
|
return removeOutcomeResult(result, itemKey);
|
|
334
396
|
}
|
|
@@ -343,6 +405,9 @@ async function removeItemBySignalKey(input, auth) {
|
|
|
343
405
|
return { status: 400, error: 'signalKey is required' };
|
|
344
406
|
if (!itemKey)
|
|
345
407
|
return { status: 400, error: 'itemKey is required' };
|
|
408
|
+
const initiator = await resolveActor(input.initiatedBy, auth);
|
|
409
|
+
if ('error' in initiator)
|
|
410
|
+
return initiator.error;
|
|
346
411
|
const escalation = await escalationService.getEscalationBySignalKey(signalKey);
|
|
347
412
|
if (!escalation)
|
|
348
413
|
return { status: 404, error: 'Escalation not found' };
|
|
@@ -357,7 +422,7 @@ async function removeItemBySignalKey(input, auth) {
|
|
|
357
422
|
if ('error' in reciprocal)
|
|
358
423
|
return reciprocal.error;
|
|
359
424
|
const result = await escalationService.removeAccumulatedItemBySignalKey(signalKey, {
|
|
360
|
-
itemKey, actor:
|
|
425
|
+
itemKey, actor: initiator.actor, reciprocal: reciprocal.reciprocal,
|
|
361
426
|
});
|
|
362
427
|
return removeOutcomeResult(result, itemKey);
|
|
363
428
|
}
|
|
@@ -372,13 +437,16 @@ async function removeItemByMetadata(input, auth) {
|
|
|
372
437
|
return { status: 400, error: 'key and value are required' };
|
|
373
438
|
if (!itemKey)
|
|
374
439
|
return { status: 400, error: 'itemKey is required' };
|
|
440
|
+
const initiator = await resolveActor(input.initiatedBy, auth);
|
|
441
|
+
if ('error' in initiator)
|
|
442
|
+
return initiator.error;
|
|
375
443
|
const writeScope = await (0, helpers_1.getEscalationWriteScope)(auth.userId);
|
|
376
444
|
const allowedRoles = (0, metadata_1.restrictScopeRoles)(writeScope.allRoles, writeScope.global, input.restrictRoles);
|
|
377
445
|
const reciprocal = await gateReciprocal(input.reciprocal, auth);
|
|
378
446
|
if ('error' in reciprocal)
|
|
379
447
|
return reciprocal.error;
|
|
380
448
|
const result = await escalationService.removeAccumulatedItemByMetadata(key, value, {
|
|
381
|
-
itemKey, actor:
|
|
449
|
+
itemKey, actor: initiator.actor, roles: allowedRoles ?? undefined, reciprocal: reciprocal.reciprocal,
|
|
382
450
|
});
|
|
383
451
|
if (result.outcome === 'not-found')
|
|
384
452
|
return { status: 404, error: NO_ACCUMULATOR_FOR_FACET };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ProvisionIfAbsent } from './helpers';
|
|
2
2
|
import type { LTApiAuth, LTApiResult } from '../../types/sdk';
|
|
3
|
+
import type { ScanAvailability } from '../../types';
|
|
3
4
|
/**
|
|
4
5
|
* Intersect the caller's scope roles with an optional caller-supplied
|
|
5
6
|
* restriction (e.g. a scan step's expected queues). Global scope with no
|
|
@@ -57,4 +58,8 @@ export declare function resolveByMetadata(input: {
|
|
|
57
58
|
metadata?: Record<string, any>;
|
|
58
59
|
restrictRoles?: string[];
|
|
59
60
|
extraFacets?: Record<string, any>;
|
|
61
|
+
/** Narrows the pick to a claim state; 'mine' is the resolver's live claim. */
|
|
62
|
+
availability?: ScanAvailability;
|
|
63
|
+
/** Resolves only this row, when it still matches every other condition. */
|
|
64
|
+
assertId?: string;
|
|
60
65
|
}, auth: LTApiAuth): Promise<LTApiResult>;
|
|
@@ -42,6 +42,7 @@ const helpers_1 = require("./helpers");
|
|
|
42
42
|
const resolver_validation_1 = require("../../services/escalation/resolver-validation");
|
|
43
43
|
const enforcement_cache_1 = require("../../services/role/enforcement-cache");
|
|
44
44
|
const resolve_1 = require("./resolve");
|
|
45
|
+
const uuid_1 = require("../../lib/uuid");
|
|
45
46
|
/**
|
|
46
47
|
* Intersect the caller's scope roles with an optional caller-supplied
|
|
47
48
|
* restriction (e.g. a scan step's expected queues). Global scope with no
|
|
@@ -138,6 +139,9 @@ async function resolveByMetadata(input, auth) {
|
|
|
138
139
|
if (!input.resolverPayload) {
|
|
139
140
|
return { status: 400, error: 'resolverPayload is required' };
|
|
140
141
|
}
|
|
142
|
+
if (input.assertId !== undefined && !(0, uuid_1.isUuid)(input.assertId)) {
|
|
143
|
+
return { status: 404, error: 'No pending escalation found for this metadata, or insufficient role permissions' };
|
|
144
|
+
}
|
|
141
145
|
const resolved = await (0, helpers_1.resolveAssignee)(input.assignee, auth);
|
|
142
146
|
if ('error' in resolved)
|
|
143
147
|
return resolved.error;
|
|
@@ -159,12 +163,12 @@ async function resolveByMetadata(input, auth) {
|
|
|
159
163
|
// writing; the payload validates here, then a second asserted pass claims
|
|
160
164
|
// + resolves the same row with pending re-checked inside the statement.
|
|
161
165
|
const enforcing = await (0, enforcement_cache_1.getEnforcingRoles)();
|
|
162
|
-
let result = await escalationService.resolveByMetadataAtomic(input.key, input.value, resolveUserId, input.resolverPayload, input.metadata, writeAllRoles, writeSelfRoles, enforcing.size > 0 ? [...enforcing] : null, null, input.extraFacets);
|
|
166
|
+
let result = await escalationService.resolveByMetadataAtomic(input.key, input.value, resolveUserId, input.resolverPayload, input.metadata, writeAllRoles, writeSelfRoles, enforcing.size > 0 ? [...enforcing] : null, input.assertId ?? null, input.extraFacets, input.availability);
|
|
163
167
|
if (result.outcome === 'validation_required' && result.row) {
|
|
164
168
|
const report = await (0, resolver_validation_1.checkResolverPayload)(result.row, input.resolverPayload, undefined, resolveUserId);
|
|
165
169
|
if (report)
|
|
166
170
|
return (0, resolve_1.validationFailure)(report);
|
|
167
|
-
result = await escalationService.resolveByMetadataAtomic(input.key, input.value, resolveUserId, input.resolverPayload, input.metadata, writeAllRoles, writeSelfRoles, null, result.row.id, input.extraFacets);
|
|
171
|
+
result = await escalationService.resolveByMetadataAtomic(input.key, input.value, resolveUserId, input.resolverPayload, input.metadata, writeAllRoles, writeSelfRoles, null, result.row.id, input.extraFacets, input.availability);
|
|
168
172
|
// The asserted row left pending between the two passes — a concurrent
|
|
169
173
|
// resolution won the row; surface it as the conflict it is.
|
|
170
174
|
if (result.outcome === 'not_found') {
|
|
@@ -110,12 +110,13 @@ async function executeScanChoice(input, auth) {
|
|
|
110
110
|
// showed. A row that moved on (resolved, claimed away, re-routed) is the
|
|
111
111
|
// same double-actor race a second scan loses.
|
|
112
112
|
const located = await (0, locate_1.locateForStep)(step, ctx, 2);
|
|
113
|
-
|
|
113
|
+
const presented = located?.escalations.find((e) => e.id === input.escalationId);
|
|
114
|
+
if (!presented) {
|
|
114
115
|
return decorate((0, context_1.conflict)('the item is no longer in the presented state'), ctx, input);
|
|
115
116
|
}
|
|
116
117
|
// 6. Dispatch through the same atomic executors a direct scan uses.
|
|
117
118
|
const synthesized = { query: step.query, verb: choice.verb, params: choice.params };
|
|
118
|
-
const result = await (0, verbs_1.dispatchChoiceVerb)(synthesized, ctx,
|
|
119
|
+
const result = await (0, verbs_1.dispatchChoiceVerb)(synthesized, ctx, presented);
|
|
119
120
|
return decorate(result, ctx, input);
|
|
120
121
|
}
|
|
121
122
|
catch (err) {
|
|
@@ -2,7 +2,12 @@ import { type ScanExecuteResponse, type ScanStep } from '../../types';
|
|
|
2
2
|
import type { LTApiResult } from '../../types/sdk';
|
|
3
3
|
import { type StepContext } from './context';
|
|
4
4
|
export declare function claimStep(step: ScanStep, ctx: StepContext): Promise<LTApiResult<ScanExecuteResponse> | null>;
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Resolves the row the step's query names: the scanned target, the extra
|
|
7
|
+
* facets, and the claim state, all inside the atomic statement. A presented
|
|
8
|
+
* choice passes the row it showed, so the resolve lands on that row or misses.
|
|
9
|
+
*/
|
|
10
|
+
export declare function resolveStep(step: ScanStep, ctx: StepContext, presentedId?: string): Promise<LTApiResult<ScanExecuteResponse> | null>;
|
|
6
11
|
export declare function escalateStep(step: ScanStep, ctx: StepContext): Promise<LTApiResult<ScanExecuteResponse> | null>;
|
|
7
12
|
export declare function releaseStep(step: ScanStep, ctx: StepContext): Promise<LTApiResult<ScanExecuteResponse> | null>;
|
|
8
13
|
/**
|
|
@@ -88,7 +88,12 @@ async function claimStep(step, ctx) {
|
|
|
88
88
|
return result;
|
|
89
89
|
return (0, context_1.executed)(result.data.escalation, step);
|
|
90
90
|
}
|
|
91
|
-
|
|
91
|
+
/**
|
|
92
|
+
* Resolves the row the step's query names: the scanned target, the extra
|
|
93
|
+
* facets, and the claim state, all inside the atomic statement. A presented
|
|
94
|
+
* choice passes the row it showed, so the resolve lands on that row or misses.
|
|
95
|
+
*/
|
|
96
|
+
async function resolveStep(step, ctx, presentedId) {
|
|
92
97
|
const rendered = await templated(step, ctx, (tpl) => ({
|
|
93
98
|
resolverPayload: scanCodeService.interpolateScanTemplate(step.params?.resolverPayload ?? {}, tpl),
|
|
94
99
|
metadata: (0, context_1.interpolatedMetadata)(step, ctx, tpl),
|
|
@@ -102,6 +107,8 @@ async function resolveStep(step, ctx) {
|
|
|
102
107
|
metadata: { ...rendered.metadata, ...(0, context_1.provenance)(ctx) },
|
|
103
108
|
restrictRoles: step.query?.roles,
|
|
104
109
|
extraFacets: step.query?.facets,
|
|
110
|
+
availability: step.query?.availability,
|
|
111
|
+
assertId: presentedId,
|
|
105
112
|
}, ctx.auth);
|
|
106
113
|
if (result.status === 404)
|
|
107
114
|
return null;
|
|
@@ -189,7 +196,7 @@ async function dispatchChoiceVerb(step, ctx, row) {
|
|
|
189
196
|
case types_1.SCAN_VERBS.CLAIM_SHOW_DETAIL:
|
|
190
197
|
return (await claimStep(step, ctx)) ?? (await missReason(step, ctx, 'the item is no longer claimable'));
|
|
191
198
|
case types_1.SCAN_VERBS.RESOLVE:
|
|
192
|
-
return (await resolveStep(step, ctx)) ?? (await missReason(step, ctx, 'the item is no longer resolvable'));
|
|
199
|
+
return (await resolveStep(step, ctx, row.id)) ?? (await missReason(step, ctx, 'the item is no longer resolvable'));
|
|
193
200
|
case types_1.SCAN_VERBS.ESCALATE:
|
|
194
201
|
return (await escalateStep(step, ctx)) ?? (await missReason(step, ctx, 'the item already moved on'));
|
|
195
202
|
case types_1.SCAN_VERBS.RELEASE:
|
|
@@ -283,7 +290,10 @@ async function accumulateStep(step, ctx) {
|
|
|
283
290
|
itemKey: rendered.itemKey,
|
|
284
291
|
payload: rendered.payload,
|
|
285
292
|
metadata: rendered.metadata,
|
|
286
|
-
restrictRoles: options.containerRoles,
|
|
293
|
+
restrictRoles: options.container?.roles ?? options.containerRoles,
|
|
294
|
+
container: options.container
|
|
295
|
+
? { types: options.container.types, subtypes: options.container.subtypes, facets: options.container.facets }
|
|
296
|
+
: undefined,
|
|
287
297
|
...(options.reciprocal === false ? {} : { reciprocal: { id: item.id } }),
|
|
288
298
|
};
|
|
289
299
|
}
|
|
@@ -21,14 +21,16 @@ export declare function invokeWorkflow(input: {
|
|
|
21
21
|
/**
|
|
22
22
|
* Get the execution status of a workflow.
|
|
23
23
|
*
|
|
24
|
-
* Returns the HotMesh status code (0
|
|
24
|
+
* Returns the HotMesh status code (above 0 running, 0 closed, below 0
|
|
25
|
+
* terminated) with the state it implies: `running`, `completed` or `failed`,
|
|
26
|
+
* `terminated` when an interrupt ended it, and `error` for a failed run.
|
|
25
27
|
* Resolves the workflow handle via task record or worker registry.
|
|
26
28
|
* `appId` selects the namespace for the job-entity fallback so a child
|
|
27
29
|
* running in another app resolves instead of 404ing against `durable`.
|
|
28
30
|
*
|
|
29
31
|
* @param input.workflowId — HotMesh workflow ID
|
|
30
32
|
* @param input.appId — HotMesh namespace for resolution (default: durable)
|
|
31
|
-
* @returns `{ status: 200, data: { workflowId, status } }` or 404
|
|
33
|
+
* @returns `{ status: 200, data: { workflowId, status, state, terminated, error? } }` or 404
|
|
32
34
|
*/
|
|
33
35
|
export declare function getWorkflowStatus(input: {
|
|
34
36
|
workflowId: string;
|
|
@@ -38,11 +40,13 @@ export declare function getWorkflowStatus(input: {
|
|
|
38
40
|
* Get the result of a completed workflow.
|
|
39
41
|
*
|
|
40
42
|
* Returns 202 if the workflow is still running, 200 with the result
|
|
41
|
-
* payload when complete
|
|
43
|
+
* payload when complete, and 200 with `state: 'failed'` (plus `terminated`
|
|
44
|
+
* and `error` when known) when it failed or was terminated. Never blocks —
|
|
45
|
+
* always returns immediately.
|
|
42
46
|
*
|
|
43
47
|
* @param input.workflowId — HotMesh workflow ID
|
|
44
48
|
* @param input.appId — HotMesh namespace for resolution (default: durable)
|
|
45
|
-
* @returns `{ status: 200, data: { workflowId, result } }` or 202 if running
|
|
49
|
+
* @returns `{ status: 200, data: { workflowId, state, result } }` or 202 if running
|
|
46
50
|
*/
|
|
47
51
|
export declare function getWorkflowResult(input: {
|
|
48
52
|
workflowId: string;
|
|
@@ -41,6 +41,7 @@ exports.exportWorkflow = exportWorkflow;
|
|
|
41
41
|
const workers_1 = require("../../workers");
|
|
42
42
|
const exportService = __importStar(require("../../services/export"));
|
|
43
43
|
const task_1 = require("../../services/task");
|
|
44
|
+
const workflow_state_1 = require("../../services/workflow-state");
|
|
44
45
|
const workflow_invocation_1 = require("../../services/workflow-invocation");
|
|
45
46
|
const crud_1 = require("../../services/escalation/crud");
|
|
46
47
|
const configService = __importStar(require("../../services/config"));
|
|
@@ -91,24 +92,26 @@ async function invokeWorkflow(input, auth) {
|
|
|
91
92
|
/**
|
|
92
93
|
* Get the execution status of a workflow.
|
|
93
94
|
*
|
|
94
|
-
* Returns the HotMesh status code (0
|
|
95
|
+
* Returns the HotMesh status code (above 0 running, 0 closed, below 0
|
|
96
|
+
* terminated) with the state it implies: `running`, `completed` or `failed`,
|
|
97
|
+
* `terminated` when an interrupt ended it, and `error` for a failed run.
|
|
95
98
|
* Resolves the workflow handle via task record or worker registry.
|
|
96
99
|
* `appId` selects the namespace for the job-entity fallback so a child
|
|
97
100
|
* running in another app resolves instead of 404ing against `durable`.
|
|
98
101
|
*
|
|
99
102
|
* @param input.workflowId — HotMesh workflow ID
|
|
100
103
|
* @param input.appId — HotMesh namespace for resolution (default: durable)
|
|
101
|
-
* @returns `{ status: 200, data: { workflowId, status } }` or 404
|
|
104
|
+
* @returns `{ status: 200, data: { workflowId, status, state, terminated, error? } }` or 404
|
|
102
105
|
*/
|
|
103
106
|
async function getWorkflowStatus(input) {
|
|
104
107
|
try {
|
|
105
108
|
const resolved = await (0, task_1.resolveWorkflowHandle)(input.workflowId, input.appId);
|
|
106
109
|
const client = (0, workers_1.createClient)();
|
|
107
110
|
const handle = await client.workflow.getHandle(resolved.taskQueue, resolved.workflowName, input.workflowId);
|
|
108
|
-
const
|
|
111
|
+
const reading = await (0, workflow_state_1.readWorkflowState)(handle);
|
|
109
112
|
return {
|
|
110
113
|
status: 200,
|
|
111
|
-
data: { workflowId: input.workflowId,
|
|
114
|
+
data: { workflowId: input.workflowId, ...reading },
|
|
112
115
|
};
|
|
113
116
|
}
|
|
114
117
|
catch (err) {
|
|
@@ -121,28 +124,42 @@ async function getWorkflowStatus(input) {
|
|
|
121
124
|
* Get the result of a completed workflow.
|
|
122
125
|
*
|
|
123
126
|
* Returns 202 if the workflow is still running, 200 with the result
|
|
124
|
-
* payload when complete
|
|
127
|
+
* payload when complete, and 200 with `state: 'failed'` (plus `terminated`
|
|
128
|
+
* and `error` when known) when it failed or was terminated. Never blocks —
|
|
129
|
+
* always returns immediately.
|
|
125
130
|
*
|
|
126
131
|
* @param input.workflowId — HotMesh workflow ID
|
|
127
132
|
* @param input.appId — HotMesh namespace for resolution (default: durable)
|
|
128
|
-
* @returns `{ status: 200, data: { workflowId, result } }` or 202 if running
|
|
133
|
+
* @returns `{ status: 200, data: { workflowId, state, result } }` or 202 if running
|
|
129
134
|
*/
|
|
130
135
|
async function getWorkflowResult(input) {
|
|
131
136
|
try {
|
|
132
137
|
const resolved = await (0, task_1.resolveWorkflowHandle)(input.workflowId, input.appId);
|
|
133
138
|
const client = (0, workers_1.createClient)();
|
|
134
139
|
const handle = await client.workflow.getHandle(resolved.taskQueue, resolved.workflowName, input.workflowId);
|
|
135
|
-
const
|
|
136
|
-
if (
|
|
140
|
+
const reading = await (0, workflow_state_1.readWorkflowState)(handle);
|
|
141
|
+
if (reading.state === workflow_state_1.WORKFLOW_STATES.RUNNING) {
|
|
137
142
|
return {
|
|
138
143
|
status: 202,
|
|
139
144
|
data: { workflowId: input.workflowId, status: 'running' },
|
|
140
145
|
};
|
|
141
146
|
}
|
|
147
|
+
if (reading.state === workflow_state_1.WORKFLOW_STATES.FAILED) {
|
|
148
|
+
return {
|
|
149
|
+
status: 200,
|
|
150
|
+
data: {
|
|
151
|
+
workflowId: input.workflowId,
|
|
152
|
+
state: reading.state,
|
|
153
|
+
terminated: reading.terminated,
|
|
154
|
+
...(reading.error ? { error: reading.error } : {}),
|
|
155
|
+
result: null,
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
142
159
|
const result = await handle.result();
|
|
143
160
|
return {
|
|
144
161
|
status: 200,
|
|
145
|
-
data: { workflowId: input.workflowId, result },
|
|
162
|
+
data: { workflowId: input.workflowId, state: reading.state, result },
|
|
146
163
|
};
|
|
147
164
|
}
|
|
148
165
|
catch (err) {
|
|
@@ -45,6 +45,7 @@ exports.terminateWorkflow = terminateWorkflow;
|
|
|
45
45
|
const picocolors_1 = __importDefault(require("picocolors"));
|
|
46
46
|
const client_1 = require("../client");
|
|
47
47
|
const format_1 = require("../format");
|
|
48
|
+
const workflow_state_1 = require("../../../shared/workflow-state");
|
|
48
49
|
const COLUMNS = [
|
|
49
50
|
{ key: 'workflow_type', label: 'Type', width: 24 },
|
|
50
51
|
{ key: 'task_queue', label: 'Queue', width: 16 },
|
|
@@ -72,13 +73,17 @@ async function invokeWorkflow(type, opts) {
|
|
|
72
73
|
console.log(`\n ${picocolors_1.default.green('✓')} Started ${picocolors_1.default.bold(type)} → ${picocolors_1.default.dim(data.workflowId)}\n`);
|
|
73
74
|
}
|
|
74
75
|
async function getWorkflowStatus(id, opts) {
|
|
75
|
-
const data = await (0, client_1.apiFetch)(`/workflows
|
|
76
|
+
const data = await (0, client_1.apiFetch)(`/workflows/${encodeURIComponent(id)}/status`);
|
|
76
77
|
if (opts.json) {
|
|
77
78
|
console.log(JSON.stringify(data, null, 2));
|
|
78
79
|
return;
|
|
79
80
|
}
|
|
80
|
-
const
|
|
81
|
-
|
|
81
|
+
const state = data.state === workflow_state_1.WORKFLOW_STATES.COMPLETED
|
|
82
|
+
? picocolors_1.default.green('completed')
|
|
83
|
+
: data.state === workflow_state_1.WORKFLOW_STATES.FAILED
|
|
84
|
+
? picocolors_1.default.red(data.terminated ? 'failed (terminated)' : 'failed')
|
|
85
|
+
: picocolors_1.default.blue('running');
|
|
86
|
+
console.log(`\n ${data.workflowId} ${state}${data.error ? picocolors_1.default.dim(` ${data.error}`) : ''}\n`);
|
|
82
87
|
}
|
|
83
88
|
async function getWorkflowResult(id, opts) {
|
|
84
89
|
const { server, token } = await (await Promise.resolve().then(() => __importStar(require('../auth')))).resolveAuth();
|
|
@@ -121,6 +126,6 @@ async function getWorkflowEnvelopes(id, opts) {
|
|
|
121
126
|
console.log();
|
|
122
127
|
}
|
|
123
128
|
async function terminateWorkflow(id) {
|
|
124
|
-
await (0, client_1.apiFetch)(`/workflows
|
|
129
|
+
await (0, client_1.apiFetch)(`/workflows/${encodeURIComponent(id)}/terminate`, { method: 'POST' });
|
|
125
130
|
console.log(`\n ${picocolors_1.default.green('✓')} Terminated ${picocolors_1.default.dim(id)}\n`);
|
|
126
131
|
}
|
|
@@ -45,7 +45,7 @@ function registerAccumulateRoutes(router) {
|
|
|
45
45
|
/**
|
|
46
46
|
* POST /api/escalations/accumulate-by-signal-key
|
|
47
47
|
* Add one item to an accumulator escalation by its signal_key.
|
|
48
|
-
* Body: { signalKey, itemKey, payload?, metadata?, reciprocal? }
|
|
48
|
+
* Body: { signalKey, itemKey, payload?, metadata?, reciprocal?, initiatedBy? }
|
|
49
49
|
*/
|
|
50
50
|
router.post('/accumulate-by-signal-key', async (req, res) => {
|
|
51
51
|
const result = await api.accumulateItemBySignalKey({
|
|
@@ -54,6 +54,7 @@ function registerAccumulateRoutes(router) {
|
|
|
54
54
|
payload: req.body?.payload,
|
|
55
55
|
metadata: req.body?.metadata,
|
|
56
56
|
reciprocal: req.body?.reciprocal,
|
|
57
|
+
initiatedBy: req.body?.initiatedBy,
|
|
57
58
|
}, req.auth);
|
|
58
59
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
59
60
|
});
|
|
@@ -61,7 +62,7 @@ function registerAccumulateRoutes(router) {
|
|
|
61
62
|
* POST /api/escalations/accumulate-by-metadata
|
|
62
63
|
* Add one item to the highest priority pending accumulator whose metadata
|
|
63
64
|
* contains the key/value.
|
|
64
|
-
* Body: { key, value, itemKey, payload?, metadata?, restrictRoles?, reciprocal? }
|
|
65
|
+
* Body: { key, value, itemKey, payload?, metadata?, restrictRoles?, container?, reciprocal?, initiatedBy? }
|
|
65
66
|
*/
|
|
66
67
|
router.post('/accumulate-by-metadata', async (req, res) => {
|
|
67
68
|
const result = await api.accumulateItemByMetadata({
|
|
@@ -71,25 +72,28 @@ function registerAccumulateRoutes(router) {
|
|
|
71
72
|
payload: req.body?.payload,
|
|
72
73
|
metadata: req.body?.metadata,
|
|
73
74
|
restrictRoles: req.body?.restrictRoles,
|
|
75
|
+
container: req.body?.container,
|
|
74
76
|
reciprocal: req.body?.reciprocal,
|
|
77
|
+
initiatedBy: req.body?.initiatedBy,
|
|
75
78
|
}, req.auth);
|
|
76
79
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
77
80
|
});
|
|
78
81
|
/**
|
|
79
82
|
* POST /api/escalations/remove-item-by-signal-key
|
|
80
|
-
* Body: { signalKey, itemKey, reciprocal? }
|
|
83
|
+
* Body: { signalKey, itemKey, reciprocal?, initiatedBy? }
|
|
81
84
|
*/
|
|
82
85
|
router.post('/remove-item-by-signal-key', async (req, res) => {
|
|
83
86
|
const result = await api.removeItemBySignalKey({
|
|
84
87
|
signalKey: req.body?.signalKey,
|
|
85
88
|
itemKey: req.body?.itemKey,
|
|
86
89
|
reciprocal: req.body?.reciprocal,
|
|
90
|
+
initiatedBy: req.body?.initiatedBy,
|
|
87
91
|
}, req.auth);
|
|
88
92
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
89
93
|
});
|
|
90
94
|
/**
|
|
91
95
|
* POST /api/escalations/remove-item-by-metadata
|
|
92
|
-
* Body: { key, value, itemKey, restrictRoles?, reciprocal? }
|
|
96
|
+
* Body: { key, value, itemKey, restrictRoles?, reciprocal?, initiatedBy? }
|
|
93
97
|
*/
|
|
94
98
|
router.post('/remove-item-by-metadata', async (req, res) => {
|
|
95
99
|
const result = await api.removeItemByMetadata({
|
|
@@ -98,6 +102,7 @@ function registerAccumulateRoutes(router) {
|
|
|
98
102
|
itemKey: req.body?.itemKey,
|
|
99
103
|
restrictRoles: req.body?.restrictRoles,
|
|
100
104
|
reciprocal: req.body?.reciprocal,
|
|
105
|
+
initiatedBy: req.body?.initiatedBy,
|
|
101
106
|
}, req.auth);
|
|
102
107
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
103
108
|
});
|
|
@@ -115,7 +120,7 @@ function registerAccumulateRoutes(router) {
|
|
|
115
120
|
* the add that reaches max answers { outcome: 'completed', signaled } and the
|
|
116
121
|
* waiting workflow resumes with the collection. Claim-agnostic unless
|
|
117
122
|
* assertClaim: true.
|
|
118
|
-
* Body: { itemKey, payload?, metadata?, assertClaim?, reciprocal? }
|
|
123
|
+
* Body: { itemKey, payload?, metadata?, assertClaim?, reciprocal?, initiatedBy? }
|
|
119
124
|
*/
|
|
120
125
|
router.post('/:id/accumulate', async (req, res) => {
|
|
121
126
|
const auth = await (0, acting_1.effectiveWorkAuth)(req, res);
|
|
@@ -128,13 +133,14 @@ function registerAccumulateRoutes(router) {
|
|
|
128
133
|
metadata: req.body?.metadata,
|
|
129
134
|
assertClaim: req.body?.assertClaim,
|
|
130
135
|
reciprocal: req.body?.reciprocal,
|
|
136
|
+
initiatedBy: req.body?.initiatedBy,
|
|
131
137
|
}, auth);
|
|
132
138
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
133
139
|
});
|
|
134
140
|
/**
|
|
135
141
|
* POST /api/escalations/:id/remove-item
|
|
136
142
|
* Remove one held item; the row stays pending and the waiter never wakes.
|
|
137
|
-
* Body: { itemKey, reciprocal? }
|
|
143
|
+
* Body: { itemKey, reciprocal?, initiatedBy? }
|
|
138
144
|
*/
|
|
139
145
|
router.post('/:id/remove-item', async (req, res) => {
|
|
140
146
|
const auth = await (0, acting_1.effectiveWorkAuth)(req, res);
|
|
@@ -144,6 +150,7 @@ function registerAccumulateRoutes(router) {
|
|
|
144
150
|
id: req.params.id,
|
|
145
151
|
itemKey: req.body?.itemKey,
|
|
146
152
|
reciprocal: req.body?.reciprocal,
|
|
153
|
+
initiatedBy: req.body?.initiatedBy,
|
|
147
154
|
}, auth);
|
|
148
155
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
149
156
|
});
|
package/build/sdk/index.d.ts
CHANGED
|
@@ -222,6 +222,8 @@ export declare function createClient(options?: LTClientOptions): {
|
|
|
222
222
|
metadata?: Record<string, any>;
|
|
223
223
|
restrictRoles?: string[];
|
|
224
224
|
extraFacets?: Record<string, any>;
|
|
225
|
+
availability?: import("..").ScanAvailability;
|
|
226
|
+
assertId?: string;
|
|
225
227
|
}, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
|
|
226
228
|
resolveBatchItem: (input: {
|
|
227
229
|
id: string;
|
|
@@ -254,6 +256,7 @@ export declare function createClient(options?: LTClientOptions): {
|
|
|
254
256
|
key: string;
|
|
255
257
|
value: string;
|
|
256
258
|
restrictRoles?: string[];
|
|
259
|
+
container?: import("..").ContainerSelector;
|
|
257
260
|
} & Omit<import("../api/escalations/accumulate").AccumulateItemInput, "assertClaim">, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
|
|
258
261
|
removeItem: (input: {
|
|
259
262
|
id: string;
|