@hotmeshio/long-tail 0.20.0 → 0.21.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/README.md +4 -4
- package/build/api/escalations/accumulate.d.ts +104 -0
- package/build/api/escalations/accumulate.js +541 -0
- package/build/api/escalations/index.d.ts +1 -0
- package/build/api/escalations/index.js +11 -1
- package/build/api/roles.d.ts +4 -5
- package/build/api/roles.js +53 -4
- package/build/api/scan-codes/context.d.ts +14 -1
- package/build/api/scan-codes/context.js +30 -2
- package/build/api/scan-codes/execute.js +2 -0
- package/build/api/scan-codes/identity.js +1 -0
- package/build/api/scan-codes/verbs.d.ts +21 -0
- package/build/api/scan-codes/verbs.js +122 -3
- package/build/index.d.ts +2 -1
- package/build/index.js +63 -2
- package/build/lib/db/schemas/036_role_portals.sql +12 -0
- package/build/routes/escalations/accumulate.d.ts +7 -0
- package/build/routes/escalations/accumulate.js +158 -0
- package/build/routes/escalations/index.js +5 -0
- package/build/sdk/index.d.ts +28 -0
- package/build/sdk/index.js +9 -0
- package/build/services/escalation/accumulate.d.ts +81 -0
- package/build/services/escalation/accumulate.js +154 -0
- package/build/services/escalation/index.d.ts +1 -0
- package/build/services/escalation/index.js +1 -0
- package/build/services/mcp/playwright-server/schemas.d.ts +2 -2
- package/build/services/orchestrator/condition.d.ts +40 -3
- package/build/services/orchestrator/condition.js +42 -2
- package/build/services/role/index.js +1 -0
- package/build/services/role/seed.js +6 -1
- package/build/services/role/sql.d.ts +6 -3
- package/build/services/role/sql.js +7 -2
- package/build/services/role/types.d.ts +38 -10
- package/build/services/role/types.js +10 -1
- 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 +35 -0
- package/build/shared/form-validation/display-only-widgets.d.ts +16 -0
- package/build/shared/form-validation/display-only-widgets.js +25 -0
- package/build/shared/form-validation/index.d.ts +2 -0
- package/build/shared/form-validation/index.js +2 -0
- package/build/shared/form-validation/x-lt-bind.d.ts +2 -14
- package/build/shared/form-validation/x-lt-bind.js +12 -8
- package/build/shared/form-validation/x-lt-invoke.d.ts +38 -0
- package/build/shared/form-validation/x-lt-invoke.js +103 -0
- package/build/system/mcp-servers/admin/escalations.js +44 -0
- package/build/system/mcp-servers/admin/schemas.d.ts +195 -13
- package/build/system/mcp-servers/admin/schemas.js +40 -3
- package/build/system/mcp-servers/admin/users.js +1 -0
- package/build/system/mcp-servers/docs.js +4 -0
- package/build/system/mcp-servers/human-queue-schemas.d.ts +85 -0
- package/build/system/mcp-servers/human-queue-schemas.js +19 -1
- package/build/system/mcp-servers/human-queue.d.ts +2 -0
- package/build/system/mcp-servers/human-queue.js +77 -0
- package/build/system/seed/tool-manifests-admin.d.ts +1108 -100
- package/build/system/seed/tool-manifests-admin.js +4 -1
- package/build/system/seed/tool-manifests-escalation.d.ts +174 -0
- package/build/system/seed/tool-manifests-escalation.js +56 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/escalation.d.ts +52 -0
- package/build/types/escalation.js +29 -1
- package/build/types/index.d.ts +4 -4
- package/build/types/index.js +4 -1
- package/build/types/scan-code.d.ts +55 -1
- package/build/types/scan-code.js +29 -2
- package/build/types/startup.d.ts +20 -0
- package/dashboard/dist/assets/{AdminDashboard-DplvDBti.js → AdminDashboard-Covdam48.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-DplvDBti.js.map → AdminDashboard-Covdam48.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-D8Bf6YxO.js → AgentConfigPage-CE1k6J5r.js} +6 -6
- package/dashboard/dist/assets/{AgentConfigPage-D8Bf6YxO.js.map → AgentConfigPage-CE1k6J5r.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-BN8g0Y2G.js → AgentDetailPage-CWJZIZP1.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-BN8g0Y2G.js.map → AgentDetailPage-CWJZIZP1.js.map} +1 -1
- package/dashboard/dist/assets/AgentsPage---Dg5ufF.js +2 -0
- package/dashboard/dist/assets/{AgentsPage-7JJBHku8.js.map → AgentsPage---Dg5ufF.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-CpbC8oTN.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-CpbC8oTN.js.map +1 -0
- package/dashboard/dist/assets/{BotPicker-CGCnIz8I.js → BotPicker-D3drO3-T.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-CGCnIz8I.js.map → BotPicker-D3drO3-T.js.map} +1 -1
- package/dashboard/dist/assets/BulkAssignModal-BOAWsViq.js +2 -0
- package/dashboard/dist/assets/{BulkAssignModal-NJBcoj-f.js.map → BulkAssignModal-BOAWsViq.js.map} +1 -1
- package/dashboard/dist/assets/CapabilitiesPage-RGgD3YZO.js +2 -0
- package/dashboard/dist/assets/{CapabilitiesPage-F8dpNn9B.js.map → CapabilitiesPage-RGgD3YZO.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-BZW6VpCU.js → CollapsibleSection-DNkZn87n.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-BZW6VpCU.js.map → CollapsibleSection-DNkZn87n.js.map} +1 -1
- package/dashboard/dist/assets/{ConfirmDeleteModal-64adXLdq.js → ConfirmDeleteModal-BqzOwhPr.js} +2 -2
- package/dashboard/dist/assets/{ConfirmDeleteModal-64adXLdq.js.map → ConfirmDeleteModal-BqzOwhPr.js.map} +1 -1
- package/dashboard/dist/assets/{CountdownTimer-BxDub9d2.js → CountdownTimer-BaexQMK6.js} +2 -2
- package/dashboard/dist/assets/{CountdownTimer-BxDub9d2.js.map → CountdownTimer-BaexQMK6.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-CnLzopLL.js → CredentialsPage-D7abp0aS.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-CnLzopLL.js.map → CredentialsPage-D7abp0aS.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-CAD5UYDT.js → CronLabel-DZiWmTwJ.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-CAD5UYDT.js.map → CronLabel-DZiWmTwJ.js.map} +1 -1
- package/dashboard/dist/assets/DataTable-spX1dFyb.js +2 -0
- package/dashboard/dist/assets/DataTable-spX1dFyb.js.map +1 -0
- package/dashboard/dist/assets/{DropZone-XlcY8hEH.js → DropZone-f1o-GLM8.js} +2 -2
- package/dashboard/dist/assets/{DropZone-XlcY8hEH.js.map → DropZone-f1o-GLM8.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-CwO4ufd0.js → ElapsedCell-BdGO_w4v.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-CwO4ufd0.js.map → ElapsedCell-BdGO_w4v.js.map} +1 -1
- package/dashboard/dist/assets/EntityTimelinePanel-DIDcF5Yu.js +2 -0
- package/dashboard/dist/assets/{EntityTimelinePanel-CkF-oW-m.js.map → EntityTimelinePanel-DIDcF5Yu.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-h9JO_q5f.js → EscalationListSchemaPage-C28rn9XC.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-h9JO_q5f.js.map → EscalationListSchemaPage-C28rn9XC.js.map} +1 -1
- package/dashboard/dist/assets/EscalationListView-CkBnkpDJ.js +2 -0
- package/dashboard/dist/assets/EscalationListView-CkBnkpDJ.js.map +1 -0
- package/dashboard/dist/assets/{EscalationSchemaPage-mJFL5_Se.js → EscalationSchemaPage-W5r0A1kj.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-mJFL5_Se.js.map → EscalationSchemaPage-W5r0A1kj.js.map} +1 -1
- package/dashboard/dist/assets/EscalationTimeline-DKyTz6sM.js +2 -0
- package/dashboard/dist/assets/EscalationTimeline-DKyTz6sM.js.map +1 -0
- package/dashboard/dist/assets/EscalationTitleSelect-CzKfavri.js +2 -0
- package/dashboard/dist/assets/EscalationTitleSelect-CzKfavri.js.map +1 -0
- package/dashboard/dist/assets/{EscalationsOverview-DlXUFqWJ.js → EscalationsOverview-Tdu3Yx2c.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-DlXUFqWJ.js.map → EscalationsOverview-Tdu3Yx2c.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-Ike2xchn.js → EventTable-DiIxOJwO.js} +2 -2
- package/dashboard/dist/assets/{EventTable-Ike2xchn.js.map → EventTable-DiIxOJwO.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-DMOR-O1c.js → FilterBar-CvMBCVIo.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-DMOR-O1c.js.map → FilterBar-CvMBCVIo.js.map} +1 -1
- package/dashboard/dist/assets/GraphInvokePage-DO-yyhi6.js +2 -0
- package/dashboard/dist/assets/{GraphInvokePage-CKtvWowP.js.map → GraphInvokePage-DO-yyhi6.js.map} +1 -1
- package/dashboard/dist/assets/HomePage-DSS3eHR2.js +2 -0
- package/dashboard/dist/assets/{HomePage-BQ3Q791Q.js.map → HomePage-DSS3eHR2.js.map} +1 -1
- package/dashboard/dist/assets/ListToolbar-C3-Tqqub.js +2 -0
- package/dashboard/dist/assets/{ListToolbar-DdJzj472.js.map → ListToolbar-C3-Tqqub.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-BbtrduWn.js → McpOverview-DEJmsdVi.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-BbtrduWn.js.map → McpOverview-DEJmsdVi.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-C1L4T-Wt.js → McpQueryDetailPage-DYJr16l7.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-C1L4T-Wt.js.map → McpQueryDetailPage-DYJr16l7.js.map} +1 -1
- package/dashboard/dist/assets/McpQueryPage-BBcG_UuU.js +2 -0
- package/dashboard/dist/assets/{McpQueryPage-CfJy7HZ7.js.map → McpQueryPage-BBcG_UuU.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-CA9yv7he.js → McpRunDetailPage-C6xw0kBg.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-CA9yv7he.js.map → McpRunDetailPage-C6xw0kBg.js.map} +1 -1
- package/dashboard/dist/assets/McpRunsPage-CRQqrF4Q.js +2 -0
- package/dashboard/dist/assets/{McpRunsPage-D7QXjW9z.js.map → McpRunsPage-CRQqrF4Q.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-Bb3revqD.js → NamespacePill-DADRJOUl.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-Bb3revqD.js.map → NamespacePill-DADRJOUl.js.map} +1 -1
- package/dashboard/dist/assets/OperationsPage-Dlfwzf-0.js +3 -0
- package/dashboard/dist/assets/OperationsPage-Dlfwzf-0.js.map +1 -0
- package/dashboard/dist/assets/OperatorDashboard-DoiDGZ9R.js +2 -0
- package/dashboard/dist/assets/{OperatorDashboard-sXNDh1Ph.js.map → OperatorDashboard-DoiDGZ9R.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-Di5Sz3an.js → PageHeader-Csq434-v.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-Di5Sz3an.js.map → PageHeader-Csq434-v.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-DutKJ-h2.js → PageHeaderWithStats-CSnk1p5A.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-DutKJ-h2.js.map → PageHeaderWithStats-CSnk1p5A.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-NeHD-Gra.js → PersonaDetailPage-BzbA4Prr.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-NeHD-Gra.js.map → PersonaDetailPage-BzbA4Prr.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-DavKXRWX.js → PersonasPage-B36yn4hU.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-DavKXRWX.js.map → PersonasPage-B36yn4hU.js.map} +1 -1
- package/dashboard/dist/assets/PortalPage-BkD4YfDf.js +2 -0
- package/dashboard/dist/assets/PortalPage-BkD4YfDf.js.map +1 -0
- package/dashboard/dist/assets/{ProcessDetailPage-DkdKJGe6.js → ProcessDetailPage-BT0eiBWY.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-DkdKJGe6.js.map → ProcessDetailPage-BT0eiBWY.js.map} +1 -1
- package/dashboard/dist/assets/ProcessesListPage-BEqeeNae.js +2 -0
- package/dashboard/dist/assets/{ProcessesListPage-CjwVKe32.js.map → ProcessesListPage-BEqeeNae.js.map} +1 -1
- package/dashboard/dist/assets/ResolverForm-BwgjIX97.js +7 -0
- package/dashboard/dist/assets/ResolverForm-BwgjIX97.js.map +1 -0
- package/dashboard/dist/assets/RoleDetailPage-BFuLNJXa.js +8 -0
- package/dashboard/dist/assets/RoleDetailPage-BFuLNJXa.js.map +1 -0
- package/dashboard/dist/assets/{RolePill-DhnVPK4q.js → RolePill-BafrASDX.js} +2 -2
- package/dashboard/dist/assets/{RolePill-DhnVPK4q.js.map → RolePill-BafrASDX.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-OM9KM8Pg.js → RolesPage-80quJU5-.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-OM9KM8Pg.js.map → RolesPage-80quJU5-.js.map} +1 -1
- package/dashboard/dist/assets/RunAsSelector-BoePhWVD.js +2 -0
- package/dashboard/dist/assets/{RunAsSelector-fFMt1bGe.js.map → RunAsSelector-BoePhWVD.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-AujH-pPQ.js → ScanCodesPage-Cu1bKEix.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-AujH-pPQ.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-gcZGefvT.js +2 -0
- package/dashboard/dist/assets/{ScanStationPage-C1_ppDoZ.js.map → ScanStationPage-gcZGefvT.js.map} +1 -1
- package/dashboard/dist/assets/{ScopeBadge-CXUg0FHo.js → ScopeBadge-b6MIBiYD.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-CXUg0FHo.js.map → ScopeBadge-b6MIBiYD.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-B91Pk9xh.js → StickyPagination-9ITrei_d.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-B91Pk9xh.js.map → StickyPagination-9ITrei_d.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-C7SPqaJt.js → StreamMessageDetail-BkYvEHFY.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-C7SPqaJt.js.map → StreamMessageDetail-BkYvEHFY.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-BcHR8ylf.js → SwimlaneTimeline-B1rotFix.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-BcHR8ylf.js.map → SwimlaneTimeline-B1rotFix.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-BZ8vb2oW.js → TagInput-ZrIIrEUP.js} +2 -2
- package/dashboard/dist/assets/{TagInput-BZ8vb2oW.js.map → TagInput-ZrIIrEUP.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-Bqj0I_I0.js → TaskDetailPage-zhn_U_eC.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-Bqj0I_I0.js.map → TaskDetailPage-zhn_U_eC.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-Bxir8WRl.js → TaskQueuePill-DkQ1uc6y.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-Bxir8WRl.js.map → TaskQueuePill-DkQ1uc6y.js.map} +1 -1
- package/dashboard/dist/assets/TasksListPage-CNbNeagx.js +2 -0
- package/dashboard/dist/assets/{TasksListPage-BB1f79lL.js.map → TasksListPage-CNbNeagx.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-BFnODmNe.js → TimeAgo-0YVMBwls.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-BFnODmNe.js.map → TimeAgo-0YVMBwls.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-BXgLOBsr.js → TimestampCell-DB7r3np8.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-BXgLOBsr.js.map → TimestampCell-DB7r3np8.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-FkgTXIhq.js → ToolPill-Baxm02L6.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-FkgTXIhq.js.map → ToolPill-Baxm02L6.js.map} +1 -1
- package/dashboard/dist/assets/ToolTestPanel-BLfA02wv.js +2 -0
- package/dashboard/dist/assets/{ToolTestPanel-Bwe3J5lj.js.map → ToolTestPanel-BLfA02wv.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-DAF07vZ9.js → TopicDetailPage-eAqPKShq.js} +3 -3
- package/dashboard/dist/assets/{TopicDetailPage-DAF07vZ9.js.map → TopicDetailPage-eAqPKShq.js.map} +1 -1
- package/dashboard/dist/assets/TopicsPage-BNNWD-zl.js +2 -0
- package/dashboard/dist/assets/{TopicsPage-C1gxBUap.js.map → TopicsPage-BNNWD-zl.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-BzXJUE6q.js → UserName-Pw46tO_k.js} +2 -2
- package/dashboard/dist/assets/{UserName-BzXJUE6q.js.map → UserName-Pw46tO_k.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-SkRU5cRX.js → WorkflowExecutionPage-DvA51lT3.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-SkRU5cRX.js.map → WorkflowExecutionPage-DvA51lT3.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill--AYMW7u_.js → WorkflowPill-ZepbO_ny.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill--AYMW7u_.js.map → WorkflowPill-ZepbO_ny.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowsDashboard-DFDTwnhn.js +2 -0
- package/dashboard/dist/assets/{WorkflowsDashboard-CZAqRk1N.js.map → WorkflowsDashboard-DFDTwnhn.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-BoN44VTE.js → WorkflowsOverview-5i2Tcy-p.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-BoN44VTE.js.map → WorkflowsOverview-5i2Tcy-p.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CqjhtdJf.js → YamlWorkflowDetailPage-p4VEYZS0.js} +11 -11
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CqjhtdJf.js.map → YamlWorkflowDetailPage-p4VEYZS0.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-CwnJkzyb.js → YamlWorkflowsPage-Cq-hMVxl.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-CwnJkzyb.js.map → YamlWorkflowsPage-Cq-hMVxl.js.map} +1 -1
- package/dashboard/dist/assets/{agents-gV0Ys-sY.js → agents-EyBPJMYa.js} +2 -2
- package/dashboard/dist/assets/{agents-gV0Ys-sY.js.map → agents-EyBPJMYa.js.map} +1 -1
- package/dashboard/dist/assets/{bots-B97itB3I.js → bots-DX6jjqtF.js} +2 -2
- package/dashboard/dist/assets/{bots-B97itB3I.js.map → bots-DX6jjqtF.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-CR9xZgGd.js → capabilities-ZdLv9xBQ.js} +2 -2
- package/dashboard/dist/assets/{capabilities-CR9xZgGd.js.map → capabilities-ZdLv9xBQ.js.map} +1 -1
- package/dashboard/dist/assets/{constants-BHkpVaqx.js → constants-CeBBTzf5.js} +2 -2
- package/dashboard/dist/assets/{constants-BHkpVaqx.js.map → constants-CeBBTzf5.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-YxvP1KCa.js → controlplane-CpvZaJuw.js} +2 -2
- package/dashboard/dist/assets/{controlplane-YxvP1KCa.js.map → controlplane-CpvZaJuw.js.map} +1 -1
- package/dashboard/dist/assets/escalation-columns-Mvsze5eV.js +2 -0
- package/dashboard/dist/assets/escalation-columns-Mvsze5eV.js.map +1 -0
- package/dashboard/dist/assets/index-B_GT23TE.js +3 -0
- package/dashboard/dist/assets/index-B_GT23TE.js.map +1 -0
- package/dashboard/dist/assets/index-BbCjGO3M.js +2 -0
- package/dashboard/dist/assets/{index-CFbo9FU9.js.map → index-BbCjGO3M.js.map} +1 -1
- package/dashboard/dist/assets/{index-DMeaiKgf.js → index-Bhb89oHH.js} +2 -2
- package/dashboard/dist/assets/{index-DMeaiKgf.js.map → index-Bhb89oHH.js.map} +1 -1
- package/dashboard/dist/assets/index-CgUcYveM.js +67 -0
- package/dashboard/dist/assets/index-CgUcYveM.js.map +1 -0
- package/dashboard/dist/assets/index-Cn8uJsd7.js +2 -0
- package/dashboard/dist/assets/{index-BQpV-DTG.js.map → index-Cn8uJsd7.js.map} +1 -1
- package/dashboard/dist/assets/index-D-Xs4rAW.js +2 -0
- package/dashboard/dist/assets/{index-Bp9KBLT5.js.map → index-D-Xs4rAW.js.map} +1 -1
- package/dashboard/dist/assets/{index-DwOnWeu8.js → index-DGmzBY9D.js} +2 -2
- package/dashboard/dist/assets/{index-DwOnWeu8.js.map → index-DGmzBY9D.js.map} +1 -1
- package/dashboard/dist/assets/{index-CIpHj4di.js → index-DZhtP2Ok.js} +2 -2
- package/dashboard/dist/assets/{index-CIpHj4di.js.map → index-DZhtP2Ok.js.map} +1 -1
- package/dashboard/dist/assets/index-Dh8MJl3L.css +1 -0
- package/dashboard/dist/assets/index-DkrBFFSO.js +13 -0
- package/dashboard/dist/assets/{index-Cfvkl2J0.js.map → index-DkrBFFSO.js.map} +1 -1
- package/dashboard/dist/assets/{index-B9BBCqLI.js → index-Eo-l3Lqo.js} +2 -2
- package/dashboard/dist/assets/{index-B9BBCqLI.js.map → index-Eo-l3Lqo.js.map} +1 -1
- package/dashboard/dist/assets/index-PfSRKerc.js +2 -0
- package/dashboard/dist/assets/{index-CUZ6LYye.js.map → index-PfSRKerc.js.map} +1 -1
- package/dashboard/dist/assets/{index-ipqwPavs.js → index-oFKUFGQL.js} +2 -2
- package/dashboard/dist/assets/{index-ipqwPavs.js.map → index-oFKUFGQL.js.map} +1 -1
- package/dashboard/dist/assets/index-z5Hpeidu.js +2 -0
- package/dashboard/dist/assets/index-z5Hpeidu.js.map +1 -0
- package/dashboard/dist/assets/{knowledge-XX6cW4Ob.js → knowledge-CgloEkaf.js} +2 -2
- package/dashboard/dist/assets/{knowledge-XX6cW4Ob.js.map → knowledge-CgloEkaf.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-CH13hNH2.js → mcp-Bix7QYO7.js} +2 -2
- package/dashboard/dist/assets/{mcp-CH13hNH2.js.map → mcp-Bix7QYO7.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-Duydd3JA.js → mcp-query-o-sGX2ST.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-Duydd3JA.js.map → mcp-query-o-sGX2ST.js.map} +1 -1
- package/dashboard/dist/assets/metadata-display-COo3mMCr.js +2 -0
- package/dashboard/dist/assets/metadata-display-COo3mMCr.js.map +1 -0
- package/dashboard/dist/assets/{personas-mDk4lLQS.js → personas-30azkJ_s.js} +2 -2
- package/dashboard/dist/assets/{personas-mDk4lLQS.js.map → personas-30azkJ_s.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-B5GcgCeF.js → pipelines-Bfk2GFK7.js} +2 -2
- package/dashboard/dist/assets/{pipelines-B5GcgCeF.js.map → pipelines-Bfk2GFK7.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-CItmNsRp.js → tasks-CpdopewW.js} +2 -2
- package/dashboard/dist/assets/{tasks-CItmNsRp.js.map → tasks-CpdopewW.js.map} +1 -1
- package/dashboard/dist/assets/{topics-CJYG7BX5.js → topics--bvCV9Yp.js} +2 -2
- package/dashboard/dist/assets/{topics-CJYG7BX5.js.map → topics--bvCV9Yp.js.map} +1 -1
- package/dashboard/dist/assets/useContainerWidth-DSLp1gEm.js +2 -0
- package/dashboard/dist/assets/useContainerWidth-DSLp1gEm.js.map +1 -0
- package/dashboard/dist/assets/{useDebouncedValue-BrwgXcp8.js → useDebouncedValue-Da0lPmj3.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-BrwgXcp8.js.map → useDebouncedValue-Da0lPmj3.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-CHty0HAS.js → useNamespace-DD_Esl6n.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-CHty0HAS.js.map → useNamespace-DD_Esl6n.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-CoTsia7t.js → useYamlActivityEvents-AeAhZJJk.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-CoTsia7t.js.map → useYamlActivityEvents-AeAhZJJk.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-DeBdvyKJ.js → vendor-icons-B7OcUM6b.js} +2 -2
- package/dashboard/dist/assets/{vendor-icons-DeBdvyKJ.js.map → vendor-icons-B7OcUM6b.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-CiWwx5rM.js → yaml-workflows-BHAOOGvn.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-CiWwx5rM.js.map → yaml-workflows-BHAOOGvn.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/accumulator.md +113 -0
- package/docs/api/http/escalations.md +90 -0
- package/docs/api/http/roles.md +1 -0
- package/docs/api/sdk/escalations.md +92 -0
- package/docs/api/sdk/roles.md +2 -0
- package/docs/architecture.md +1 -1
- package/docs/code-owned-configuration.md +2 -1
- package/docs/dashboard.md +10 -4
- package/docs/hitl/design.md +1 -1
- package/docs/hitl/escalation.md +37 -1
- package/docs/hitl/invoke-form.md +4 -0
- package/docs/hitl/pinned-views.md +4 -0
- package/docs/hitl/portal.md +97 -0
- package/docs/hitl/resolution.md +41 -0
- package/docs/hitl/x-lt-embed.md +1 -1
- package/docs/hitl/x-lt-invoke.md +95 -0
- package/docs/hitl/x-lt-list-schema.md +3 -1
- package/docs/hitl/x-lt-widget.md +1 -0
- package/docs/hitl-guide.md +8 -1
- package/docs/scan-codes.md +33 -9
- package/docs/sdk.md +1 -1
- package/docs/workflows.md +2 -2
- package/package.json +4 -2
- package/dashboard/dist/assets/AgentsPage-7JJBHku8.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-lz5qwSjg.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-lz5qwSjg.js.map +0 -1
- package/dashboard/dist/assets/BulkAssignModal-NJBcoj-f.js +0 -2
- package/dashboard/dist/assets/CapabilitiesPage-F8dpNn9B.js +0 -2
- package/dashboard/dist/assets/DataTable-7C7riavf.js +0 -2
- package/dashboard/dist/assets/DataTable-7C7riavf.js.map +0 -1
- package/dashboard/dist/assets/EntityTimelinePanel-CkF-oW-m.js +0 -2
- package/dashboard/dist/assets/EscalationListView-AHW2xtlr.js +0 -2
- package/dashboard/dist/assets/EscalationListView-AHW2xtlr.js.map +0 -1
- package/dashboard/dist/assets/GraphInvokePage-CKtvWowP.js +0 -2
- package/dashboard/dist/assets/HomePage-BQ3Q791Q.js +0 -2
- package/dashboard/dist/assets/ListToolbar-DdJzj472.js +0 -2
- package/dashboard/dist/assets/McpQueryPage-CfJy7HZ7.js +0 -2
- package/dashboard/dist/assets/McpRunsPage-D7QXjW9z.js +0 -2
- package/dashboard/dist/assets/OperationsPage-aLHHAP2X.js +0 -3
- package/dashboard/dist/assets/OperationsPage-aLHHAP2X.js.map +0 -1
- package/dashboard/dist/assets/OperatorDashboard-sXNDh1Ph.js +0 -2
- package/dashboard/dist/assets/ProcessesListPage-CjwVKe32.js +0 -2
- package/dashboard/dist/assets/ResolverForm-Bk-wDkN-.js +0 -3
- package/dashboard/dist/assets/ResolverForm-Bk-wDkN-.js.map +0 -1
- package/dashboard/dist/assets/RoleDetailPage-WQt0y5l7.js +0 -8
- package/dashboard/dist/assets/RoleDetailPage-WQt0y5l7.js.map +0 -1
- package/dashboard/dist/assets/RunAsSelector-fFMt1bGe.js +0 -2
- package/dashboard/dist/assets/ScanSchemeDetailPage-eKQpmsC_.js +0 -2
- package/dashboard/dist/assets/ScanSchemeDetailPage-eKQpmsC_.js.map +0 -1
- package/dashboard/dist/assets/ScanStationPage-C1_ppDoZ.js +0 -2
- package/dashboard/dist/assets/TasksListPage-BB1f79lL.js +0 -2
- package/dashboard/dist/assets/ToolTestPanel-Bwe3J5lj.js +0 -2
- package/dashboard/dist/assets/TopicsPage-C1gxBUap.js +0 -2
- package/dashboard/dist/assets/WorkflowsDashboard-CZAqRk1N.js +0 -2
- package/dashboard/dist/assets/escalation-columns-uq-IV2aj.js +0 -2
- package/dashboard/dist/assets/escalation-columns-uq-IV2aj.js.map +0 -1
- package/dashboard/dist/assets/index-3ezfWLkE.js +0 -6
- package/dashboard/dist/assets/index-3ezfWLkE.js.map +0 -1
- package/dashboard/dist/assets/index-BQpV-DTG.js +0 -2
- package/dashboard/dist/assets/index-Bp9KBLT5.js +0 -2
- package/dashboard/dist/assets/index-Bpvfr4OW.css +0 -1
- package/dashboard/dist/assets/index-CFbo9FU9.js +0 -2
- package/dashboard/dist/assets/index-CIwlVfvV.js +0 -67
- package/dashboard/dist/assets/index-CIwlVfvV.js.map +0 -1
- package/dashboard/dist/assets/index-CUZ6LYye.js +0 -2
- package/dashboard/dist/assets/index-Cfvkl2J0.js +0 -13
- package/dashboard/dist/assets/index-SGyrXGp8.js +0 -3
- package/dashboard/dist/assets/index-SGyrXGp8.js.map +0 -1
- package/dashboard/dist/assets/invoke-context-DrVyUEfs.js +0 -2
- package/dashboard/dist/assets/invoke-context-DrVyUEfs.js.map +0 -1
- package/dashboard/dist/assets/metadata-display--TzK0REC.js +0 -2
- package/dashboard/dist/assets/metadata-display--TzK0REC.js.map +0 -1
- package/dashboard/dist/assets/resolver-payload-m9AGKZ3a.js +0 -2
- package/dashboard/dist/assets/resolver-payload-m9AGKZ3a.js.map +0 -1
- package/docs/compilation.md +0 -152
- package/docs/compiler.md +0 -311
- package/docs/contributing.md +0 -56
- package/docs/design-principles.md +0 -245
- package/docs/schema-exchange.md +0 -173
- package/docs/self-test.md +0 -106
- package/docs/story.md +0 -184
package/README.md
CHANGED
|
@@ -234,13 +234,13 @@ All modes share PostgreSQL and scale independently. See [Cloud Deployment](https
|
|
|
234
234
|
|
|
235
235
|
| Guide | What it covers |
|
|
236
236
|
|-------|---------------|
|
|
237
|
-
| [The Long Tail Story](https://github.com/hotmeshio/long-tail/blob/main/docs/story.md) | Why this exists, what accumulates over time |
|
|
237
|
+
| [The Long Tail Story](https://github.com/hotmeshio/long-tail/blob/main/docs/donotpublish/story.md) | Why this exists, what accumulates over time |
|
|
238
238
|
| [Workflows](https://github.com/hotmeshio/long-tail/blob/main/docs/workflows.md) | Activities, interceptor, escalation lifecycle, composition |
|
|
239
239
|
| [IAM](https://github.com/hotmeshio/long-tail/blob/main/docs/iam.md) | Identity propagation, service accounts, credential exchange |
|
|
240
240
|
| [Dashboard](https://github.com/hotmeshio/long-tail/blob/main/docs/dashboard.md) | Navigation, key pages, event feed |
|
|
241
241
|
| [MCP](https://github.com/hotmeshio/long-tail/blob/main/docs/mcp.md) | Server registration, tool calls, human queue |
|
|
242
|
-
| [Compilation](https://github.com/hotmeshio/long-tail/blob/main/docs/compilation.md) | Dynamic to deterministic pipeline wizard |
|
|
243
|
-
| [Compiler](https://github.com/hotmeshio/long-tail/blob/main/docs/compiler.md) | `ltc compile` — durable TypeScript to YAML DAGs |
|
|
242
|
+
| [Compilation](https://github.com/hotmeshio/long-tail/blob/main/docs/donotpublish/compilation.md) | Dynamic to deterministic pipeline wizard |
|
|
243
|
+
| [Compiler](https://github.com/hotmeshio/long-tail/blob/main/docs/donotpublish/compiler.md) | `ltc compile` — durable TypeScript to YAML DAGs |
|
|
244
244
|
| [CLI](https://github.com/hotmeshio/long-tail/blob/main/docs/cli.md) | `ltc` — terminal access to workflows, escalations, knowledge, MCP |
|
|
245
245
|
| [Escalation Strategies](https://github.com/hotmeshio/long-tail/blob/main/docs/escalation-strategies.md) | Default, MCP triage, custom handlers |
|
|
246
246
|
| [Schema Enforcement](https://github.com/hotmeshio/long-tail/blob/main/docs/schema-enforcement.md) | form_schema as an enforced API contract on every resolve surface |
|
|
@@ -274,7 +274,7 @@ Open [http://localhost:3000](http://localhost:3000). Example workflows seed the
|
|
|
274
274
|
| `engineer` | `l0ngt@1l` | engineer |
|
|
275
275
|
| `reviewer` | `l0ngt@1l` | reviewer |
|
|
276
276
|
|
|
277
|
-
See [Contributing](https://github.com/hotmeshio/long-tail/blob/main/docs/contributing.md).
|
|
277
|
+
See [Contributing](https://github.com/hotmeshio/long-tail/blob/main/docs/donotpublish/contributing.md).
|
|
278
278
|
|
|
279
279
|
## License
|
|
280
280
|
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { AccumulatedItem, LTEscalationRecord } from '../../types';
|
|
2
|
+
import type { LTApiAuth, LTApiResult } from '../../types/sdk';
|
|
3
|
+
/** Names the second row of a reciprocal add or removal. Exactly one selector. */
|
|
4
|
+
export interface ReciprocalInput {
|
|
5
|
+
id?: string;
|
|
6
|
+
signalKey?: string;
|
|
7
|
+
key?: string;
|
|
8
|
+
value?: string;
|
|
9
|
+
payload?: Record<string, any>;
|
|
10
|
+
}
|
|
11
|
+
export interface AccumulateItemInput {
|
|
12
|
+
itemKey: string;
|
|
13
|
+
/** Stored on the entry and delivered inside `$accumulated`. Validates
|
|
14
|
+
* against the container's versioned role form when present. */
|
|
15
|
+
payload?: Record<string, any>;
|
|
16
|
+
metadata?: Record<string, any>;
|
|
17
|
+
assertClaim?: boolean;
|
|
18
|
+
reciprocal?: ReciprocalInput;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Add ONE item to an accumulator escalation (a `conditional` wait declared
|
|
22
|
+
* with `accumulate: {...}`). Interim adds are cheap atomic row appends: the
|
|
23
|
+
* row stays pending and `count`/`remaining` report progress. An add that
|
|
24
|
+
* reaches `max` completes the escalation: the row resolves and the waiting
|
|
25
|
+
* workflow wakes with the ordered collection, in the same statement.
|
|
26
|
+
*
|
|
27
|
+
* With `reciprocal`, a second accumulator row is written in that same
|
|
28
|
+
* statement or not at all: it holds this container's id as its item key and
|
|
29
|
+
* each entry points at the other row. The reciprocal is RBAC-gated here
|
|
30
|
+
* before the statement runs.
|
|
31
|
+
*
|
|
32
|
+
* Claim semantics match batch: claim-agnostic by default (a container
|
|
33
|
+
* collects contributions from many hands); `assertClaim: true` requires the
|
|
34
|
+
* caller's own live claim, asserted atomically inside the SDK statement.
|
|
35
|
+
*/
|
|
36
|
+
export declare function accumulateItem(input: {
|
|
37
|
+
id: string;
|
|
38
|
+
} & AccumulateItemInput, auth: LTApiAuth): Promise<LTApiResult>;
|
|
39
|
+
/**
|
|
40
|
+
* Add selecting the container by its `signal_key`, the deterministic home
|
|
41
|
+
* signal id the waiting workflow parked on. Mirrors resolve-by-signal-key:
|
|
42
|
+
* claim-agnostic, write-scope gated with 404 non-disclosure.
|
|
43
|
+
*/
|
|
44
|
+
export declare function accumulateItemBySignalKey(input: {
|
|
45
|
+
signalKey: string;
|
|
46
|
+
} & Omit<AccumulateItemInput, 'assertClaim'>, auth: LTApiAuth): Promise<LTApiResult>;
|
|
47
|
+
/**
|
|
48
|
+
* Add selecting the container by metadata facet, the faceted sibling of
|
|
49
|
+
* {@link accumulateItem}. RBAC folds into the SDK's atomic facet selection
|
|
50
|
+
* as a flat role filter. Schema enforcement is two-phase when enforcing
|
|
51
|
+
* roles exist and a payload is present: the row is picked first, validated
|
|
52
|
+
* against ITS schema, then written by asserted id; a row that went terminal
|
|
53
|
+
* between phases surfaces as a 409.
|
|
54
|
+
*/
|
|
55
|
+
export declare function accumulateItemByMetadata(input: {
|
|
56
|
+
key: string;
|
|
57
|
+
value: string;
|
|
58
|
+
restrictRoles?: string[];
|
|
59
|
+
} & Omit<AccumulateItemInput, 'assertClaim'>, auth: LTApiAuth): Promise<LTApiResult>;
|
|
60
|
+
export interface RemoveItemInput {
|
|
61
|
+
itemKey: string;
|
|
62
|
+
reciprocal?: Omit<ReciprocalInput, 'payload'>;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Remove ONE held item from a pending accumulator escalation, one guarded
|
|
66
|
+
* statement, no wake. With `reciprocal`, the container's id leaves that row
|
|
67
|
+
* in the same statement or neither row changes.
|
|
68
|
+
*/
|
|
69
|
+
export declare function removeItem(input: {
|
|
70
|
+
id: string;
|
|
71
|
+
} & RemoveItemInput, auth: LTApiAuth): Promise<LTApiResult>;
|
|
72
|
+
export declare function removeItemBySignalKey(input: {
|
|
73
|
+
signalKey: string;
|
|
74
|
+
} & RemoveItemInput, auth: LTApiAuth): Promise<LTApiResult>;
|
|
75
|
+
export declare function removeItemByMetadata(input: {
|
|
76
|
+
key: string;
|
|
77
|
+
value: string;
|
|
78
|
+
restrictRoles?: string[];
|
|
79
|
+
} & RemoveItemInput, auth: LTApiAuth): Promise<LTApiResult>;
|
|
80
|
+
export interface EscalationItemsView {
|
|
81
|
+
escalationId: string;
|
|
82
|
+
kind: 'accumulate' | 'batch';
|
|
83
|
+
status: LTEscalationRecord['status'];
|
|
84
|
+
count: number;
|
|
85
|
+
/** The count trigger (accumulate) or the declared size (batch); null when unbounded. */
|
|
86
|
+
max: number | null;
|
|
87
|
+
items: AccumulatedItem[];
|
|
88
|
+
/** Batch only: declared keys still awaiting submission. */
|
|
89
|
+
pending?: string[];
|
|
90
|
+
}
|
|
91
|
+
/** The normalized ordered item list of an accumulator or batch row. */
|
|
92
|
+
export declare function itemsView(escalation: LTEscalationRecord): EscalationItemsView | null;
|
|
93
|
+
/** GET the held items of an accumulator or batch row, in arrival order. Read access; 404 non-disclosure. */
|
|
94
|
+
export declare function getEscalationItems(input: {
|
|
95
|
+
id: string;
|
|
96
|
+
}, auth: LTApiAuth): Promise<LTApiResult<EscalationItemsView>>;
|
|
97
|
+
/**
|
|
98
|
+
* GET the held items of an accumulator or batch row by its `signal_key`, the
|
|
99
|
+
* deterministic home signal id a workflow knows without a row id. Read scope
|
|
100
|
+
* gates it; anything the caller may not see answers 404.
|
|
101
|
+
*/
|
|
102
|
+
export declare function getEscalationItemsBySignalKey(input: {
|
|
103
|
+
signalKey: string;
|
|
104
|
+
}, auth: LTApiAuth): Promise<LTApiResult<EscalationItemsView>>;
|
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.accumulateItem = accumulateItem;
|
|
37
|
+
exports.accumulateItemBySignalKey = accumulateItemBySignalKey;
|
|
38
|
+
exports.accumulateItemByMetadata = accumulateItemByMetadata;
|
|
39
|
+
exports.removeItem = removeItem;
|
|
40
|
+
exports.removeItemBySignalKey = removeItemBySignalKey;
|
|
41
|
+
exports.removeItemByMetadata = removeItemByMetadata;
|
|
42
|
+
exports.itemsView = itemsView;
|
|
43
|
+
exports.getEscalationItems = getEscalationItems;
|
|
44
|
+
exports.getEscalationItemsBySignalKey = getEscalationItemsBySignalKey;
|
|
45
|
+
const escalationService = __importStar(require("../../services/escalation"));
|
|
46
|
+
const resolver_validation_1 = require("../../services/escalation/resolver-validation");
|
|
47
|
+
const enforcement_cache_1 = require("../../services/role/enforcement-cache");
|
|
48
|
+
const escalation_1 = require("../../types/escalation");
|
|
49
|
+
const helpers_1 = require("./helpers");
|
|
50
|
+
const resolve_1 = require("./resolve");
|
|
51
|
+
const metadata_1 = require("./metadata");
|
|
52
|
+
function parseEnvelope(escalation) {
|
|
53
|
+
try {
|
|
54
|
+
const parsed = JSON.parse(escalation.envelope || '{}');
|
|
55
|
+
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return {};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function isAccumulator(escalation) {
|
|
62
|
+
const items = parseEnvelope(escalation)[escalation_1.ESCALATION_ACCUMULATE_KEYS.ITEMS];
|
|
63
|
+
return !!items && typeof items === 'object' && !Array.isArray(items);
|
|
64
|
+
}
|
|
65
|
+
function isBatch(escalation) {
|
|
66
|
+
return Array.isArray(escalation.metadata?.[escalation_1.ESCALATION_BATCH_KEYS.PENDING]);
|
|
67
|
+
}
|
|
68
|
+
function reciprocalSelectorCount(r) {
|
|
69
|
+
return (r.id ? 1 : 0) + (r.signalKey ? 1 : 0) + (r.key !== undefined ? 1 : 0);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Locates and RBAC-gates the reciprocal row before the statement. The row
|
|
73
|
+
* must be visible to the caller (404 non-disclosure otherwise) and within
|
|
74
|
+
* their write scope (403 by id; 404 for the ingress selectors). Returns the
|
|
75
|
+
* selector the service forwards, resolved to the row's id.
|
|
76
|
+
*/
|
|
77
|
+
async function gateReciprocal(input, auth) {
|
|
78
|
+
if (!input)
|
|
79
|
+
return {};
|
|
80
|
+
if (reciprocalSelectorCount(input) !== 1) {
|
|
81
|
+
return { error: { status: 400, error: 'reciprocal requires exactly one of id, signalKey, or key/value' } };
|
|
82
|
+
}
|
|
83
|
+
let row = null;
|
|
84
|
+
if (input.id) {
|
|
85
|
+
row = await escalationService.getEscalation(input.id);
|
|
86
|
+
}
|
|
87
|
+
else if (input.signalKey) {
|
|
88
|
+
row = await escalationService.getEscalationBySignalKey(input.signalKey);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
const writeScope = await (0, helpers_1.getEscalationWriteScope)(auth.userId);
|
|
92
|
+
const found = await escalationService.findByMetadata(input.key, String(input.value), 'pending', 1, 0, writeScope.global ? undefined : { allRoles: writeScope.allRoles, meUserId: auth.userId });
|
|
93
|
+
row = found.escalations[0] ?? null;
|
|
94
|
+
}
|
|
95
|
+
if (!row)
|
|
96
|
+
return { error: { status: 404, error: 'Reciprocal escalation not found' } };
|
|
97
|
+
if (input.id) {
|
|
98
|
+
if (await (0, helpers_1.assertReadAccess)(auth.userId, row)) {
|
|
99
|
+
return { error: { status: 404, error: 'Reciprocal escalation not found' } };
|
|
100
|
+
}
|
|
101
|
+
const denied = await (0, helpers_1.assertWriteAccess)(auth.userId, row);
|
|
102
|
+
if (denied)
|
|
103
|
+
return { error: { ...denied, error: `Reciprocal: ${denied.error}` } };
|
|
104
|
+
}
|
|
105
|
+
else if (await (0, helpers_1.assertWriteAccess)(auth.userId, row)) {
|
|
106
|
+
return { error: { status: 404, error: 'Reciprocal escalation not found' } };
|
|
107
|
+
}
|
|
108
|
+
return { reciprocal: { id: row.id, payload: input.payload } };
|
|
109
|
+
}
|
|
110
|
+
/** Validates the item payload against the container's versioned role form. */
|
|
111
|
+
async function gatePayload(escalation, payload, userId) {
|
|
112
|
+
if (payload === undefined)
|
|
113
|
+
return {};
|
|
114
|
+
if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
|
|
115
|
+
return { error: { status: 400, error: 'payload must be an object' } };
|
|
116
|
+
}
|
|
117
|
+
const violation = await (0, resolver_validation_1.checkResolverPayload)(escalation, payload, undefined, userId);
|
|
118
|
+
if (violation)
|
|
119
|
+
return { error: (0, resolve_1.validationFailure)(violation) };
|
|
120
|
+
return { payload: await (0, resolve_1.redactPasswords)(payload, escalation.metadata?.form_schema) };
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Add ONE item to an accumulator escalation (a `conditional` wait declared
|
|
124
|
+
* with `accumulate: {...}`). Interim adds are cheap atomic row appends: the
|
|
125
|
+
* row stays pending and `count`/`remaining` report progress. An add that
|
|
126
|
+
* reaches `max` completes the escalation: the row resolves and the waiting
|
|
127
|
+
* workflow wakes with the ordered collection, in the same statement.
|
|
128
|
+
*
|
|
129
|
+
* With `reciprocal`, a second accumulator row is written in that same
|
|
130
|
+
* statement or not at all: it holds this container's id as its item key and
|
|
131
|
+
* each entry points at the other row. The reciprocal is RBAC-gated here
|
|
132
|
+
* before the statement runs.
|
|
133
|
+
*
|
|
134
|
+
* Claim semantics match batch: claim-agnostic by default (a container
|
|
135
|
+
* collects contributions from many hands); `assertClaim: true` requires the
|
|
136
|
+
* caller's own live claim, asserted atomically inside the SDK statement.
|
|
137
|
+
*/
|
|
138
|
+
async function accumulateItem(input, auth) {
|
|
139
|
+
try {
|
|
140
|
+
const { id, itemKey, metadata } = input;
|
|
141
|
+
if (!itemKey)
|
|
142
|
+
return { status: 400, error: 'itemKey is required' };
|
|
143
|
+
const escalation = await escalationService.getEscalation(id);
|
|
144
|
+
if (!escalation)
|
|
145
|
+
return { status: 404, error: 'Escalation not found' };
|
|
146
|
+
if (escalation.status === 'cancelled')
|
|
147
|
+
return { status: 409, error: 'Escalation is cancelled' };
|
|
148
|
+
if (escalation.status !== 'pending')
|
|
149
|
+
return { status: 409, error: 'Escalation not available for accumulation' };
|
|
150
|
+
if (!isAccumulator(escalation))
|
|
151
|
+
return { status: 400, error: 'Escalation is not an accumulator' };
|
|
152
|
+
if (await (0, helpers_1.assertReadAccess)(auth.userId, escalation)) {
|
|
153
|
+
return { status: 404, error: 'Escalation not found' };
|
|
154
|
+
}
|
|
155
|
+
const denied = await (0, helpers_1.assertWriteAccess)(auth.userId, escalation);
|
|
156
|
+
if (denied)
|
|
157
|
+
return denied;
|
|
158
|
+
const reciprocal = await gateReciprocal(input.reciprocal, auth);
|
|
159
|
+
if ('error' in reciprocal)
|
|
160
|
+
return reciprocal.error;
|
|
161
|
+
const payload = await gatePayload(escalation, input.payload, auth.userId);
|
|
162
|
+
if ('error' in payload)
|
|
163
|
+
return payload.error;
|
|
164
|
+
const result = await escalationService.accumulateItem(escalation.id, {
|
|
165
|
+
itemKey,
|
|
166
|
+
payload: payload.payload,
|
|
167
|
+
metadata: { ...metadata, resolved_by: auth.userId },
|
|
168
|
+
actor: auth.userId,
|
|
169
|
+
assertClaim: input.assertClaim ? auth.userId : undefined,
|
|
170
|
+
resolvedBy: await (0, resolve_1.resolverIdentity)(auth),
|
|
171
|
+
reciprocal: reciprocal.reciprocal,
|
|
172
|
+
});
|
|
173
|
+
return accumulateOutcomeResult(result, itemKey, escalation.workflow_id);
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
return { status: 500, error: err.message };
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Add selecting the container by its `signal_key`, the deterministic home
|
|
181
|
+
* signal id the waiting workflow parked on. Mirrors resolve-by-signal-key:
|
|
182
|
+
* claim-agnostic, write-scope gated with 404 non-disclosure.
|
|
183
|
+
*/
|
|
184
|
+
async function accumulateItemBySignalKey(input, auth) {
|
|
185
|
+
try {
|
|
186
|
+
const { signalKey, itemKey, metadata } = input;
|
|
187
|
+
if (!signalKey)
|
|
188
|
+
return { status: 400, error: 'signalKey is required' };
|
|
189
|
+
if (!itemKey)
|
|
190
|
+
return { status: 400, error: 'itemKey is required' };
|
|
191
|
+
const escalation = await escalationService.getEscalationBySignalKey(signalKey);
|
|
192
|
+
if (!escalation)
|
|
193
|
+
return { status: 404, error: 'Escalation not found' };
|
|
194
|
+
if (escalation.status !== 'pending')
|
|
195
|
+
return { status: 409, error: 'Escalation not available for accumulation' };
|
|
196
|
+
if (!isAccumulator(escalation))
|
|
197
|
+
return { status: 400, error: 'Escalation is not an accumulator' };
|
|
198
|
+
const denied = await (0, helpers_1.assertWriteAccess)(auth.userId, escalation);
|
|
199
|
+
if (denied)
|
|
200
|
+
return { status: 404, error: 'Escalation not found' };
|
|
201
|
+
const reciprocal = await gateReciprocal(input.reciprocal, auth);
|
|
202
|
+
if ('error' in reciprocal)
|
|
203
|
+
return reciprocal.error;
|
|
204
|
+
const payload = await gatePayload(escalation, input.payload, auth.userId);
|
|
205
|
+
if ('error' in payload)
|
|
206
|
+
return payload.error;
|
|
207
|
+
const result = await escalationService.accumulateItemBySignalKey(signalKey, {
|
|
208
|
+
itemKey,
|
|
209
|
+
payload: payload.payload,
|
|
210
|
+
metadata: { ...metadata, resolved_by: auth.userId },
|
|
211
|
+
actor: auth.userId,
|
|
212
|
+
resolvedBy: await (0, resolve_1.resolverIdentity)(auth),
|
|
213
|
+
reciprocal: reciprocal.reciprocal,
|
|
214
|
+
});
|
|
215
|
+
return accumulateOutcomeResult(result, itemKey, escalation.workflow_id);
|
|
216
|
+
}
|
|
217
|
+
catch (err) {
|
|
218
|
+
return { status: 500, error: err.message };
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Add selecting the container by metadata facet, the faceted sibling of
|
|
223
|
+
* {@link accumulateItem}. RBAC folds into the SDK's atomic facet selection
|
|
224
|
+
* as a flat role filter. Schema enforcement is two-phase when enforcing
|
|
225
|
+
* roles exist and a payload is present: the row is picked first, validated
|
|
226
|
+
* against ITS schema, then written by asserted id; a row that went terminal
|
|
227
|
+
* between phases surfaces as a 409.
|
|
228
|
+
*/
|
|
229
|
+
async function accumulateItemByMetadata(input, auth) {
|
|
230
|
+
try {
|
|
231
|
+
const { key, value, itemKey, metadata } = input;
|
|
232
|
+
if (!key || !value)
|
|
233
|
+
return { status: 400, error: 'key and value are required' };
|
|
234
|
+
if (!itemKey)
|
|
235
|
+
return { status: 400, error: 'itemKey is required' };
|
|
236
|
+
const writeScope = await (0, helpers_1.getEscalationWriteScope)(auth.userId);
|
|
237
|
+
const allowedRoles = (0, metadata_1.restrictScopeRoles)(writeScope.allRoles, writeScope.global, input.restrictRoles);
|
|
238
|
+
const reciprocal = await gateReciprocal(input.reciprocal, auth);
|
|
239
|
+
if ('error' in reciprocal)
|
|
240
|
+
return reciprocal.error;
|
|
241
|
+
const resolvedBy = await (0, resolve_1.resolverIdentity)(auth);
|
|
242
|
+
const outcome = { ...metadata, resolved_by: auth.userId };
|
|
243
|
+
const enforcing = await (0, enforcement_cache_1.getEnforcingRoles)();
|
|
244
|
+
if (enforcing.size === 0 || input.payload === undefined) {
|
|
245
|
+
const result = await escalationService.accumulateItemByMetadata(key, value, {
|
|
246
|
+
itemKey,
|
|
247
|
+
payload: input.payload,
|
|
248
|
+
metadata: outcome,
|
|
249
|
+
actor: auth.userId,
|
|
250
|
+
resolvedBy,
|
|
251
|
+
roles: allowedRoles ?? undefined,
|
|
252
|
+
reciprocal: reciprocal.reciprocal,
|
|
253
|
+
});
|
|
254
|
+
return accumulateOutcomeResult(result, itemKey, result.escalation?.workflow_id ?? null);
|
|
255
|
+
}
|
|
256
|
+
const found = await escalationService.findByMetadata(key, value, 'pending', 1, 0, allowedRoles === null ? undefined : { allRoles: allowedRoles, meUserId: auth.userId });
|
|
257
|
+
const row = found.escalations[0];
|
|
258
|
+
if (!row)
|
|
259
|
+
return { status: 404, error: 'No pending escalation found for this metadata' };
|
|
260
|
+
if (!isAccumulator(row))
|
|
261
|
+
return { status: 400, error: 'Escalation is not an accumulator' };
|
|
262
|
+
const payload = await gatePayload(row, input.payload, auth.userId);
|
|
263
|
+
if ('error' in payload)
|
|
264
|
+
return payload.error;
|
|
265
|
+
const result = await escalationService.accumulateItem(row.id, {
|
|
266
|
+
itemKey,
|
|
267
|
+
payload: payload.payload,
|
|
268
|
+
metadata: outcome,
|
|
269
|
+
actor: auth.userId,
|
|
270
|
+
resolvedBy,
|
|
271
|
+
reciprocal: reciprocal.reciprocal,
|
|
272
|
+
});
|
|
273
|
+
if (result.outcome === 'not-found') {
|
|
274
|
+
return { status: 409, error: 'A concurrent change is already in progress for this escalation' };
|
|
275
|
+
}
|
|
276
|
+
return accumulateOutcomeResult(result, itemKey, row.workflow_id);
|
|
277
|
+
}
|
|
278
|
+
catch (err) {
|
|
279
|
+
return { status: 500, error: err.message };
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Remove ONE held item from a pending accumulator escalation, one guarded
|
|
284
|
+
* statement, no wake. With `reciprocal`, the container's id leaves that row
|
|
285
|
+
* in the same statement or neither row changes.
|
|
286
|
+
*/
|
|
287
|
+
async function removeItem(input, auth) {
|
|
288
|
+
try {
|
|
289
|
+
const { id, itemKey } = input;
|
|
290
|
+
if (!itemKey)
|
|
291
|
+
return { status: 400, error: 'itemKey is required' };
|
|
292
|
+
const escalation = await escalationService.getEscalation(id);
|
|
293
|
+
if (!escalation)
|
|
294
|
+
return { status: 404, error: 'Escalation not found' };
|
|
295
|
+
if (escalation.status !== 'pending')
|
|
296
|
+
return { status: 409, error: 'Escalation not available for accumulation' };
|
|
297
|
+
if (!isAccumulator(escalation))
|
|
298
|
+
return { status: 400, error: 'Escalation is not an accumulator' };
|
|
299
|
+
if (await (0, helpers_1.assertReadAccess)(auth.userId, escalation)) {
|
|
300
|
+
return { status: 404, error: 'Escalation not found' };
|
|
301
|
+
}
|
|
302
|
+
const denied = await (0, helpers_1.assertWriteAccess)(auth.userId, escalation);
|
|
303
|
+
if (denied)
|
|
304
|
+
return denied;
|
|
305
|
+
const reciprocal = await gateReciprocal(input.reciprocal, auth);
|
|
306
|
+
if ('error' in reciprocal)
|
|
307
|
+
return reciprocal.error;
|
|
308
|
+
const result = await escalationService.removeAccumulatedItem(escalation.id, {
|
|
309
|
+
itemKey, actor: auth.userId, reciprocal: reciprocal.reciprocal,
|
|
310
|
+
});
|
|
311
|
+
return removeOutcomeResult(result, itemKey);
|
|
312
|
+
}
|
|
313
|
+
catch (err) {
|
|
314
|
+
return { status: 500, error: err.message };
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
async function removeItemBySignalKey(input, auth) {
|
|
318
|
+
try {
|
|
319
|
+
const { signalKey, itemKey } = input;
|
|
320
|
+
if (!signalKey)
|
|
321
|
+
return { status: 400, error: 'signalKey is required' };
|
|
322
|
+
if (!itemKey)
|
|
323
|
+
return { status: 400, error: 'itemKey is required' };
|
|
324
|
+
const escalation = await escalationService.getEscalationBySignalKey(signalKey);
|
|
325
|
+
if (!escalation)
|
|
326
|
+
return { status: 404, error: 'Escalation not found' };
|
|
327
|
+
if (escalation.status !== 'pending')
|
|
328
|
+
return { status: 409, error: 'Escalation not available for accumulation' };
|
|
329
|
+
if (!isAccumulator(escalation))
|
|
330
|
+
return { status: 400, error: 'Escalation is not an accumulator' };
|
|
331
|
+
if (await (0, helpers_1.assertWriteAccess)(auth.userId, escalation)) {
|
|
332
|
+
return { status: 404, error: 'Escalation not found' };
|
|
333
|
+
}
|
|
334
|
+
const reciprocal = await gateReciprocal(input.reciprocal, auth);
|
|
335
|
+
if ('error' in reciprocal)
|
|
336
|
+
return reciprocal.error;
|
|
337
|
+
const result = await escalationService.removeAccumulatedItemBySignalKey(signalKey, {
|
|
338
|
+
itemKey, actor: auth.userId, reciprocal: reciprocal.reciprocal,
|
|
339
|
+
});
|
|
340
|
+
return removeOutcomeResult(result, itemKey);
|
|
341
|
+
}
|
|
342
|
+
catch (err) {
|
|
343
|
+
return { status: 500, error: err.message };
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
async function removeItemByMetadata(input, auth) {
|
|
347
|
+
try {
|
|
348
|
+
const { key, value, itemKey } = input;
|
|
349
|
+
if (!key || !value)
|
|
350
|
+
return { status: 400, error: 'key and value are required' };
|
|
351
|
+
if (!itemKey)
|
|
352
|
+
return { status: 400, error: 'itemKey is required' };
|
|
353
|
+
const writeScope = await (0, helpers_1.getEscalationWriteScope)(auth.userId);
|
|
354
|
+
const allowedRoles = (0, metadata_1.restrictScopeRoles)(writeScope.allRoles, writeScope.global, input.restrictRoles);
|
|
355
|
+
const reciprocal = await gateReciprocal(input.reciprocal, auth);
|
|
356
|
+
if ('error' in reciprocal)
|
|
357
|
+
return reciprocal.error;
|
|
358
|
+
const result = await escalationService.removeAccumulatedItemByMetadata(key, value, {
|
|
359
|
+
itemKey, actor: auth.userId, roles: allowedRoles ?? undefined, reciprocal: reciprocal.reciprocal,
|
|
360
|
+
});
|
|
361
|
+
return removeOutcomeResult(result, itemKey);
|
|
362
|
+
}
|
|
363
|
+
catch (err) {
|
|
364
|
+
return { status: 500, error: err.message };
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
/** The normalized ordered item list of an accumulator or batch row. */
|
|
368
|
+
function itemsView(escalation) {
|
|
369
|
+
const envelope = parseEnvelope(escalation);
|
|
370
|
+
const metadata = (escalation.metadata ?? {});
|
|
371
|
+
if (isAccumulator(escalation)) {
|
|
372
|
+
const store = envelope[escalation_1.ESCALATION_ACCUMULATE_KEYS.ITEMS];
|
|
373
|
+
const items = Object.entries(store)
|
|
374
|
+
.map(([itemKey, entry]) => ({ itemKey, ...entry }))
|
|
375
|
+
.sort((a, b) => a.at.localeCompare(b.at) || a.itemKey.localeCompare(b.itemKey));
|
|
376
|
+
const max = metadata[escalation_1.ESCALATION_ACCUMULATE_KEYS.MAX];
|
|
377
|
+
return {
|
|
378
|
+
escalationId: escalation.id,
|
|
379
|
+
kind: 'accumulate',
|
|
380
|
+
status: escalation.status,
|
|
381
|
+
count: items.length,
|
|
382
|
+
max: typeof max === 'number' ? max : null,
|
|
383
|
+
items,
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
if (isBatch(escalation)) {
|
|
387
|
+
const store = (envelope[escalation_1.ESCALATION_BATCH_KEYS.ITEMS] ?? {});
|
|
388
|
+
const filledAt = (envelope[escalation_1.ESCALATION_BATCH_KEYS.FILLED_AT] ?? {});
|
|
389
|
+
const keys = (metadata[escalation_1.ESCALATION_BATCH_KEYS.KEYS] ?? []);
|
|
390
|
+
const items = Object.entries(store)
|
|
391
|
+
.map(([itemKey, payload]) => ({ itemKey, payload: payload, at: filledAt[itemKey] ?? '' }))
|
|
392
|
+
.sort((a, b) => a.at.localeCompare(b.at) || a.itemKey.localeCompare(b.itemKey));
|
|
393
|
+
return {
|
|
394
|
+
escalationId: escalation.id,
|
|
395
|
+
kind: 'batch',
|
|
396
|
+
status: escalation.status,
|
|
397
|
+
count: items.length,
|
|
398
|
+
max: keys.length,
|
|
399
|
+
items,
|
|
400
|
+
pending: metadata[escalation_1.ESCALATION_BATCH_KEYS.PENDING] ?? [],
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
/** GET the held items of an accumulator or batch row, in arrival order. Read access; 404 non-disclosure. */
|
|
406
|
+
async function getEscalationItems(input, auth) {
|
|
407
|
+
try {
|
|
408
|
+
const escalation = await escalationService.getEscalation(input.id);
|
|
409
|
+
if (!escalation)
|
|
410
|
+
return { status: 404, error: 'Escalation not found' };
|
|
411
|
+
if (await (0, helpers_1.assertReadAccess)(auth.userId, escalation)) {
|
|
412
|
+
return { status: 404, error: 'Escalation not found' };
|
|
413
|
+
}
|
|
414
|
+
const view = itemsView(escalation);
|
|
415
|
+
if (!view)
|
|
416
|
+
return { status: 400, error: 'Escalation holds no items' };
|
|
417
|
+
return { status: 200, data: view };
|
|
418
|
+
}
|
|
419
|
+
catch (err) {
|
|
420
|
+
return { status: 500, error: err.message };
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* GET the held items of an accumulator or batch row by its `signal_key`, the
|
|
425
|
+
* deterministic home signal id a workflow knows without a row id. Read scope
|
|
426
|
+
* gates it; anything the caller may not see answers 404.
|
|
427
|
+
*/
|
|
428
|
+
async function getEscalationItemsBySignalKey(input, auth) {
|
|
429
|
+
try {
|
|
430
|
+
if (!input.signalKey)
|
|
431
|
+
return { status: 400, error: 'signalKey is required' };
|
|
432
|
+
const escalation = await escalationService.getEscalationBySignalKey(input.signalKey);
|
|
433
|
+
if (!escalation)
|
|
434
|
+
return { status: 404, error: 'Escalation not found' };
|
|
435
|
+
if (await (0, helpers_1.assertReadAccess)(auth.userId, escalation)) {
|
|
436
|
+
return { status: 404, error: 'Escalation not found' };
|
|
437
|
+
}
|
|
438
|
+
const view = itemsView(escalation);
|
|
439
|
+
if (!view)
|
|
440
|
+
return { status: 400, error: 'Escalation holds no items' };
|
|
441
|
+
return { status: 200, data: view };
|
|
442
|
+
}
|
|
443
|
+
catch (err) {
|
|
444
|
+
return { status: 500, error: err.message };
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
function sideData(side) {
|
|
448
|
+
return {
|
|
449
|
+
outcome: side.outcome,
|
|
450
|
+
count: side.count,
|
|
451
|
+
remaining: side.remaining,
|
|
452
|
+
escalationId: side.escalation.id,
|
|
453
|
+
signaled: side.outcome === 'completed' && !!side.escalation.signal_key,
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
/** Maps the SDK accumulate outcome vocabulary onto HTTP results. */
|
|
457
|
+
function accumulateOutcomeResult(result, itemKey, workflowId) {
|
|
458
|
+
const reciprocal = result.reciprocal ? { reciprocal: sideData(result.reciprocal) } : {};
|
|
459
|
+
switch (result.outcome) {
|
|
460
|
+
case 'completed':
|
|
461
|
+
return {
|
|
462
|
+
status: 200,
|
|
463
|
+
data: {
|
|
464
|
+
outcome: 'completed',
|
|
465
|
+
count: result.count,
|
|
466
|
+
remaining: 0,
|
|
467
|
+
signaled: !!result.escalation?.signal_key,
|
|
468
|
+
escalationId: result.escalation?.id,
|
|
469
|
+
workflowId,
|
|
470
|
+
...reciprocal,
|
|
471
|
+
},
|
|
472
|
+
};
|
|
473
|
+
case 'accepted':
|
|
474
|
+
return {
|
|
475
|
+
status: 200,
|
|
476
|
+
data: {
|
|
477
|
+
outcome: 'accepted',
|
|
478
|
+
count: result.count,
|
|
479
|
+
remaining: result.remaining,
|
|
480
|
+
escalationId: result.escalation?.id,
|
|
481
|
+
...reciprocal,
|
|
482
|
+
},
|
|
483
|
+
};
|
|
484
|
+
case 'duplicate-item':
|
|
485
|
+
return { status: 409, error: 'Item already held', data: { error: 'Item already held', itemKey } };
|
|
486
|
+
case 'full':
|
|
487
|
+
return { status: 409, error: 'Accumulator is full', data: { error: 'Accumulator is full', itemKey } };
|
|
488
|
+
case 'claimed-by-other':
|
|
489
|
+
return { status: 409, error: 'Escalation is claimed by another user' };
|
|
490
|
+
case 'claim-expired':
|
|
491
|
+
return { status: 409, error: 'Your claim has expired; re-claim this escalation to add to it' };
|
|
492
|
+
case 'not-found':
|
|
493
|
+
return { status: 404, error: 'Escalation not found' };
|
|
494
|
+
case 'not-accumulator':
|
|
495
|
+
return { status: 400, error: 'Escalation is not an accumulator' };
|
|
496
|
+
case 'reciprocal-not-found':
|
|
497
|
+
return { status: 404, error: 'Reciprocal escalation not found' };
|
|
498
|
+
case 'reciprocal-not-accumulator':
|
|
499
|
+
return { status: 400, error: 'Reciprocal escalation is not an accumulator' };
|
|
500
|
+
case 'reciprocal-duplicate':
|
|
501
|
+
return { status: 409, error: 'Reciprocal escalation already holds this container', data: { error: 'Reciprocal escalation already holds this container', outcome: result.outcome } };
|
|
502
|
+
case 'reciprocal-full':
|
|
503
|
+
return { status: 409, error: 'Reciprocal accumulator is full', data: { error: 'Reciprocal accumulator is full', outcome: result.outcome } };
|
|
504
|
+
case 'reciprocal-terminal':
|
|
505
|
+
return { status: 409, error: 'Reciprocal escalation is no longer pending', data: { error: 'Reciprocal escalation is no longer pending', outcome: result.outcome } };
|
|
506
|
+
default:
|
|
507
|
+
return { status: 409, error: 'Escalation not available for accumulation' };
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
function removeOutcomeResult(result, itemKey) {
|
|
511
|
+
switch (result.outcome) {
|
|
512
|
+
case 'removed':
|
|
513
|
+
return {
|
|
514
|
+
status: 200,
|
|
515
|
+
data: {
|
|
516
|
+
outcome: 'removed',
|
|
517
|
+
count: result.count,
|
|
518
|
+
escalationId: result.escalation?.id,
|
|
519
|
+
...(result.reciprocal
|
|
520
|
+
? { reciprocal: { count: result.reciprocal.count, escalationId: result.reciprocal.escalation.id } }
|
|
521
|
+
: {}),
|
|
522
|
+
},
|
|
523
|
+
};
|
|
524
|
+
case 'item-absent':
|
|
525
|
+
return { status: 404, error: 'Item not held by this escalation', data: { error: 'Item not held by this escalation', itemKey } };
|
|
526
|
+
case 'not-found':
|
|
527
|
+
return { status: 404, error: 'Escalation not found' };
|
|
528
|
+
case 'not-accumulator':
|
|
529
|
+
return { status: 400, error: 'Escalation is not an accumulator' };
|
|
530
|
+
case 'reciprocal-not-found':
|
|
531
|
+
return { status: 404, error: 'Reciprocal escalation not found' };
|
|
532
|
+
case 'reciprocal-not-accumulator':
|
|
533
|
+
return { status: 400, error: 'Reciprocal escalation is not an accumulator' };
|
|
534
|
+
case 'reciprocal-absent':
|
|
535
|
+
return { status: 404, error: 'Reciprocal escalation does not hold this container', data: { error: 'Reciprocal escalation does not hold this container', outcome: result.outcome } };
|
|
536
|
+
case 'reciprocal-terminal':
|
|
537
|
+
return { status: 409, error: 'Reciprocal escalation is no longer pending', data: { error: 'Reciprocal escalation is no longer pending', outcome: result.outcome } };
|
|
538
|
+
default:
|
|
539
|
+
return { status: 409, error: 'Escalation not available for accumulation' };
|
|
540
|
+
}
|
|
541
|
+
}
|
|
@@ -6,6 +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, getEscalationItemsBySignalKey, itemsView, } from './accumulate';
|
|
9
10
|
export { findByMetadata, claimByMetadata, resolveByMetadata } from './metadata';
|
|
10
11
|
export { cancelSingleEscalation, bulkCancel } from './cancel';
|
|
11
12
|
export { searchByFacets, claimGroups, claimByFacets } from './facets';
|