@hotmeshio/long-tail 0.21.0 → 0.21.2
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 +13 -2
- package/build/api/escalations/accumulate.js +56 -7
- package/build/api/escalations/index.d.ts +1 -1
- package/build/api/escalations/index.js +2 -1
- package/build/api/scan-codes/context.d.ts +14 -1
- package/build/api/scan-codes/context.js +30 -2
- package/build/api/scan-codes/identity.js +1 -0
- package/build/api/scan-codes/verbs.d.ts +9 -3
- package/build/api/scan-codes/verbs.js +77 -23
- package/build/index.d.ts +2 -1
- package/build/index.js +3 -2
- package/build/routes/escalations/accumulate.js +8 -0
- package/build/sdk/index.d.ts +3 -0
- package/build/sdk/index.js +1 -0
- package/build/services/scan-code/index.d.ts +1 -1
- package/build/services/scan-code/index.js +3 -1
- package/build/services/scan-code/parse.d.ts +17 -3
- package/build/services/scan-code/parse.js +37 -4
- package/build/services/scan-code/validate.js +19 -0
- package/build/system/mcp-servers/admin/escalations.js +6 -1
- package/build/system/mcp-servers/admin/schemas.d.ts +6 -3
- package/build/system/mcp-servers/admin/schemas.js +2 -1
- package/build/system/seed/tool-manifests-admin.d.ts +189 -0
- package/build/system/seed/tool-manifests-admin.js +1 -1
- package/build/types/index.d.ts +2 -2
- package/build/types/index.js +2 -1
- package/build/types/scan-code.d.ts +31 -1
- package/build/types/scan-code.js +20 -2
- package/dashboard/dist/assets/{AdminDashboard-uarpHB88.js → AdminDashboard-Covdam48.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-uarpHB88.js.map → AdminDashboard-Covdam48.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-BcUaDD5E.js → AgentConfigPage-CE1k6J5r.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-BcUaDD5E.js.map → AgentConfigPage-CE1k6J5r.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-BaZBhK6i.js → AgentDetailPage-CWJZIZP1.js} +2 -2
- package/dashboard/dist/assets/{AgentDetailPage-BaZBhK6i.js.map → AgentDetailPage-CWJZIZP1.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-CuVFSDc4.js → AgentsPage---Dg5ufF.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-CuVFSDc4.js.map → AgentsPage---Dg5ufF.js.map} +1 -1
- package/dashboard/dist/assets/{AvailableEscalationsPage-iO5NyyIK.js → AvailableEscalationsPage-CpbC8oTN.js} +2 -2
- package/dashboard/dist/assets/{AvailableEscalationsPage-iO5NyyIK.js.map → AvailableEscalationsPage-CpbC8oTN.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-CClMby6B.js → BotPicker-D3drO3-T.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-CClMby6B.js.map → BotPicker-D3drO3-T.js.map} +1 -1
- package/dashboard/dist/assets/{BulkAssignModal-BL8FRgkN.js → BulkAssignModal-BOAWsViq.js} +2 -2
- package/dashboard/dist/assets/{BulkAssignModal-BL8FRgkN.js.map → BulkAssignModal-BOAWsViq.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-D53ogPor.js → CapabilitiesPage-RGgD3YZO.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-D53ogPor.js.map → CapabilitiesPage-RGgD3YZO.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-ow8jpbtD.js → CollapsibleSection-DNkZn87n.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-ow8jpbtD.js.map → CollapsibleSection-DNkZn87n.js.map} +1 -1
- package/dashboard/dist/assets/{ConfirmDeleteModal-CeEDt9iJ.js → ConfirmDeleteModal-BqzOwhPr.js} +2 -2
- package/dashboard/dist/assets/{ConfirmDeleteModal-CeEDt9iJ.js.map → ConfirmDeleteModal-BqzOwhPr.js.map} +1 -1
- package/dashboard/dist/assets/{CountdownTimer-CSqyZMCG.js → CountdownTimer-BaexQMK6.js} +2 -2
- package/dashboard/dist/assets/{CountdownTimer-CSqyZMCG.js.map → CountdownTimer-BaexQMK6.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-Dx7SxA23.js → CredentialsPage-D7abp0aS.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-Dx7SxA23.js.map → CredentialsPage-D7abp0aS.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-LYPxpvNN.js → CronLabel-DZiWmTwJ.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-LYPxpvNN.js.map → CronLabel-DZiWmTwJ.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-BZJTSm9N.js → ElapsedCell-BdGO_w4v.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-BZJTSm9N.js.map → ElapsedCell-BdGO_w4v.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-0wIIW2en.js → EntityTimelinePanel-DIDcF5Yu.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-0wIIW2en.js.map → EntityTimelinePanel-DIDcF5Yu.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-CoYvtMzj.js → EscalationListSchemaPage-C28rn9XC.js} +2 -2
- package/dashboard/dist/assets/{EscalationListSchemaPage-CoYvtMzj.js.map → EscalationListSchemaPage-C28rn9XC.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListView-DWFHPufv.js → EscalationListView-CkBnkpDJ.js} +2 -2
- package/dashboard/dist/assets/{EscalationListView-DWFHPufv.js.map → EscalationListView-CkBnkpDJ.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-C9Xu_A25.js → EscalationSchemaPage-W5r0A1kj.js} +2 -2
- package/dashboard/dist/assets/{EscalationSchemaPage-C9Xu_A25.js.map → EscalationSchemaPage-W5r0A1kj.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTimeline-D8W2LNNk.js → EscalationTimeline-DKyTz6sM.js} +2 -2
- package/dashboard/dist/assets/{EscalationTimeline-D8W2LNNk.js.map → EscalationTimeline-DKyTz6sM.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTitleSelect-DLK8NWMp.js → EscalationTitleSelect-CzKfavri.js} +2 -2
- package/dashboard/dist/assets/{EscalationTitleSelect-DLK8NWMp.js.map → EscalationTitleSelect-CzKfavri.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-CW57FaP9.js → EscalationsOverview-Tdu3Yx2c.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-CW57FaP9.js.map → EscalationsOverview-Tdu3Yx2c.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-D1ctWhKf.js → EventTable-DiIxOJwO.js} +2 -2
- package/dashboard/dist/assets/{EventTable-D1ctWhKf.js.map → EventTable-DiIxOJwO.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-C-iur-Nj.js → FilterBar-CvMBCVIo.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-C-iur-Nj.js.map → FilterBar-CvMBCVIo.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-CcA_44M4.js → GraphInvokePage-DO-yyhi6.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-CcA_44M4.js.map → GraphInvokePage-DO-yyhi6.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-Dc085ghJ.js → HomePage-DSS3eHR2.js} +2 -2
- package/dashboard/dist/assets/{HomePage-Dc085ghJ.js.map → HomePage-DSS3eHR2.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-h_ziBt4O.js → ListToolbar-C3-Tqqub.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-h_ziBt4O.js.map → ListToolbar-C3-Tqqub.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-qXXhbNWV.js → McpOverview-DEJmsdVi.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-qXXhbNWV.js.map → McpOverview-DEJmsdVi.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-SEzSbZrd.js → McpQueryDetailPage-DYJr16l7.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-SEzSbZrd.js.map → McpQueryDetailPage-DYJr16l7.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-Cy0V0kv9.js → McpQueryPage-BBcG_UuU.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-Cy0V0kv9.js.map → McpQueryPage-BBcG_UuU.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-DjJO5vSb.js → McpRunDetailPage-C6xw0kBg.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-DjJO5vSb.js.map → McpRunDetailPage-C6xw0kBg.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-BfjiJ8mM.js → McpRunsPage-CRQqrF4Q.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-BfjiJ8mM.js.map → McpRunsPage-CRQqrF4Q.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-dJcER0T_.js → OperationsPage-Dlfwzf-0.js} +2 -2
- package/dashboard/dist/assets/{OperationsPage-dJcER0T_.js.map → OperationsPage-Dlfwzf-0.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-zCkW4eqk.js → OperatorDashboard-DoiDGZ9R.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-zCkW4eqk.js.map → OperatorDashboard-DoiDGZ9R.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-Cx6L3Jvu.js → PersonaDetailPage-BzbA4Prr.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-Cx6L3Jvu.js.map → PersonaDetailPage-BzbA4Prr.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-DOgGUlJl.js → PersonasPage-B36yn4hU.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-DOgGUlJl.js.map → PersonasPage-B36yn4hU.js.map} +1 -1
- package/dashboard/dist/assets/{PortalPage-BKuL1BeJ.js → PortalPage-BkD4YfDf.js} +2 -2
- package/dashboard/dist/assets/{PortalPage-BKuL1BeJ.js.map → PortalPage-BkD4YfDf.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-BFcFSDUv.js → ProcessDetailPage-BT0eiBWY.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-BFcFSDUv.js.map → ProcessDetailPage-BT0eiBWY.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-BaHV2cXp.js → ProcessesListPage-BEqeeNae.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-BaHV2cXp.js.map → ProcessesListPage-BEqeeNae.js.map} +1 -1
- package/dashboard/dist/assets/{ResolverForm-Bgc0Zrya.js → ResolverForm-BwgjIX97.js} +2 -2
- package/dashboard/dist/assets/{ResolverForm-Bgc0Zrya.js.map → ResolverForm-BwgjIX97.js.map} +1 -1
- package/dashboard/dist/assets/{RoleDetailPage-BPY6i3CU.js → RoleDetailPage-BFuLNJXa.js} +2 -2
- package/dashboard/dist/assets/{RoleDetailPage-BPY6i3CU.js.map → RoleDetailPage-BFuLNJXa.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-DSqqKPbv.js → RolesPage-80quJU5-.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-DSqqKPbv.js.map → RolesPage-80quJU5-.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-B29iWwel.js → RunAsSelector-BoePhWVD.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-B29iWwel.js.map → RunAsSelector-BoePhWVD.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-S8aAJfnC.js → ScanCodesPage-Cu1bKEix.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-S8aAJfnC.js.map → ScanCodesPage-Cu1bKEix.js.map} +1 -1
- package/dashboard/dist/assets/ScanSchemeDetailPage-D9AbS6UY.js +2 -0
- package/dashboard/dist/assets/ScanSchemeDetailPage-D9AbS6UY.js.map +1 -0
- package/dashboard/dist/assets/{ScanStationPage-R9t1-CeQ.js → ScanStationPage-gcZGefvT.js} +2 -2
- package/dashboard/dist/assets/{ScanStationPage-R9t1-CeQ.js.map → ScanStationPage-gcZGefvT.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-CkW_A507.js → StickyPagination-9ITrei_d.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-CkW_A507.js.map → StickyPagination-9ITrei_d.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-yzWX0wac.js → StreamMessageDetail-BkYvEHFY.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-yzWX0wac.js.map → StreamMessageDetail-BkYvEHFY.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-Cf4DXFxj.js → SwimlaneTimeline-B1rotFix.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-Cf4DXFxj.js.map → SwimlaneTimeline-B1rotFix.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-DCDcEps9.js → TaskDetailPage-zhn_U_eC.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-DCDcEps9.js.map → TaskDetailPage-zhn_U_eC.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-BBATgpf7.js → TasksListPage-CNbNeagx.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-BBATgpf7.js.map → TasksListPage-CNbNeagx.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-CSNVEjch.js → TimeAgo-0YVMBwls.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-CSNVEjch.js.map → TimeAgo-0YVMBwls.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-Du1nBrPn.js → TimestampCell-DB7r3np8.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-Du1nBrPn.js.map → TimestampCell-DB7r3np8.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-CF-h_5Rg.js → ToolTestPanel-BLfA02wv.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-CF-h_5Rg.js.map → ToolTestPanel-BLfA02wv.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-Dr1UmWcp.js → TopicDetailPage-eAqPKShq.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-Dr1UmWcp.js.map → TopicDetailPage-eAqPKShq.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-CUUo-Ylf.js → TopicsPage-BNNWD-zl.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-CUUo-Ylf.js.map → TopicsPage-BNNWD-zl.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-kBh1dc39.js → UserName-Pw46tO_k.js} +2 -2
- package/dashboard/dist/assets/{UserName-kBh1dc39.js.map → UserName-Pw46tO_k.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-CCRSbnDx.js → WorkflowExecutionPage-DvA51lT3.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-CCRSbnDx.js.map → WorkflowExecutionPage-DvA51lT3.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-BNQVvyek.js → WorkflowsDashboard-DFDTwnhn.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-BNQVvyek.js.map → WorkflowsDashboard-DFDTwnhn.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-DswubNJN.js → WorkflowsOverview-5i2Tcy-p.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-DswubNJN.js.map → WorkflowsOverview-5i2Tcy-p.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-Cw9Dlmup.js → YamlWorkflowDetailPage-p4VEYZS0.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-Cw9Dlmup.js.map → YamlWorkflowDetailPage-p4VEYZS0.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-DB8xnIXy.js → YamlWorkflowsPage-Cq-hMVxl.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-DB8xnIXy.js.map → YamlWorkflowsPage-Cq-hMVxl.js.map} +1 -1
- package/dashboard/dist/assets/{agents-BwEnf6N9.js → agents-EyBPJMYa.js} +2 -2
- package/dashboard/dist/assets/{agents-BwEnf6N9.js.map → agents-EyBPJMYa.js.map} +1 -1
- package/dashboard/dist/assets/{bots-CCmJTT2u.js → bots-DX6jjqtF.js} +2 -2
- package/dashboard/dist/assets/{bots-CCmJTT2u.js.map → bots-DX6jjqtF.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-BZHgp_nh.js → capabilities-ZdLv9xBQ.js} +2 -2
- package/dashboard/dist/assets/{capabilities-BZHgp_nh.js.map → capabilities-ZdLv9xBQ.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-CyfwUlFA.js → controlplane-CpvZaJuw.js} +2 -2
- package/dashboard/dist/assets/{controlplane-CyfwUlFA.js.map → controlplane-CpvZaJuw.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-BJPTNmLW.js → escalation-columns-Mvsze5eV.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-BJPTNmLW.js.map → escalation-columns-Mvsze5eV.js.map} +1 -1
- package/dashboard/dist/assets/{index-CDrqqbSR.js → index-B_GT23TE.js} +3 -3
- package/dashboard/dist/assets/{index-CDrqqbSR.js.map → index-B_GT23TE.js.map} +1 -1
- package/dashboard/dist/assets/{index-CVwzCZ43.js → index-BbCjGO3M.js} +2 -2
- package/dashboard/dist/assets/{index-CVwzCZ43.js.map → index-BbCjGO3M.js.map} +1 -1
- package/dashboard/dist/assets/{index-CuVkSmj5.js → index-Bhb89oHH.js} +2 -2
- package/dashboard/dist/assets/{index-CuVkSmj5.js.map → index-Bhb89oHH.js.map} +1 -1
- package/dashboard/dist/assets/{index-3gbd5neL.js → index-CgUcYveM.js} +33 -33
- package/dashboard/dist/assets/index-CgUcYveM.js.map +1 -0
- package/dashboard/dist/assets/{index-BAAVTyZ-.js → index-Cn8uJsd7.js} +2 -2
- package/dashboard/dist/assets/{index-BAAVTyZ-.js.map → index-Cn8uJsd7.js.map} +1 -1
- package/dashboard/dist/assets/{index-C7KHqOTQ.js → index-D-Xs4rAW.js} +2 -2
- package/dashboard/dist/assets/{index-C7KHqOTQ.js.map → index-D-Xs4rAW.js.map} +1 -1
- package/dashboard/dist/assets/{index-DZ8X_Gp4.js → index-DGmzBY9D.js} +2 -2
- package/dashboard/dist/assets/{index-DZ8X_Gp4.js.map → index-DGmzBY9D.js.map} +1 -1
- package/dashboard/dist/assets/{index-DBWS5QL8.js → index-DZhtP2Ok.js} +2 -2
- package/dashboard/dist/assets/{index-DBWS5QL8.js.map → index-DZhtP2Ok.js.map} +1 -1
- package/dashboard/dist/assets/{index-ClVbfe4z.js → index-DkrBFFSO.js} +2 -2
- package/dashboard/dist/assets/{index-ClVbfe4z.js.map → index-DkrBFFSO.js.map} +1 -1
- package/dashboard/dist/assets/{index-BC6Jenlo.js → index-Eo-l3Lqo.js} +2 -2
- package/dashboard/dist/assets/{index-BC6Jenlo.js.map → index-Eo-l3Lqo.js.map} +1 -1
- package/dashboard/dist/assets/{index-DIWCI6HC.js → index-PfSRKerc.js} +2 -2
- package/dashboard/dist/assets/{index-DIWCI6HC.js.map → index-PfSRKerc.js.map} +1 -1
- package/dashboard/dist/assets/{index-DAuX_PlL.js → index-oFKUFGQL.js} +2 -2
- package/dashboard/dist/assets/{index-DAuX_PlL.js.map → index-oFKUFGQL.js.map} +1 -1
- package/dashboard/dist/assets/{index-CaGF6TCC.js → index-z5Hpeidu.js} +2 -2
- package/dashboard/dist/assets/{index-CaGF6TCC.js.map → index-z5Hpeidu.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-CqyLhUMg.js → knowledge-CgloEkaf.js} +2 -2
- package/dashboard/dist/assets/{knowledge-CqyLhUMg.js.map → knowledge-CgloEkaf.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-Cvu6bFYH.js → mcp-Bix7QYO7.js} +2 -2
- package/dashboard/dist/assets/{mcp-Cvu6bFYH.js.map → mcp-Bix7QYO7.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-qC6A3e9l.js → mcp-query-o-sGX2ST.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-qC6A3e9l.js.map → mcp-query-o-sGX2ST.js.map} +1 -1
- package/dashboard/dist/assets/{personas-BKN_lJuV.js → personas-30azkJ_s.js} +2 -2
- package/dashboard/dist/assets/{personas-BKN_lJuV.js.map → personas-30azkJ_s.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-BldIfv85.js → pipelines-Bfk2GFK7.js} +2 -2
- package/dashboard/dist/assets/{pipelines-BldIfv85.js.map → pipelines-Bfk2GFK7.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-B-Uay8uL.js → tasks-CpdopewW.js} +2 -2
- package/dashboard/dist/assets/{tasks-B-Uay8uL.js.map → tasks-CpdopewW.js.map} +1 -1
- package/dashboard/dist/assets/{topics-438EQogt.js → topics--bvCV9Yp.js} +2 -2
- package/dashboard/dist/assets/{topics-438EQogt.js.map → topics--bvCV9Yp.js.map} +1 -1
- package/dashboard/dist/assets/{useDebouncedValue-Cw8hYZ8y.js → useDebouncedValue-Da0lPmj3.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-Cw8hYZ8y.js.map → useDebouncedValue-Da0lPmj3.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-D1218GQ8.js → useNamespace-DD_Esl6n.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-D1218GQ8.js.map → useNamespace-DD_Esl6n.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-BAQf_y_U.js → useYamlActivityEvents-AeAhZJJk.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-BAQf_y_U.js.map → useYamlActivityEvents-AeAhZJJk.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-CN01gEB0.js → yaml-workflows-BHAOOGvn.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-CN01gEB0.js.map → yaml-workflows-BHAOOGvn.js.map} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/docs/accumulator.md +6 -4
- package/docs/api/http/escalations.md +3 -2
- package/docs/api/sdk/escalations.md +4 -3
- package/docs/scan-codes.md +23 -10
- package/package.json +2 -2
- package/dashboard/dist/assets/ScanSchemeDetailPage-CUBRAtmJ.js +0 -2
- package/dashboard/dist/assets/ScanSchemeDetailPage-CUBRAtmJ.js.map +0 -1
- package/dashboard/dist/assets/index-3gbd5neL.js.map +0 -1
|
@@ -46,8 +46,11 @@ export declare function accumulateItemBySignalKey(input: {
|
|
|
46
46
|
} & Omit<AccumulateItemInput, 'assertClaim'>, auth: LTApiAuth): Promise<LTApiResult>;
|
|
47
47
|
/**
|
|
48
48
|
* Add selecting the container by metadata facet, the faceted sibling of
|
|
49
|
-
* {@link accumulateItem}.
|
|
50
|
-
*
|
|
49
|
+
* {@link accumulateItem}. The facet names a container, so only pending rows
|
|
50
|
+
* carrying the accumulator declaration are candidates: a release or
|
|
51
|
+
* remediation row that shares the facet is never picked, and when no open
|
|
52
|
+
* container shares it the answer is 404. RBAC folds into the SDK's atomic
|
|
53
|
+
* facet selection as a flat role filter. Schema enforcement is two-phase when enforcing
|
|
51
54
|
* roles exist and a payload is present: the row is picked first, validated
|
|
52
55
|
* against ITS schema, then written by asserted id; a row that went terminal
|
|
53
56
|
* between phases surfaces as a 409.
|
|
@@ -94,3 +97,11 @@ export declare function itemsView(escalation: LTEscalationRecord): EscalationIte
|
|
|
94
97
|
export declare function getEscalationItems(input: {
|
|
95
98
|
id: string;
|
|
96
99
|
}, auth: LTApiAuth): Promise<LTApiResult<EscalationItemsView>>;
|
|
100
|
+
/**
|
|
101
|
+
* GET the held items of an accumulator or batch row by its `signal_key`, the
|
|
102
|
+
* deterministic home signal id a workflow knows without a row id. Read scope
|
|
103
|
+
* gates it; anything the caller may not see answers 404.
|
|
104
|
+
*/
|
|
105
|
+
export declare function getEscalationItemsBySignalKey(input: {
|
|
106
|
+
signalKey: string;
|
|
107
|
+
}, auth: LTApiAuth): Promise<LTApiResult<EscalationItemsView>>;
|
|
@@ -41,6 +41,7 @@ exports.removeItemBySignalKey = removeItemBySignalKey;
|
|
|
41
41
|
exports.removeItemByMetadata = removeItemByMetadata;
|
|
42
42
|
exports.itemsView = itemsView;
|
|
43
43
|
exports.getEscalationItems = getEscalationItems;
|
|
44
|
+
exports.getEscalationItemsBySignalKey = getEscalationItemsBySignalKey;
|
|
44
45
|
const escalationService = __importStar(require("../../services/escalation"));
|
|
45
46
|
const resolver_validation_1 = require("../../services/escalation/resolver-validation");
|
|
46
47
|
const enforcement_cache_1 = require("../../services/role/enforcement-cache");
|
|
@@ -64,6 +65,25 @@ function isAccumulator(escalation) {
|
|
|
64
65
|
function isBatch(escalation) {
|
|
65
66
|
return Array.isArray(escalation.metadata?.[escalation_1.ESCALATION_BATCH_KEYS.PENDING]);
|
|
66
67
|
}
|
|
68
|
+
const NO_ACCUMULATOR_FOR_FACET = 'No pending accumulator found for this metadata';
|
|
69
|
+
/**
|
|
70
|
+
* The container a facet names: the highest priority pending row that carries
|
|
71
|
+
* the facet AND the accumulator declaration, within the given roles (null =
|
|
72
|
+
* unscoped). A release or remediation row sharing the facet is never a
|
|
73
|
+
* candidate, so a by-facet add lands on the open container or nowhere.
|
|
74
|
+
*/
|
|
75
|
+
async function pickAccumulatorByFacet(key, value, roles) {
|
|
76
|
+
if (roles !== null && roles.length === 0)
|
|
77
|
+
return null;
|
|
78
|
+
const found = await escalationService.searchByFacets({
|
|
79
|
+
roles: roles ?? undefined,
|
|
80
|
+
facets: { [key]: value },
|
|
81
|
+
status: 'pending',
|
|
82
|
+
exists: [escalation_1.ESCALATION_ACCUMULATE_KEYS.COUNT],
|
|
83
|
+
limit: 1,
|
|
84
|
+
});
|
|
85
|
+
return found.escalations[0] ?? null;
|
|
86
|
+
}
|
|
67
87
|
function reciprocalSelectorCount(r) {
|
|
68
88
|
return (r.id ? 1 : 0) + (r.signalKey ? 1 : 0) + (r.key !== undefined ? 1 : 0);
|
|
69
89
|
}
|
|
@@ -88,8 +108,7 @@ async function gateReciprocal(input, auth) {
|
|
|
88
108
|
}
|
|
89
109
|
else {
|
|
90
110
|
const writeScope = await (0, helpers_1.getEscalationWriteScope)(auth.userId);
|
|
91
|
-
|
|
92
|
-
row = found.escalations[0] ?? null;
|
|
111
|
+
row = await pickAccumulatorByFacet(input.key, String(input.value), writeScope.global ? null : writeScope.allRoles);
|
|
93
112
|
}
|
|
94
113
|
if (!row)
|
|
95
114
|
return { error: { status: 404, error: 'Reciprocal escalation not found' } };
|
|
@@ -219,8 +238,11 @@ async function accumulateItemBySignalKey(input, auth) {
|
|
|
219
238
|
}
|
|
220
239
|
/**
|
|
221
240
|
* Add selecting the container by metadata facet, the faceted sibling of
|
|
222
|
-
* {@link accumulateItem}.
|
|
223
|
-
*
|
|
241
|
+
* {@link accumulateItem}. The facet names a container, so only pending rows
|
|
242
|
+
* carrying the accumulator declaration are candidates: a release or
|
|
243
|
+
* remediation row that shares the facet is never picked, and when no open
|
|
244
|
+
* container shares it the answer is 404. RBAC folds into the SDK's atomic
|
|
245
|
+
* facet selection as a flat role filter. Schema enforcement is two-phase when enforcing
|
|
224
246
|
* roles exist and a payload is present: the row is picked first, validated
|
|
225
247
|
* against ITS schema, then written by asserted id; a row that went terminal
|
|
226
248
|
* between phases surfaces as a 409.
|
|
@@ -250,12 +272,13 @@ async function accumulateItemByMetadata(input, auth) {
|
|
|
250
272
|
roles: allowedRoles ?? undefined,
|
|
251
273
|
reciprocal: reciprocal.reciprocal,
|
|
252
274
|
});
|
|
275
|
+
if (result.outcome === 'not-found')
|
|
276
|
+
return { status: 404, error: NO_ACCUMULATOR_FOR_FACET };
|
|
253
277
|
return accumulateOutcomeResult(result, itemKey, result.escalation?.workflow_id ?? null);
|
|
254
278
|
}
|
|
255
|
-
const
|
|
256
|
-
const row = found.escalations[0];
|
|
279
|
+
const row = await pickAccumulatorByFacet(key, value, allowedRoles);
|
|
257
280
|
if (!row)
|
|
258
|
-
return { status: 404, error:
|
|
281
|
+
return { status: 404, error: NO_ACCUMULATOR_FOR_FACET };
|
|
259
282
|
if (!isAccumulator(row))
|
|
260
283
|
return { status: 400, error: 'Escalation is not an accumulator' };
|
|
261
284
|
const payload = await gatePayload(row, input.payload, auth.userId);
|
|
@@ -357,6 +380,8 @@ async function removeItemByMetadata(input, auth) {
|
|
|
357
380
|
const result = await escalationService.removeAccumulatedItemByMetadata(key, value, {
|
|
358
381
|
itemKey, actor: auth.userId, roles: allowedRoles ?? undefined, reciprocal: reciprocal.reciprocal,
|
|
359
382
|
});
|
|
383
|
+
if (result.outcome === 'not-found')
|
|
384
|
+
return { status: 404, error: NO_ACCUMULATOR_FOR_FACET };
|
|
360
385
|
return removeOutcomeResult(result, itemKey);
|
|
361
386
|
}
|
|
362
387
|
catch (err) {
|
|
@@ -419,6 +444,30 @@ async function getEscalationItems(input, auth) {
|
|
|
419
444
|
return { status: 500, error: err.message };
|
|
420
445
|
}
|
|
421
446
|
}
|
|
447
|
+
/**
|
|
448
|
+
* GET the held items of an accumulator or batch row by its `signal_key`, the
|
|
449
|
+
* deterministic home signal id a workflow knows without a row id. Read scope
|
|
450
|
+
* gates it; anything the caller may not see answers 404.
|
|
451
|
+
*/
|
|
452
|
+
async function getEscalationItemsBySignalKey(input, auth) {
|
|
453
|
+
try {
|
|
454
|
+
if (!input.signalKey)
|
|
455
|
+
return { status: 400, error: 'signalKey is required' };
|
|
456
|
+
const escalation = await escalationService.getEscalationBySignalKey(input.signalKey);
|
|
457
|
+
if (!escalation)
|
|
458
|
+
return { status: 404, error: 'Escalation not found' };
|
|
459
|
+
if (await (0, helpers_1.assertReadAccess)(auth.userId, escalation)) {
|
|
460
|
+
return { status: 404, error: 'Escalation not found' };
|
|
461
|
+
}
|
|
462
|
+
const view = itemsView(escalation);
|
|
463
|
+
if (!view)
|
|
464
|
+
return { status: 400, error: 'Escalation holds no items' };
|
|
465
|
+
return { status: 200, data: view };
|
|
466
|
+
}
|
|
467
|
+
catch (err) {
|
|
468
|
+
return { status: 500, error: err.message };
|
|
469
|
+
}
|
|
470
|
+
}
|
|
422
471
|
function sideData(side) {
|
|
423
472
|
return {
|
|
424
473
|
outcome: side.outcome,
|
|
@@ -6,7 +6,7 @@ export { claimEscalation, releaseEscalation } from './claim';
|
|
|
6
6
|
export { releaseExpiredClaims, updatePriority, bulkClaim, bulkAssign, bulkUnassign, bulkEscalate, bulkTriage } from './bulk';
|
|
7
7
|
export { resolveEscalation, resolveBySignalKey, resolveByIds, resolveAllOrNone } from './resolve';
|
|
8
8
|
export { resolveBatchItem, resolveBatchItemBySignalKey, resolveBatchItemByMetadata } from './resolve-batch';
|
|
9
|
-
export { accumulateItem, accumulateItemBySignalKey, accumulateItemByMetadata, removeItem, removeItemBySignalKey, removeItemByMetadata, getEscalationItems, itemsView, } from './accumulate';
|
|
9
|
+
export { accumulateItem, accumulateItemBySignalKey, accumulateItemByMetadata, removeItem, removeItemBySignalKey, removeItemByMetadata, getEscalationItems, getEscalationItemsBySignalKey, itemsView, } from './accumulate';
|
|
10
10
|
export { findByMetadata, claimByMetadata, resolveByMetadata } from './metadata';
|
|
11
11
|
export { cancelSingleEscalation, bulkCancel } from './cancel';
|
|
12
12
|
export { searchByFacets, claimGroups, claimByFacets } from './facets';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.timelineByFacet = exports.aggregateByFacets = exports.claimByFacets = exports.claimGroups = exports.searchByFacets = exports.bulkCancel = exports.cancelSingleEscalation = exports.resolveByMetadata = exports.claimByMetadata = exports.findByMetadata = exports.itemsView = exports.getEscalationItems = exports.removeItemByMetadata = exports.removeItemBySignalKey = exports.removeItem = exports.accumulateItemByMetadata = exports.accumulateItemBySignalKey = exports.accumulateItem = exports.resolveBatchItemByMetadata = exports.resolveBatchItemBySignalKey = exports.resolveBatchItem = exports.resolveAllOrNone = exports.resolveByIds = exports.resolveBySignalKey = exports.resolveEscalation = exports.bulkTriage = exports.bulkEscalate = exports.bulkUnassign = exports.bulkAssign = exports.bulkClaim = exports.updatePriority = exports.releaseExpiredClaims = exports.releaseEscalation = exports.claimEscalation = exports.getEscalationLookups = exports.escalateToRole = exports.getEscalationsByWorkflowId = exports.getEscalation = exports.getStationMetrics = exports.getEscalationStats = exports.listFacetValues = exports.listFacetKeys = exports.listDistinctTypes = exports.listAvailableEscalations = exports.listEscalations = exports.createEscalation = void 0;
|
|
3
|
+
exports.timelineByFacet = exports.aggregateByFacets = exports.claimByFacets = exports.claimGroups = exports.searchByFacets = exports.bulkCancel = exports.cancelSingleEscalation = exports.resolveByMetadata = exports.claimByMetadata = exports.findByMetadata = exports.itemsView = exports.getEscalationItemsBySignalKey = exports.getEscalationItems = exports.removeItemByMetadata = exports.removeItemBySignalKey = exports.removeItem = exports.accumulateItemByMetadata = exports.accumulateItemBySignalKey = exports.accumulateItem = exports.resolveBatchItemByMetadata = exports.resolveBatchItemBySignalKey = exports.resolveBatchItem = exports.resolveAllOrNone = exports.resolveByIds = exports.resolveBySignalKey = exports.resolveEscalation = exports.bulkTriage = exports.bulkEscalate = exports.bulkUnassign = exports.bulkAssign = exports.bulkClaim = exports.updatePriority = exports.releaseExpiredClaims = exports.releaseEscalation = exports.claimEscalation = exports.getEscalationLookups = exports.escalateToRole = exports.getEscalationsByWorkflowId = exports.getEscalation = exports.getStationMetrics = exports.getEscalationStats = exports.listFacetValues = exports.listFacetKeys = exports.listDistinctTypes = exports.listAvailableEscalations = exports.listEscalations = exports.createEscalation = void 0;
|
|
4
4
|
var create_1 = require("./create");
|
|
5
5
|
Object.defineProperty(exports, "createEscalation", { enumerable: true, get: function () { return create_1.createEscalation; } });
|
|
6
6
|
var list_1 = require("./list");
|
|
@@ -45,6 +45,7 @@ Object.defineProperty(exports, "removeItem", { enumerable: true, get: function (
|
|
|
45
45
|
Object.defineProperty(exports, "removeItemBySignalKey", { enumerable: true, get: function () { return accumulate_1.removeItemBySignalKey; } });
|
|
46
46
|
Object.defineProperty(exports, "removeItemByMetadata", { enumerable: true, get: function () { return accumulate_1.removeItemByMetadata; } });
|
|
47
47
|
Object.defineProperty(exports, "getEscalationItems", { enumerable: true, get: function () { return accumulate_1.getEscalationItems; } });
|
|
48
|
+
Object.defineProperty(exports, "getEscalationItemsBySignalKey", { enumerable: true, get: function () { return accumulate_1.getEscalationItemsBySignalKey; } });
|
|
48
49
|
Object.defineProperty(exports, "itemsView", { enumerable: true, get: function () { return accumulate_1.itemsView; } });
|
|
49
50
|
var metadata_1 = require("./metadata");
|
|
50
51
|
Object.defineProperty(exports, "findByMetadata", { enumerable: true, get: function () { return metadata_1.findByMetadata; } });
|
|
@@ -16,8 +16,21 @@ export interface StepContext {
|
|
|
16
16
|
}
|
|
17
17
|
export declare function targetFilter(step: ScanStep, ctx: StepContext): Record<string, any>;
|
|
18
18
|
export declare function templateContext(ctx: StepContext): scanCodeService.ScanTemplateContext;
|
|
19
|
+
/**
|
|
20
|
+
* The metadata of the acting user's single live claim, or undefined when
|
|
21
|
+
* they hold none or more than one. One scoped list query, read before the
|
|
22
|
+
* guarded write; the write re-checks everything under lock.
|
|
23
|
+
*/
|
|
24
|
+
export declare function liveClaimMetadata(ctx: StepContext): Promise<Record<string, unknown> | undefined>;
|
|
25
|
+
/**
|
|
26
|
+
* The template context for one step: the scan tokens, the located item row's
|
|
27
|
+
* metadata when the verb has one, and the actor's live claim when the step's
|
|
28
|
+
* params mention `{claim.…}` (the lookup costs one query, so it runs only
|
|
29
|
+
* then).
|
|
30
|
+
*/
|
|
31
|
+
export declare function stepTemplate(step: ScanStep, ctx: StepContext, item?: LTEscalationRecord): Promise<scanCodeService.ScanTemplateContext>;
|
|
19
32
|
export declare function provenance(ctx: StepContext): Record<string, any>;
|
|
20
|
-
export declare function interpolatedMetadata(step: ScanStep, ctx: StepContext): Record<string, any>;
|
|
33
|
+
export declare function interpolatedMetadata(step: ScanStep, ctx: StepContext, tpl?: scanCodeService.ScanTemplateContext): Record<string, any>;
|
|
21
34
|
export declare function executed(escalation: LTEscalationRecord | Record<string, any> | undefined, step: Pick<ScanStep, 'verb'>): LTApiResult<ScanExecuteResponse>;
|
|
22
35
|
export declare function forbidden(error?: string): LTApiResult<ScanExecuteResponse>;
|
|
23
36
|
export declare function conflict(error?: string): LTApiResult<ScanExecuteResponse>;
|
|
@@ -35,6 +35,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.targetFilter = targetFilter;
|
|
37
37
|
exports.templateContext = templateContext;
|
|
38
|
+
exports.liveClaimMetadata = liveClaimMetadata;
|
|
39
|
+
exports.stepTemplate = stepTemplate;
|
|
38
40
|
exports.provenance = provenance;
|
|
39
41
|
exports.interpolatedMetadata = interpolatedMetadata;
|
|
40
42
|
exports.executed = executed;
|
|
@@ -42,6 +44,7 @@ exports.forbidden = forbidden;
|
|
|
42
44
|
exports.conflict = conflict;
|
|
43
45
|
exports.notPrimed = notPrimed;
|
|
44
46
|
const scanCodeService = __importStar(require("../../services/scan-code"));
|
|
47
|
+
const escalationService = __importStar(require("../../services/escalation"));
|
|
45
48
|
const types_1 = require("../../types");
|
|
46
49
|
function targetFilter(step, ctx) {
|
|
47
50
|
return { [ctx.scheme.target_facet]: ctx.parsed.target, ...(step.query?.facets ?? {}) };
|
|
@@ -49,6 +52,31 @@ function targetFilter(step, ctx) {
|
|
|
49
52
|
function templateContext(ctx) {
|
|
50
53
|
return { target: ctx.parsed.target, category: ctx.parsed.category, scannedAt: ctx.scannedAt };
|
|
51
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* The metadata of the acting user's single live claim, or undefined when
|
|
57
|
+
* they hold none or more than one. One scoped list query, read before the
|
|
58
|
+
* guarded write; the write re-checks everything under lock.
|
|
59
|
+
*/
|
|
60
|
+
async function liveClaimMetadata(ctx) {
|
|
61
|
+
const { escalations } = await escalationService.listEscalations({
|
|
62
|
+
assigned_to: ctx.auth.userId,
|
|
63
|
+
status: 'pending',
|
|
64
|
+
limit: 2,
|
|
65
|
+
});
|
|
66
|
+
const live = escalations.filter(types_1.isEffectivelyClaimed);
|
|
67
|
+
return live.length === 1 ? (live[0].metadata ?? {}) : undefined;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The template context for one step: the scan tokens, the located item row's
|
|
71
|
+
* metadata when the verb has one, and the actor's live claim when the step's
|
|
72
|
+
* params mention `{claim.…}` (the lookup costs one query, so it runs only
|
|
73
|
+
* then).
|
|
74
|
+
*/
|
|
75
|
+
async function stepTemplate(step, ctx, item) {
|
|
76
|
+
const base = templateContext(ctx);
|
|
77
|
+
const claim = scanCodeService.mentionsClaimToken(step.params) ? await liveClaimMetadata(ctx) : undefined;
|
|
78
|
+
return { ...base, ...(item ? { item: item.metadata ?? {} } : {}), ...(claim ? { claim } : {}) };
|
|
79
|
+
}
|
|
52
80
|
function provenance(ctx) {
|
|
53
81
|
return {
|
|
54
82
|
[types_1.SCAN_PROVENANCE_KEYS.SCHEME]: ctx.scheme.version,
|
|
@@ -60,9 +88,9 @@ function provenance(ctx) {
|
|
|
60
88
|
...(ctx.acting ? { [types_1.SCAN_PROVENANCE_KEYS.STATION]: ctx.stationAuth.userId } : {}),
|
|
61
89
|
};
|
|
62
90
|
}
|
|
63
|
-
function interpolatedMetadata(step, ctx) {
|
|
91
|
+
function interpolatedMetadata(step, ctx, tpl = templateContext(ctx)) {
|
|
64
92
|
return step.params?.metadata
|
|
65
|
-
? scanCodeService.interpolateScanTemplate(step.params.metadata,
|
|
93
|
+
? scanCodeService.interpolateScanTemplate(step.params.metadata, tpl)
|
|
66
94
|
: {};
|
|
67
95
|
}
|
|
68
96
|
function executed(escalation, step) {
|
|
@@ -94,6 +94,7 @@ async function executeIdentityScan(parsed, scheme, rule, previousActingToken) {
|
|
|
94
94
|
actor: { id: user.id, displayName: user.display_name || user.external_id },
|
|
95
95
|
actingToken: (0, ephemeral_1.formatEphemeralToken)(uuid, types_1.ACTING_IDENTITY_LABEL),
|
|
96
96
|
expiresAt,
|
|
97
|
+
maxUses: scheme.grant_max_uses ?? 0,
|
|
97
98
|
},
|
|
98
99
|
};
|
|
99
100
|
}
|
|
@@ -20,11 +20,17 @@ export declare function cancelStep(step: ScanStep, ctx: StepContext): Promise<LT
|
|
|
20
20
|
* item's own pending row through the scheme facet, reads the container
|
|
21
21
|
* facet value it carries, and adds the target to the container that shares
|
|
22
22
|
* it, writing the item row as the reciprocal in the same statement. An
|
|
23
|
-
* item with no row, or no container facet, falls through.
|
|
23
|
+
* item with no row, or no container facet, falls through. An item whose
|
|
24
|
+
* container has closed and whose successor has not parked yet answers
|
|
25
|
+
* `no_open_container` with the item row, so the station can say "scan
|
|
26
|
+
* again" instead of showing the bag with no hint.
|
|
24
27
|
* - Container-locate (no `containerFacet`): the scan locates the container
|
|
25
28
|
* by the scheme facet and adds `params.itemKey` (template).
|
|
26
29
|
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
30
|
+
* Templates may read `{claim.<facet>}` (the actor's live claim) and, in item
|
|
31
|
+
* mode, `{item.<facet>}` (the located row); an unresolvable token falls
|
|
32
|
+
* through. The write is the SDK's guarded statement; the locate only picks
|
|
33
|
+
* ids. A container already holding the item answers conflict, never a
|
|
34
|
+
* second add.
|
|
29
35
|
*/
|
|
30
36
|
export declare function accumulateStep(step: ScanStep, ctx: StepContext): Promise<LTApiResult<ScanExecuteResponse> | null>;
|
|
@@ -54,12 +54,30 @@ const locate_1 = require("./locate");
|
|
|
54
54
|
// ctx.auth is the effective actor: the badged person when a grant rode the
|
|
55
55
|
// request, otherwise the authenticated principal. Attribution and write
|
|
56
56
|
// scoping both derive from it, live, inside the escalation APIs.
|
|
57
|
+
/**
|
|
58
|
+
* Interpolates a step's params, or falls through when a `{claim.…}` or
|
|
59
|
+
* `{item.…}` token has nothing to read: a literal token never reaches a row.
|
|
60
|
+
*/
|
|
61
|
+
async function templated(step, ctx, render, item) {
|
|
62
|
+
const tpl = await (0, context_1.stepTemplate)(step, ctx, item);
|
|
63
|
+
try {
|
|
64
|
+
return render(tpl);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
if (err instanceof scanCodeService.ScanTemplateError)
|
|
68
|
+
return null;
|
|
69
|
+
throw err;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
57
72
|
async function claimStep(step, ctx) {
|
|
73
|
+
const metadata = await templated(step, ctx, (tpl) => (0, context_1.interpolatedMetadata)(step, ctx, tpl));
|
|
74
|
+
if (metadata === null)
|
|
75
|
+
return null;
|
|
58
76
|
const result = await (0, metadata_1.claimByMetadata)({
|
|
59
77
|
key: ctx.scheme.target_facet,
|
|
60
78
|
value: ctx.parsed.target,
|
|
61
79
|
durationMinutes: step.params?.durationMinutes,
|
|
62
|
-
metadata: { ...
|
|
80
|
+
metadata: { ...metadata, ...(0, context_1.provenance)(ctx) },
|
|
63
81
|
restrictRoles: step.query?.roles,
|
|
64
82
|
}, ctx.auth);
|
|
65
83
|
if (result.status === 404)
|
|
@@ -71,11 +89,17 @@ async function claimStep(step, ctx) {
|
|
|
71
89
|
return (0, context_1.executed)(result.data.escalation, step);
|
|
72
90
|
}
|
|
73
91
|
async function resolveStep(step, ctx) {
|
|
92
|
+
const rendered = await templated(step, ctx, (tpl) => ({
|
|
93
|
+
resolverPayload: scanCodeService.interpolateScanTemplate(step.params?.resolverPayload ?? {}, tpl),
|
|
94
|
+
metadata: (0, context_1.interpolatedMetadata)(step, ctx, tpl),
|
|
95
|
+
}));
|
|
96
|
+
if (rendered === null)
|
|
97
|
+
return null;
|
|
74
98
|
const result = await (0, metadata_1.resolveByMetadata)({
|
|
75
99
|
key: ctx.scheme.target_facet,
|
|
76
100
|
value: ctx.parsed.target,
|
|
77
|
-
resolverPayload:
|
|
78
|
-
metadata: { ...
|
|
101
|
+
resolverPayload: rendered.resolverPayload,
|
|
102
|
+
metadata: { ...rendered.metadata, ...(0, context_1.provenance)(ctx) },
|
|
79
103
|
restrictRoles: step.query?.roles,
|
|
80
104
|
extraFacets: step.query?.facets,
|
|
81
105
|
}, ctx.auth);
|
|
@@ -213,35 +237,52 @@ async function cancelStep(step, ctx) {
|
|
|
213
237
|
* item's own pending row through the scheme facet, reads the container
|
|
214
238
|
* facet value it carries, and adds the target to the container that shares
|
|
215
239
|
* it, writing the item row as the reciprocal in the same statement. An
|
|
216
|
-
* item with no row, or no container facet, falls through.
|
|
240
|
+
* item with no row, or no container facet, falls through. An item whose
|
|
241
|
+
* container has closed and whose successor has not parked yet answers
|
|
242
|
+
* `no_open_container` with the item row, so the station can say "scan
|
|
243
|
+
* again" instead of showing the bag with no hint.
|
|
217
244
|
* - Container-locate (no `containerFacet`): the scan locates the container
|
|
218
245
|
* by the scheme facet and adds `params.itemKey` (template).
|
|
219
246
|
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
247
|
+
* Templates may read `{claim.<facet>}` (the actor's live claim) and, in item
|
|
248
|
+
* mode, `{item.<facet>}` (the located row); an unresolvable token falls
|
|
249
|
+
* through. The write is the SDK's guarded statement; the locate only picks
|
|
250
|
+
* ids. A container already holding the item answers conflict, never a
|
|
251
|
+
* second add.
|
|
222
252
|
*/
|
|
223
253
|
async function accumulateStep(step, ctx) {
|
|
224
|
-
const tpl = (0, context_1.templateContext)(ctx);
|
|
225
|
-
const payload = step.params?.resolverPayload
|
|
226
|
-
? scanCodeService.interpolateScanTemplate(step.params.resolverPayload, tpl)
|
|
227
|
-
: undefined;
|
|
228
|
-
const metadata = { ...(0, context_1.interpolatedMetadata)(step, ctx), ...(0, context_1.provenance)(ctx) };
|
|
229
254
|
const options = step.params?.accumulate;
|
|
230
|
-
let
|
|
255
|
+
let item;
|
|
231
256
|
if (options?.containerFacet) {
|
|
232
257
|
const located = await (0, locate_1.locateForStep)(step, ctx, 1);
|
|
233
|
-
|
|
258
|
+
item = located?.escalations[0];
|
|
234
259
|
if (!item)
|
|
235
260
|
return null;
|
|
261
|
+
}
|
|
262
|
+
const rendered = await templated(step, ctx, (tpl) => ({
|
|
263
|
+
payload: step.params?.resolverPayload
|
|
264
|
+
? scanCodeService.interpolateScanTemplate(step.params.resolverPayload, tpl)
|
|
265
|
+
: undefined,
|
|
266
|
+
metadata: { ...(0, context_1.interpolatedMetadata)(step, ctx, tpl), ...(0, context_1.provenance)(ctx) },
|
|
267
|
+
itemKey: options?.containerFacet
|
|
268
|
+
? ctx.parsed.target
|
|
269
|
+
: scanCodeService.interpolateScanTemplate(step.params.itemKey, tpl),
|
|
270
|
+
}), item);
|
|
271
|
+
if (rendered === null)
|
|
272
|
+
return null;
|
|
273
|
+
let request;
|
|
274
|
+
let container;
|
|
275
|
+
if (options?.containerFacet && item) {
|
|
236
276
|
const containerValue = item.metadata?.[options.containerFacet];
|
|
237
277
|
if (containerValue === undefined || containerValue === null || containerValue === '')
|
|
238
278
|
return null;
|
|
279
|
+
container = { facet: options.containerFacet, value: String(containerValue) };
|
|
239
280
|
request = {
|
|
240
|
-
key:
|
|
241
|
-
value:
|
|
242
|
-
itemKey:
|
|
243
|
-
payload,
|
|
244
|
-
metadata,
|
|
281
|
+
key: container.facet,
|
|
282
|
+
value: container.value,
|
|
283
|
+
itemKey: rendered.itemKey,
|
|
284
|
+
payload: rendered.payload,
|
|
285
|
+
metadata: rendered.metadata,
|
|
245
286
|
restrictRoles: options.containerRoles,
|
|
246
287
|
...(options.reciprocal === false ? {} : { reciprocal: { id: item.id } }),
|
|
247
288
|
};
|
|
@@ -250,15 +291,28 @@ async function accumulateStep(step, ctx) {
|
|
|
250
291
|
request = {
|
|
251
292
|
key: ctx.scheme.target_facet,
|
|
252
293
|
value: ctx.parsed.target,
|
|
253
|
-
itemKey:
|
|
254
|
-
payload,
|
|
255
|
-
metadata,
|
|
294
|
+
itemKey: rendered.itemKey,
|
|
295
|
+
payload: rendered.payload,
|
|
296
|
+
metadata: rendered.metadata,
|
|
256
297
|
restrictRoles: step.query?.roles,
|
|
257
298
|
};
|
|
258
299
|
}
|
|
259
300
|
const result = await (0, accumulate_1.accumulateItemByMetadata)(request, ctx.auth);
|
|
260
|
-
if (result.status === 404)
|
|
261
|
-
|
|
301
|
+
if (result.status === 404) {
|
|
302
|
+
if (!container || !item)
|
|
303
|
+
return null;
|
|
304
|
+
return {
|
|
305
|
+
status: 200,
|
|
306
|
+
data: {
|
|
307
|
+
outcome: types_1.SCAN_OUTCOMES.NO_OPEN_CONTAINER,
|
|
308
|
+
verb: step.verb,
|
|
309
|
+
escalation: item,
|
|
310
|
+
container,
|
|
311
|
+
fallback: ctx.rule.fallback,
|
|
312
|
+
error: `No open container carries ${container.facet} = ${container.value}`,
|
|
313
|
+
},
|
|
314
|
+
};
|
|
315
|
+
}
|
|
262
316
|
if (result.status === 403)
|
|
263
317
|
return (0, context_1.forbidden)(result.error);
|
|
264
318
|
if (result.status === 409)
|
package/build/index.d.ts
CHANGED
|
@@ -3,7 +3,8 @@ export { midnightTheme } from './themes/midnight';
|
|
|
3
3
|
export { registerLT, createLTInterceptor } from './services/interceptor';
|
|
4
4
|
export { createLTActivityInterceptor } from './services/interceptor/activity-interceptor';
|
|
5
5
|
export { executeLT } from './services/orchestrator';
|
|
6
|
-
export { conditional, conditionLT } from './services/orchestrator/condition';
|
|
6
|
+
export { conditional, conditionLT, conditionalAccumulator } from './services/orchestrator/condition';
|
|
7
|
+
export type { ConditionEscalationConfig, ConditionAccumulatorConfig } from './services/orchestrator/condition';
|
|
7
8
|
export type { ExecuteLTOptions } from './services/orchestrator/types';
|
|
8
9
|
export { JwtAuthAdapter, createAuthMiddleware, requireAuth, requireAdmin, signToken, setAuthAdapter } from './modules/auth';
|
|
9
10
|
export * from './types';
|
package/build/index.js
CHANGED
|
@@ -36,8 +36,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
};
|
|
37
37
|
})();
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.
|
|
40
|
-
exports.LTExpressAdapter = exports.api = exports.KnowledgeApi = exports.resolveCredential = exports.mimeFromPath = exports.getStorageBackend = exports.listOAuthConnections = exports.getFreshAccessToken = exports.createClient = exports.CallbackEventAdapter = exports.builtinMcpServerFactories = exports.getSystemAgents = exports.getSystemWorkers = exports.registerMcpTool = exports.getToolContext = void 0;
|
|
39
|
+
exports.McpEscalationStrategy = exports.DefaultEscalationStrategy = exports.escalationStrategyRegistry = exports.McpVisionServer = exports.McpTranslationServer = exports.McpServer = exports.McpClient = exports.McpService = exports.BuiltInMcpAdapter = exports.mcpRegistry = exports.defaultMaintenanceConfig = exports.maintenanceRegistry = exports.PinoLoggerAdapter = exports.loggerRegistry = exports.HoneycombTelemetryAdapter = exports.telemetryRegistry = exports.publishKnowledgeEvent = exports.publishAgentEvent = exports.publishWorkflowEvent = exports.publishActivityEvent = exports.publishEscalationEvent = exports.publishTaskEvent = exports.publishMilestoneEvent = exports.SocketIOEventAdapter = exports.InMemoryEventAdapter = exports.NatsEventAdapter = exports.eventRegistry = exports.ltConfig = exports.seedConfigTopics = exports.seedSystemTopics = exports.TopicService = exports.UserService = exports.ConfigService = exports.EscalationService = exports.TaskService = exports.setAuthAdapter = exports.signToken = exports.requireAdmin = exports.requireAuth = exports.createAuthMiddleware = exports.JwtAuthAdapter = exports.conditionalAccumulator = exports.conditionLT = exports.conditional = exports.executeLT = exports.createLTActivityInterceptor = exports.createLTInterceptor = exports.registerLT = exports.midnightTheme = exports.start = void 0;
|
|
40
|
+
exports.LTExpressAdapter = exports.api = exports.KnowledgeApi = exports.resolveCredential = exports.mimeFromPath = exports.getStorageBackend = exports.listOAuthConnections = exports.getFreshAccessToken = exports.createClient = exports.CallbackEventAdapter = exports.builtinMcpServerFactories = exports.getSystemAgents = exports.getSystemWorkers = exports.registerMcpTool = exports.getToolContext = exports.getActivityIdentity = void 0;
|
|
41
41
|
const config_1 = require("./modules/config");
|
|
42
42
|
const logger_1 = require("./lib/logger");
|
|
43
43
|
const midnight_1 = require("./themes/midnight");
|
|
@@ -57,6 +57,7 @@ Object.defineProperty(exports, "executeLT", { enumerable: true, get: function ()
|
|
|
57
57
|
var condition_1 = require("./services/orchestrator/condition");
|
|
58
58
|
Object.defineProperty(exports, "conditional", { enumerable: true, get: function () { return condition_1.conditional; } });
|
|
59
59
|
Object.defineProperty(exports, "conditionLT", { enumerable: true, get: function () { return condition_1.conditionLT; } });
|
|
60
|
+
Object.defineProperty(exports, "conditionalAccumulator", { enumerable: true, get: function () { return condition_1.conditionalAccumulator; } });
|
|
60
61
|
var auth_1 = require("./modules/auth");
|
|
61
62
|
Object.defineProperty(exports, "JwtAuthAdapter", { enumerable: true, get: function () { return auth_1.JwtAuthAdapter; } });
|
|
62
63
|
Object.defineProperty(exports, "createAuthMiddleware", { enumerable: true, get: function () { return auth_1.createAuthMiddleware; } });
|
|
@@ -101,6 +101,14 @@ function registerAccumulateRoutes(router) {
|
|
|
101
101
|
}, req.auth);
|
|
102
102
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
103
103
|
});
|
|
104
|
+
/**
|
|
105
|
+
* GET /api/escalations/items-by-signal-key?signalKey=…
|
|
106
|
+
* The held items of an accumulator or batch row by its signal_key.
|
|
107
|
+
*/
|
|
108
|
+
router.get('/items-by-signal-key', async (req, res) => {
|
|
109
|
+
const result = await api.getEscalationItemsBySignalKey({ signalKey: String(req.query.signalKey ?? '') }, req.auth);
|
|
110
|
+
res.status(result.status).json(result.data ?? { error: result.error });
|
|
111
|
+
});
|
|
104
112
|
/**
|
|
105
113
|
* POST /api/escalations/:id/accumulate
|
|
106
114
|
* Add one item. Interim adds answer { outcome: 'accepted', count, remaining };
|
package/build/sdk/index.d.ts
CHANGED
|
@@ -269,6 +269,9 @@ export declare function createClient(options?: LTClientOptions): {
|
|
|
269
269
|
getItems: (input: {
|
|
270
270
|
id: string;
|
|
271
271
|
}, auth?: LTApiAuth) => Promise<LTApiResult<import("../api/escalations/accumulate").EscalationItemsView>>;
|
|
272
|
+
getItemsBySignalKey: (input: {
|
|
273
|
+
signalKey: string;
|
|
274
|
+
}, auth?: LTApiAuth) => Promise<LTApiResult<import("../api/escalations/accumulate").EscalationItemsView>>;
|
|
272
275
|
searchByFacets: (input: import("..").FacetQuery, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
|
|
273
276
|
claimGroups: (input: {
|
|
274
277
|
query: import("..").FacetQuery;
|
package/build/sdk/index.js
CHANGED
|
@@ -154,6 +154,7 @@ function createClient(options = {}) {
|
|
|
154
154
|
removeItemBySignalKey: bindAuth(escalationsApi.removeItemBySignalKey, auth),
|
|
155
155
|
removeItemByMetadata: bindAuth(escalationsApi.removeItemByMetadata, auth),
|
|
156
156
|
getItems: bindAuth(escalationsApi.getEscalationItems, auth),
|
|
157
|
+
getItemsBySignalKey: bindAuth(escalationsApi.getEscalationItemsBySignalKey, auth),
|
|
157
158
|
// Faceted-routing surface (pond search + batch claim), RBAC-scoped to the caller's role.
|
|
158
159
|
searchByFacets: bindAuth(escalationsApi.searchByFacets, auth),
|
|
159
160
|
claimGroups: bindAuth(escalationsApi.claimGroups, auth),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { listScanSchemes, getScanScheme, listScanRules, getScanRule, } from './read';
|
|
2
2
|
export { upsertScanScheme, deleteScanScheme, upsertScanRule, deleteScanRule, seedScanScheme, seedScanRule, applyScanScheme, applyScanRule, type ScanSchemeInput, type ScanRuleInput, } from './write';
|
|
3
|
-
export { parseScanCode, interpolateScanTemplate, type ScanParseResult, type ScanParseFailure, type ScanTemplateContext, } from './parse';
|
|
3
|
+
export { parseScanCode, interpolateScanTemplate, mentionsClaimToken, ScanTemplateError, type ScanParseResult, type ScanParseFailure, type ScanTemplateContext, } from './parse';
|
|
4
4
|
export { assertValidScheme, assertValidSteps } from './validate';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.assertValidSteps = exports.assertValidScheme = exports.interpolateScanTemplate = exports.parseScanCode = exports.applyScanRule = exports.applyScanScheme = exports.seedScanRule = exports.seedScanScheme = exports.deleteScanRule = exports.upsertScanRule = exports.deleteScanScheme = exports.upsertScanScheme = exports.getScanRule = exports.listScanRules = exports.getScanScheme = exports.listScanSchemes = void 0;
|
|
3
|
+
exports.assertValidSteps = exports.assertValidScheme = exports.ScanTemplateError = exports.mentionsClaimToken = exports.interpolateScanTemplate = exports.parseScanCode = exports.applyScanRule = exports.applyScanScheme = exports.seedScanRule = exports.seedScanScheme = exports.deleteScanRule = exports.upsertScanRule = exports.deleteScanScheme = exports.upsertScanScheme = exports.getScanRule = exports.listScanRules = exports.getScanScheme = exports.listScanSchemes = void 0;
|
|
4
4
|
var read_1 = require("./read");
|
|
5
5
|
Object.defineProperty(exports, "listScanSchemes", { enumerable: true, get: function () { return read_1.listScanSchemes; } });
|
|
6
6
|
Object.defineProperty(exports, "getScanScheme", { enumerable: true, get: function () { return read_1.getScanScheme; } });
|
|
@@ -18,6 +18,8 @@ Object.defineProperty(exports, "applyScanRule", { enumerable: true, get: functio
|
|
|
18
18
|
var parse_1 = require("./parse");
|
|
19
19
|
Object.defineProperty(exports, "parseScanCode", { enumerable: true, get: function () { return parse_1.parseScanCode; } });
|
|
20
20
|
Object.defineProperty(exports, "interpolateScanTemplate", { enumerable: true, get: function () { return parse_1.interpolateScanTemplate; } });
|
|
21
|
+
Object.defineProperty(exports, "mentionsClaimToken", { enumerable: true, get: function () { return parse_1.mentionsClaimToken; } });
|
|
22
|
+
Object.defineProperty(exports, "ScanTemplateError", { enumerable: true, get: function () { return parse_1.ScanTemplateError; } });
|
|
21
23
|
var validate_1 = require("./validate");
|
|
22
24
|
Object.defineProperty(exports, "assertValidScheme", { enumerable: true, get: function () { return validate_1.assertValidScheme; } });
|
|
23
25
|
Object.defineProperty(exports, "assertValidSteps", { enumerable: true, get: function () { return validate_1.assertValidSteps; } });
|
|
@@ -26,10 +26,24 @@ export interface ScanTemplateContext {
|
|
|
26
26
|
target: string;
|
|
27
27
|
category: string;
|
|
28
28
|
scannedAt: string;
|
|
29
|
+
/** The acting user's single live claim, its metadata; absent when none or ambiguous. */
|
|
30
|
+
claim?: Record<string, unknown>;
|
|
31
|
+
/** The row an item-mode accumulate step located, its metadata. */
|
|
32
|
+
item?: Record<string, unknown>;
|
|
29
33
|
}
|
|
34
|
+
/** A `{claim.x}` or `{item.x}` token the context cannot resolve. */
|
|
35
|
+
export declare class ScanTemplateError extends Error {
|
|
36
|
+
readonly token: string;
|
|
37
|
+
readonly reason: string;
|
|
38
|
+
constructor(token: string, reason: string);
|
|
39
|
+
}
|
|
40
|
+
/** True when any string in the params mentions a `{claim.…}` token. */
|
|
41
|
+
export declare function mentionsClaimToken(value: unknown): boolean;
|
|
30
42
|
/**
|
|
31
|
-
* Replace
|
|
32
|
-
* Deep, pure, non-mutating.
|
|
33
|
-
*
|
|
43
|
+
* Replace the template tokens inside string values of a params object.
|
|
44
|
+
* Deep, pure, non-mutating. The three scan tokens are plain text
|
|
45
|
+
* replacement; `{claim.<facet>}` and `{item.<facet>}` read the context's
|
|
46
|
+
* facet bags and throw {@link ScanTemplateError} when they cannot resolve,
|
|
47
|
+
* so a literal token never reaches a row. No expression language.
|
|
34
48
|
*/
|
|
35
49
|
export declare function interpolateScanTemplate<T>(value: T, ctx: ScanTemplateContext): T;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ScanTemplateError = void 0;
|
|
3
4
|
exports.parseScanCode = parseScanCode;
|
|
5
|
+
exports.mentionsClaimToken = mentionsClaimToken;
|
|
4
6
|
exports.interpolateScanTemplate = interpolateScanTemplate;
|
|
5
7
|
const types_1 = require("../../types");
|
|
6
8
|
/**
|
|
@@ -82,17 +84,48 @@ function malformed(scheme, detail) {
|
|
|
82
84
|
failure: { reason: 'malformed', detail: `scheme ${scheme.version} ("${scheme.name}"): ${detail}` },
|
|
83
85
|
};
|
|
84
86
|
}
|
|
87
|
+
/** A `{claim.x}` or `{item.x}` token the context cannot resolve. */
|
|
88
|
+
class ScanTemplateError extends Error {
|
|
89
|
+
constructor(token, reason) {
|
|
90
|
+
super(`scan template ${token}: ${reason}`);
|
|
91
|
+
this.token = token;
|
|
92
|
+
this.reason = reason;
|
|
93
|
+
this.name = 'ScanTemplateError';
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.ScanTemplateError = ScanTemplateError;
|
|
97
|
+
const BAG_TOKEN = /\{(claim|item)\.([a-zA-Z0-9_]+)\}/g;
|
|
98
|
+
/** True when any string in the params mentions a `{claim.…}` token. */
|
|
99
|
+
function mentionsClaimToken(value) {
|
|
100
|
+
return JSON.stringify(value ?? null).includes(`{${types_1.SCAN_TEMPLATE_BAGS.CLAIM}.`);
|
|
101
|
+
}
|
|
102
|
+
function resolveBagToken(ctx, bag, facet, token) {
|
|
103
|
+
const source = bag === types_1.SCAN_TEMPLATE_BAGS.CLAIM ? ctx.claim : ctx.item;
|
|
104
|
+
if (!source) {
|
|
105
|
+
throw new ScanTemplateError(token, bag === types_1.SCAN_TEMPLATE_BAGS.CLAIM
|
|
106
|
+
? 'the actor holds no single live claim'
|
|
107
|
+
: 'no located item row on this step');
|
|
108
|
+
}
|
|
109
|
+
const v = source[facet];
|
|
110
|
+
if (v === undefined || v === null || v === '') {
|
|
111
|
+
throw new ScanTemplateError(token, `facet ${facet} is absent`);
|
|
112
|
+
}
|
|
113
|
+
return typeof v === 'object' ? JSON.stringify(v) : String(v);
|
|
114
|
+
}
|
|
85
115
|
/**
|
|
86
|
-
* Replace
|
|
87
|
-
* Deep, pure, non-mutating.
|
|
88
|
-
*
|
|
116
|
+
* Replace the template tokens inside string values of a params object.
|
|
117
|
+
* Deep, pure, non-mutating. The three scan tokens are plain text
|
|
118
|
+
* replacement; `{claim.<facet>}` and `{item.<facet>}` read the context's
|
|
119
|
+
* facet bags and throw {@link ScanTemplateError} when they cannot resolve,
|
|
120
|
+
* so a literal token never reaches a row. No expression language.
|
|
89
121
|
*/
|
|
90
122
|
function interpolateScanTemplate(value, ctx) {
|
|
91
123
|
if (typeof value === 'string') {
|
|
92
|
-
|
|
124
|
+
const scanned = value
|
|
93
125
|
.split(types_1.SCAN_TEMPLATE_TOKENS.TARGET).join(ctx.target)
|
|
94
126
|
.split(types_1.SCAN_TEMPLATE_TOKENS.CATEGORY).join(ctx.category)
|
|
95
127
|
.split(types_1.SCAN_TEMPLATE_TOKENS.SCANNED_AT).join(ctx.scannedAt);
|
|
128
|
+
return scanned.replace(BAG_TOKEN, (token, bag, facet) => resolveBagToken(ctx, bag, facet, token));
|
|
96
129
|
}
|
|
97
130
|
if (Array.isArray(value)) {
|
|
98
131
|
return value.map((v) => interpolateScanTemplate(v, ctx));
|