@hotmeshio/long-tail 0.5.12 → 0.6.0
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 +1 -0
- package/build/api/escalations/bulk.js +9 -1
- package/build/api/escalations/cancel.js +5 -7
- package/build/api/escalations/claim.js +18 -15
- package/build/api/escalations/create.d.ts +6 -0
- package/build/api/escalations/create.js +11 -8
- package/build/api/escalations/facets.d.ts +18 -0
- package/build/api/escalations/facets.js +115 -0
- package/build/api/escalations/helpers.d.ts +70 -1
- package/build/api/escalations/helpers.js +101 -7
- package/build/api/escalations/index.d.ts +3 -2
- package/build/api/escalations/index.js +7 -1
- package/build/api/escalations/list.d.ts +21 -2
- package/build/api/escalations/list.js +109 -10
- package/build/api/escalations/metadata.js +22 -27
- package/build/api/escalations/resolve.d.ts +19 -1
- package/build/api/escalations/resolve.js +111 -26
- package/build/api/escalations/single.js +8 -8
- package/build/api/users.d.ts +6 -0
- package/build/api/users.js +29 -1
- package/build/bin/ltc.js +40 -0
- package/build/lib/cli/commands/escalations.d.ts +36 -0
- package/build/lib/cli/commands/escalations.js +98 -0
- package/build/lib/db/schemas/001_schema.sql +10 -5
- package/build/lib/db/schemas/012_lt_tasks_workflow_id_unique.sql +20 -0
- package/build/lib/db/schemas/013_role_scope.sql +37 -0
- package/build/modules/version.d.ts +10 -5
- package/build/modules/version.js +27 -11
- package/build/routes/escalations/facets.d.ts +7 -0
- package/build/routes/escalations/facets.js +81 -0
- package/build/routes/escalations/index.js +3 -0
- package/build/routes/escalations/list.js +46 -0
- package/build/routes/escalations/resolve.js +22 -4
- package/build/routes/users.js +9 -5
- package/build/sdk/index.d.ts +33 -2
- package/build/sdk/index.js +7 -0
- package/build/services/escalation/crud.d.ts +56 -6
- package/build/services/escalation/crud.js +102 -31
- package/build/services/escalation/facet-sql.d.ts +18 -0
- package/build/services/escalation/facet-sql.js +118 -0
- package/build/services/escalation/facets.d.ts +45 -0
- package/build/services/escalation/facets.js +218 -0
- package/build/services/escalation/index.d.ts +1 -0
- package/build/services/escalation/index.js +8 -1
- package/build/services/escalation/queries.d.ts +45 -0
- package/build/services/escalation/queries.js +107 -6
- package/build/services/escalation/sql.d.ts +10 -4
- package/build/services/escalation/sql.js +36 -8
- package/build/services/interceptor/activities/escalation.d.ts +2 -0
- package/build/services/interceptor/activities/escalation.js +1 -1
- package/build/services/interceptor/lifecycle.js +4 -0
- package/build/services/mcp/server-tools.js +10 -4
- package/build/services/orchestrator/condition.js +6 -2
- package/build/services/role/index.js +2 -3
- package/build/services/role/sql.d.ts +8 -0
- package/build/services/role/sql.js +17 -1
- package/build/services/task/crud.js +22 -14
- package/build/services/task/process.js +3 -21
- package/build/services/task/sql.d.ts +24 -1
- package/build/services/task/sql.js +65 -1
- package/build/services/user/crud.d.ts +1 -0
- package/build/services/user/crud.js +29 -11
- package/build/services/user/index.d.ts +2 -1
- package/build/services/user/index.js +12 -1
- package/build/services/user/rbac.d.ts +18 -0
- package/build/services/user/rbac.js +27 -0
- package/build/services/user/roles.d.ts +7 -2
- package/build/services/user/roles.js +21 -5
- package/build/services/user/scope.d.ts +22 -0
- package/build/services/user/scope.js +50 -0
- package/build/services/user/seed-admin.js +34 -17
- package/build/services/user/sql.d.ts +18 -7
- package/build/services/user/sql.js +38 -13
- package/build/services/user/sso-provision.js +41 -24
- package/build/services/user/types.d.ts +9 -5
- package/build/system/mcp-servers/admin/escalations.js +65 -0
- package/build/system/mcp-servers/admin/schemas.d.ts +325 -0
- package/build/system/mcp-servers/admin/schemas.js +63 -2
- package/build/system/mcp-servers/admin/users.js +28 -2
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/envelope.d.ts +7 -0
- package/build/types/facets.d.ts +60 -0
- package/build/types/facets.js +10 -0
- package/build/types/index.d.ts +2 -1
- package/build/types/user.d.ts +11 -0
- package/dashboard/dist/assets/AdminDashboard-2CZ8py9X.js +2 -0
- package/dashboard/dist/assets/{AdminDashboard-LTiYLuzq.js.map → AdminDashboard-2CZ8py9X.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-nlOudfpZ.js → AgentConfigPage-D68sodgo.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-nlOudfpZ.js.map → AgentConfigPage-D68sodgo.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-BSUnDvGp.js → AgentDetailPage-BmhuWbKi.js} +2 -2
- package/dashboard/dist/assets/{AgentDetailPage-BSUnDvGp.js.map → AgentDetailPage-BmhuWbKi.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-DpS0cCYe.js → AgentsPage-C4SKQVeU.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-DpS0cCYe.js.map → AgentsPage-C4SKQVeU.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-9RBEYwkt.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-9RBEYwkt.js.map +1 -0
- package/dashboard/dist/assets/{BotPicker-BhKmq7M7.js → BotPicker-D-FvXJOM.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-BhKmq7M7.js.map → BotPicker-D-FvXJOM.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-DLIleX2L.js → CapabilitiesPage-ByDf6WJr.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-DLIleX2L.js.map → CapabilitiesPage-ByDf6WJr.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-D7SVwNVk.js → CollapsibleSection-BjGNYEvh.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-D7SVwNVk.js.map → CollapsibleSection-BjGNYEvh.js.map} +1 -1
- package/dashboard/dist/assets/CopyableId-blg-gZvT.js +2 -0
- package/dashboard/dist/assets/CopyableId-blg-gZvT.js.map +1 -0
- package/dashboard/dist/assets/{CredentialsPage-fat5Z2U9.js → CredentialsPage-DvCA-wQN.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-fat5Z2U9.js.map → CredentialsPage-DvCA-wQN.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-OOP4P2mJ.js → CronLabel-DBMurd_c.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-OOP4P2mJ.js.map → CronLabel-DBMurd_c.js.map} +1 -1
- package/dashboard/dist/assets/{CustomDurationPicker-COacSAXO.js → CustomDurationPicker-DHflFoEa.js} +2 -2
- package/dashboard/dist/assets/{CustomDurationPicker-COacSAXO.js.map → CustomDurationPicker-DHflFoEa.js.map} +1 -1
- package/dashboard/dist/assets/{DropZone-Bfw2YLVS.js → DropZone-CUtdp99Z.js} +2 -2
- package/dashboard/dist/assets/{DropZone-Bfw2YLVS.js.map → DropZone-CUtdp99Z.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-CkfCD-m7.js → ElapsedCell-CSjcVOpo.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-CkfCD-m7.js.map → ElapsedCell-CSjcVOpo.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-BmI8jxlh.js → EscalationsOverview-BUqRNJbK.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-BmI8jxlh.js.map → EscalationsOverview-BUqRNJbK.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-CeKfFk3m.js → EventTable-Chz-6XPE.js} +2 -2
- package/dashboard/dist/assets/{EventTable-CeKfFk3m.js.map → EventTable-Chz-6XPE.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-BZBPBCSq.js → GraphInvokePage-BXdgciWg.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-BZBPBCSq.js.map → GraphInvokePage-BXdgciWg.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-dM7U2tl6.js → HomePage-CEMxnk0r.js} +2 -2
- package/dashboard/dist/assets/{HomePage-dM7U2tl6.js.map → HomePage-CEMxnk0r.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-BJaCzAXS.js → ListToolbar-_73JCdbB.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-BJaCzAXS.js.map → ListToolbar-_73JCdbB.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-CvnDG5OB.js → McpOverview-DfdqxhSz.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-CvnDG5OB.js.map → McpOverview-DfdqxhSz.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-DwmSIcIL.js → McpQueryDetailPage-DPAljieY.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-DwmSIcIL.js.map → McpQueryDetailPage-DPAljieY.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-CU6FMEEk.js → McpQueryPage-D5cSziYS.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-CU6FMEEk.js.map → McpQueryPage-D5cSziYS.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-8a6lsehv.js → McpRunDetailPage-DwNb9wZg.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-8a6lsehv.js.map → McpRunDetailPage-DwNb9wZg.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-CPMYWgm_.js → McpRunsPage-O5H6yStl.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-CPMYWgm_.js.map → McpRunsPage-O5H6yStl.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-D6btr6e8.js → NamespacePill-uW-xOedj.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-D6btr6e8.js.map → NamespacePill-uW-xOedj.js.map} +1 -1
- package/dashboard/dist/assets/OperatorDashboard-DYw9Ekv5.js +2 -0
- package/dashboard/dist/assets/{OperatorDashboard-g9o7I925.js.map → OperatorDashboard-DYw9Ekv5.js.map} +1 -1
- package/dashboard/dist/assets/PageHeader-DVOZjBfL.js +2 -0
- package/dashboard/dist/assets/PageHeader-DVOZjBfL.js.map +1 -0
- package/dashboard/dist/assets/{PageHeaderWithStats-DJQCZ0FR.js → PageHeaderWithStats-DtTpDHOd.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-DJQCZ0FR.js.map → PageHeaderWithStats-DtTpDHOd.js.map} +1 -1
- package/dashboard/dist/assets/PriorityBadge-B4ykBH7f.js +2 -0
- package/dashboard/dist/assets/PriorityBadge-B4ykBH7f.js.map +1 -0
- package/dashboard/dist/assets/{ProcessDetailPage-ByyWCs2A.js → ProcessDetailPage-B0Dokcx9.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-ByyWCs2A.js.map → ProcessDetailPage-B0Dokcx9.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-BTsXds4l.js → ProcessesListPage-Cc87WIjL.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-BTsXds4l.js.map → ProcessesListPage-Cc87WIjL.js.map} +1 -1
- package/dashboard/dist/assets/RolePill-BaW-30TC.js +2 -0
- package/dashboard/dist/assets/RolePill-BaW-30TC.js.map +1 -0
- package/dashboard/dist/assets/{RolesPage-B2Kdf-L9.js → RolesPage-cp6PiF08.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-B2Kdf-L9.js.map → RolesPage-cp6PiF08.js.map} +1 -1
- package/dashboard/dist/assets/RowActions-BA9L9djf.js +2 -0
- package/dashboard/dist/assets/RowActions-BA9L9djf.js.map +1 -0
- package/dashboard/dist/assets/{RunAsSelector-BzkZXpSX.js → RunAsSelector-2LWkjSnO.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-BzkZXpSX.js.map → RunAsSelector-2LWkjSnO.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-BWhFSr2d.js → StickyPagination-BQEm--kI.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-BWhFSr2d.js.map → StickyPagination-BQEm--kI.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-B6ch-6SY.js → StreamMessageDetail-BTtw3GjX.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-B6ch-6SY.js.map → StreamMessageDetail-BTtw3GjX.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-CjvfUkls.js → SwimlaneTimeline-DdXxP4fO.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-CjvfUkls.js.map → SwimlaneTimeline-DdXxP4fO.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-CZSeyesi.js → TagInput-x9XTuqMb.js} +2 -2
- package/dashboard/dist/assets/{TagInput-CZSeyesi.js.map → TagInput-x9XTuqMb.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-BjHU6opi.js → TaskDetailPage-B8veYG4X.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-BjHU6opi.js.map → TaskDetailPage-B8veYG4X.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-CQrXrSxk.js → TaskQueuePill-DSEQZ-HT.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-CQrXrSxk.js.map → TaskQueuePill-DSEQZ-HT.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-Bem44zd0.js → TasksListPage-CsN1gZj5.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-Bem44zd0.js.map → TasksListPage-CsN1gZj5.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-CUIYqSt_.js → TimeAgo-n182EcLx.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-CUIYqSt_.js.map → TimeAgo-n182EcLx.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell--tnreI1i.js → TimestampCell-2dlcQAfX.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell--tnreI1i.js.map → TimestampCell-2dlcQAfX.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-O09jsTQM.js → ToolPill-B_e4eT77.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-O09jsTQM.js.map → ToolPill-B_e4eT77.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-OD99H7Pk.js → ToolTestPanel-Bhnncc6M.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-OD99H7Pk.js.map → ToolTestPanel-Bhnncc6M.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-rh_dsTJI.js → TopicDetailPage-29lsNsqI.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-rh_dsTJI.js.map → TopicDetailPage-29lsNsqI.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-CD_40_v-.js → TopicsPage-KJ7_LAvo.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-CD_40_v-.js.map → TopicsPage-KJ7_LAvo.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-C__c8BN0.js → UserName-CMoFi9zb.js} +2 -2
- package/dashboard/dist/assets/{UserName-C__c8BN0.js.map → UserName-CMoFi9zb.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-Bw6QdtUO.js → WorkflowExecutionPage-Cymfx-Bp.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-Bw6QdtUO.js.map → WorkflowExecutionPage-Cymfx-Bp.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill-CS-IsR0U.js → WorkflowPill-B66_AnaY.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-CS-IsR0U.js.map → WorkflowPill-B66_AnaY.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-BgI-iOP6.js → WorkflowsDashboard-CqLN8spd.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-BgI-iOP6.js.map → WorkflowsDashboard-CqLN8spd.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-BRc0QbA7.js → WorkflowsOverview-0Rc2WT6q.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-BRc0QbA7.js.map → WorkflowsOverview-0Rc2WT6q.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-DdzspNQR.js → YamlWorkflowDetailPage-CARQ7_LN.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-DdzspNQR.js.map → YamlWorkflowDetailPage-CARQ7_LN.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-Djw5ZbgQ.js → YamlWorkflowsPage-B-7sz1nf.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-Djw5ZbgQ.js.map → YamlWorkflowsPage-B-7sz1nf.js.map} +1 -1
- package/dashboard/dist/assets/{agents-xstNkF6c.js → agents-zM43d5Yf.js} +2 -2
- package/dashboard/dist/assets/{agents-xstNkF6c.js.map → agents-zM43d5Yf.js.map} +1 -1
- package/dashboard/dist/assets/{bots-BztAI0s_.js → bots-D5BasOGz.js} +2 -2
- package/dashboard/dist/assets/{bots-BztAI0s_.js.map → bots-D5BasOGz.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-CEDwtxNL.js → capabilities-BT3PW9CZ.js} +2 -2
- package/dashboard/dist/assets/{capabilities-CEDwtxNL.js.map → capabilities-BT3PW9CZ.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-BlGEsRKe.js → controlplane-NpJr49rN.js} +2 -2
- package/dashboard/dist/assets/{controlplane-BlGEsRKe.js.map → controlplane-NpJr49rN.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-iI4QKlP-.js → escalation-DrzQolPG.js} +2 -2
- package/dashboard/dist/assets/{escalation-iI4QKlP-.js.map → escalation-DrzQolPG.js.map} +1 -1
- package/dashboard/dist/assets/escalation-columns-QzwmtD60.js +2 -0
- package/dashboard/dist/assets/escalation-columns-QzwmtD60.js.map +1 -0
- package/dashboard/dist/assets/index-B5w4Gjyk.js +6 -0
- package/dashboard/dist/assets/index-B5w4Gjyk.js.map +1 -0
- package/dashboard/dist/assets/{index-CMviPjXQ.js → index-BCT4kqGR.js} +2 -2
- package/dashboard/dist/assets/{index-CMviPjXQ.js.map → index-BCT4kqGR.js.map} +1 -1
- package/dashboard/dist/assets/{index-B7VC0vjf.js → index-C69XvBfg.js} +2 -2
- package/dashboard/dist/assets/{index-B7VC0vjf.js.map → index-C69XvBfg.js.map} +1 -1
- package/dashboard/dist/assets/index-CHw4Fl0t.css +1 -0
- package/dashboard/dist/assets/{index-CUfgt3mV.js → index-C_NwHTMh.js} +2 -2
- package/dashboard/dist/assets/{index-CUfgt3mV.js.map → index-C_NwHTMh.js.map} +1 -1
- package/dashboard/dist/assets/{index-CAqEy2Db.js → index-Cq0trGqf.js} +2 -2
- package/dashboard/dist/assets/{index-CAqEy2Db.js.map → index-Cq0trGqf.js.map} +1 -1
- package/dashboard/dist/assets/{index-D1xVY4JR.js → index-DE0r9SEX.js} +22 -22
- package/dashboard/dist/assets/index-DE0r9SEX.js.map +1 -0
- package/dashboard/dist/assets/{index-DjJ6VCuc.js → index-DH_CiD0W.js} +2 -2
- package/dashboard/dist/assets/{index-DjJ6VCuc.js.map → index-DH_CiD0W.js.map} +1 -1
- package/dashboard/dist/assets/{index-DzVYjoex.js → index-K23FdS-T.js} +2 -2
- package/dashboard/dist/assets/{index-DzVYjoex.js.map → index-K23FdS-T.js.map} +1 -1
- package/dashboard/dist/assets/{index-FuhiJuHL.js → index-f6K1UNrn.js} +2 -2
- package/dashboard/dist/assets/{index-FuhiJuHL.js.map → index-f6K1UNrn.js.map} +1 -1
- package/dashboard/dist/assets/{index-B5qsp8lb.js → index-qr1fndqM.js} +2 -2
- package/dashboard/dist/assets/{index-B5qsp8lb.js.map → index-qr1fndqM.js.map} +1 -1
- package/dashboard/dist/assets/index-vKTvJ_li.js +2 -0
- package/dashboard/dist/assets/index-vKTvJ_li.js.map +1 -0
- package/dashboard/dist/assets/{index-BUmnJ4eT.js → index-y-3ODtEE.js} +2 -2
- package/dashboard/dist/assets/{index-BUmnJ4eT.js.map → index-y-3ODtEE.js.map} +1 -1
- package/dashboard/dist/assets/{index-Dsi5o7dx.js → index-y56Ds-LB.js} +2 -2
- package/dashboard/dist/assets/{index-Dsi5o7dx.js.map → index-y56Ds-LB.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-BKg0cr39.js → knowledge-DSSATOTX.js} +2 -2
- package/dashboard/dist/assets/{knowledge-BKg0cr39.js.map → knowledge-DSSATOTX.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-CVdHpKlz.js → mcp-CfJFVo5k.js} +2 -2
- package/dashboard/dist/assets/{mcp-CVdHpKlz.js.map → mcp-CfJFVo5k.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-CYxZcbwQ.js → mcp-query-DKVx2Q-X.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-CYxZcbwQ.js.map → mcp-query-DKVx2Q-X.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-BOEv7P6O.js → pipelines-BSWzE-6M.js} +2 -2
- package/dashboard/dist/assets/{pipelines-BOEv7P6O.js.map → pipelines-BSWzE-6M.js.map} +1 -1
- package/dashboard/dist/assets/{roles-c5cV2QYQ.js → roles-t9HzhI5N.js} +2 -2
- package/dashboard/dist/assets/{roles-c5cV2QYQ.js.map → roles-t9HzhI5N.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-JV3BjeEF.js → tasks-B7rUihoH.js} +2 -2
- package/dashboard/dist/assets/{tasks-JV3BjeEF.js.map → tasks-B7rUihoH.js.map} +1 -1
- package/dashboard/dist/assets/{topics-BDaPnhnQ.js → topics-PC2fEiyD.js} +2 -2
- package/dashboard/dist/assets/{topics-BDaPnhnQ.js.map → topics-PC2fEiyD.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-a7Dnh8G4.js → useEventHooks-DK9mw1cI.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-a7Dnh8G4.js.map → useEventHooks-DK9mw1cI.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-BSwEV0e9.js → useNamespace-3IjtUtAw.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-BSwEV0e9.js.map → useNamespace-3IjtUtAw.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-BuqvL-cn.js → useYamlActivityEvents-uxukp3gO.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-BuqvL-cn.js.map → useYamlActivityEvents-uxukp3gO.js.map} +1 -1
- package/dashboard/dist/assets/users-CC4B5Fm5.js +2 -0
- package/dashboard/dist/assets/users-CC4B5Fm5.js.map +1 -0
- package/dashboard/dist/assets/{vendor-icons-D5ycKPA2.js → vendor-icons-Dy5Jpknf.js} +2 -2
- package/dashboard/dist/assets/{vendor-icons-D5ycKPA2.js.map → vendor-icons-Dy5Jpknf.js.map} +1 -1
- package/dashboard/dist/assets/{workflows-DF-9Voyi.js → workflows-S7MF1nNk.js} +2 -2
- package/dashboard/dist/assets/{workflows-DF-9Voyi.js.map → workflows-S7MF1nNk.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-2roKaSSK.js → yaml-workflows-WfdaMHNn.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-2roKaSSK.js.map → yaml-workflows-WfdaMHNn.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/api/http/escalations.md +131 -10
- package/docs/api/http/roles.md +44 -9
- package/docs/api/http/users.md +15 -6
- package/docs/api/mcp/admin.md +8 -2
- package/docs/api/mcp/human-queue.md +34 -2
- package/docs/api/sdk/escalations.md +155 -2
- package/docs/api/sdk/roles.md +11 -0
- package/docs/api/sdk/users.md +26 -1
- package/docs/auth.md +1 -1
- package/docs/dashboard.md +5 -4
- package/docs/data.md +9 -2
- package/docs/faceted-routing.md +221 -0
- package/docs/hitl-guide.md +50 -0
- package/docs/iam.md +31 -0
- package/docs/mcp.md +8 -0
- package/package.json +2 -2
- package/dashboard/dist/assets/AdminDashboard-LTiYLuzq.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-BEylRqjP.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-BEylRqjP.js.map +0 -1
- package/dashboard/dist/assets/CopyableId-DaT0ZRHg.js +0 -2
- package/dashboard/dist/assets/CopyableId-DaT0ZRHg.js.map +0 -1
- package/dashboard/dist/assets/OperatorDashboard-g9o7I925.js +0 -2
- package/dashboard/dist/assets/PageHeader-Dk2Pe44Q.js +0 -2
- package/dashboard/dist/assets/PageHeader-Dk2Pe44Q.js.map +0 -1
- package/dashboard/dist/assets/PriorityBadge-DfQY9St9.js +0 -2
- package/dashboard/dist/assets/PriorityBadge-DfQY9St9.js.map +0 -1
- package/dashboard/dist/assets/RolePill-Du-aNnjR.js +0 -2
- package/dashboard/dist/assets/RolePill-Du-aNnjR.js.map +0 -1
- package/dashboard/dist/assets/RowActions-Dg-Fsm5O.js +0 -2
- package/dashboard/dist/assets/RowActions-Dg-Fsm5O.js.map +0 -1
- package/dashboard/dist/assets/escalation-columns-nVYVt7Gl.js +0 -2
- package/dashboard/dist/assets/escalation-columns-nVYVt7Gl.js.map +0 -1
- package/dashboard/dist/assets/index-CP0JEQhZ.js +0 -6
- package/dashboard/dist/assets/index-CP0JEQhZ.js.map +0 -1
- package/dashboard/dist/assets/index-ClvYSNZd.css +0 -1
- package/dashboard/dist/assets/index-D1xVY4JR.js.map +0 -1
- package/dashboard/dist/assets/index-DPLy-jwO.js +0 -2
- package/dashboard/dist/assets/index-DPLy-jwO.js.map +0 -1
- package/dashboard/dist/assets/users-Pn85K_3C.js +0 -2
- package/dashboard/dist/assets/users-Pn85K_3C.js.map +0 -1
package/docs/api/mcp/admin.md
CHANGED
|
@@ -54,6 +54,8 @@ Get all tasks and escalations for a process (origin_id).
|
|
|
54
54
|
|
|
55
55
|
## Escalations
|
|
56
56
|
|
|
57
|
+
Escalations belong to a role's queue. Which of them a person sees and acts on is set by their work-surface scope: a role membership carries a `type` (`member`, `admin`, or `superadmin`) plus `read_scope` (`self` | `all`) — which escalations a member sees — and `write_scope` (`none` | `self` | `all`) — which they may claim, resolve, or cancel — with write ⊆ read. `read_self`/`write_self` narrows a member to items assigned to them (`assigned_to = user`); an `admin` or `superadmin` acts on the whole queue. The tools below operate at whole-queue breadth and need a role permitted to act on the target (see [Access](#access) above). The `assigned_to` filter on `find_escalations` pairs with this model — it narrows results to one user's items, the same surface a `read_self` member sees. Defaults are `all`/`all`. See the [Roles API](../http/roles.md) for the full scope model.
|
|
58
|
+
|
|
57
59
|
### find_escalations
|
|
58
60
|
|
|
59
61
|
Search escalations with optional filters and sorting. Returns full records
|
|
@@ -659,11 +661,13 @@ Create a new user account with optional roles.
|
|
|
659
661
|
| external_id | string | Yes | External identifier |
|
|
660
662
|
| display_name | string | No | Display name |
|
|
661
663
|
| email | string | No | Email address |
|
|
662
|
-
| roles | object[] | No | Roles array (each: role
|
|
664
|
+
| roles | object[] | No | Roles array (each: `role`, `type`: superadmin/admin/member, optional `read_scope`, `write_scope`) |
|
|
665
|
+
|
|
666
|
+
Each role entry may carry a member work-surface scope: `read_scope` (`self` \| `all`, default `all`) and `write_scope` (`none` \| `self` \| `all`, default `all`), with write ⊆ read. This is how a one-time user is provisioned — e.g. `{ "role": "customer-triage", "type": "member", "read_scope": "self", "write_scope": "self" }` for someone who only handles their own pre-assigned escalation.
|
|
663
667
|
|
|
664
668
|
### add_user_role
|
|
665
669
|
|
|
666
|
-
Assign a role to a user.
|
|
670
|
+
Assign a role to a user. For a `member`, optional scope narrows the work surface.
|
|
667
671
|
|
|
668
672
|
| | |
|
|
669
673
|
|---|---|
|
|
@@ -676,6 +680,8 @@ Assign a role to a user.
|
|
|
676
680
|
| user_id | string | Yes | User ID |
|
|
677
681
|
| role | string | Yes | Role name |
|
|
678
682
|
| type | string | Yes | Role type: superadmin, admin, or member |
|
|
683
|
+
| read_scope | string | No | Member search breadth: `self` or `all` (default `all`) |
|
|
684
|
+
| write_scope | string | No | Member claim/ack/delete breadth: `none`, `self`, or `all` (default `all`) |
|
|
679
685
|
|
|
680
686
|
### remove_user_role
|
|
681
687
|
|
|
@@ -65,7 +65,7 @@ List available escalations for a role. Returns pending, unassigned escalations.
|
|
|
65
65
|
|
|
66
66
|
### claim_and_resolve
|
|
67
67
|
|
|
68
|
-
Claim an escalation and immediately resolve it with a payload. Atomic operation.
|
|
68
|
+
Claim an escalation and immediately resolve it with a payload. Atomic operation. A read/write service account uses this to close out work and record the outcome in one call.
|
|
69
69
|
|
|
70
70
|
| | |
|
|
71
71
|
|---|---|
|
|
@@ -77,7 +77,24 @@ Claim an escalation and immediately resolve it with a payload. Atomic operation.
|
|
|
77
77
|
|-------|------|----------|-------------|
|
|
78
78
|
| escalation_id | string | Yes | The escalation ID to claim and resolve |
|
|
79
79
|
| resolver_id | string | Yes | Identifier for who/what is resolving |
|
|
80
|
-
| payload | object | Yes | Resolution payload data |
|
|
80
|
+
| payload | object | Yes | Resolution payload data — resumes the waiting workflow |
|
|
81
|
+
| metadata | object | No | Outcome facets merged into the escalation's metadata: the durable, `@>`-queryable record of what happened (disposition, reviewer, timing). Distinct from `payload`, which is not indexed |
|
|
82
|
+
|
|
83
|
+
### resolve_escalation
|
|
84
|
+
|
|
85
|
+
Resolve an already-claimed escalation with a payload. Use when the claim happened externally (e.g. via API).
|
|
86
|
+
|
|
87
|
+
| | |
|
|
88
|
+
|---|---|
|
|
89
|
+
| Read-safe | No |
|
|
90
|
+
|
|
91
|
+
**Parameters:**
|
|
92
|
+
|
|
93
|
+
| Field | Type | Required | Description |
|
|
94
|
+
|-------|------|----------|-------------|
|
|
95
|
+
| escalation_id | string | Yes | The escalation ID to resolve |
|
|
96
|
+
| payload | object | Yes | Resolution payload data — resumes the waiting workflow |
|
|
97
|
+
| metadata | object | No | Outcome facets merged into the escalation's metadata (see `claim_and_resolve`) |
|
|
81
98
|
|
|
82
99
|
### escalate_and_wait
|
|
83
100
|
|
|
@@ -99,3 +116,18 @@ Create an escalation and pause the workflow until a human responds. Returns a si
|
|
|
99
116
|
| type | string | No | Escalation type classification (default: "mcp") |
|
|
100
117
|
| subtype | string | No | Escalation subtype (default: "wait_for_human") |
|
|
101
118
|
| priority | number | No | Priority: 1 (highest) to 4 (lowest) (default: 1) |
|
|
119
|
+
|
|
120
|
+
## Scope and One-Time Users
|
|
121
|
+
|
|
122
|
+
Escalations created by these tools land in the target role's queue. Each member of that role sees and acts on them according to their work-surface scope — two axes carried by the role membership alongside its `type` (`member`, `admin`, or `superadmin`):
|
|
123
|
+
|
|
124
|
+
- `read_scope` (`self` | `all`) governs which escalations a member sees. `read_all` shows the whole role queue; `read_self` shows only items assigned to the member (`assigned_to = user`).
|
|
125
|
+
- `write_scope` (`none` | `self` | `all`) governs which a member may claim and resolve. `write_self` acts only on the member's own assigned items; `write_all` acts on the whole queue. The constraint is write ⊆ read — you cannot act on what you cannot see.
|
|
126
|
+
|
|
127
|
+
An `admin` or `superadmin` member ignores scope and always acts on the whole queue. The defaults are `all`/`all` — the full-queue worker.
|
|
128
|
+
|
|
129
|
+
`get_available_work` lists pending, unassigned escalations for a role: the shared pool that whole-queue (`write_all`) workers pull from. A `write_self` member does not draw from this pool — their item is pre-assigned to them.
|
|
130
|
+
|
|
131
|
+
### The one-time-user pattern
|
|
132
|
+
|
|
133
|
+
To route a single escalation to a named person, set `assigned_to` when creating it — the `assigned_to` field on `escalate_and_wait` pre-claims the item for that user — and provision that person as a `member` of the role with `read_self` + `write_self`. The result is a scoped single-item surface: they see and act on exactly that one escalation, with no access to the rest of the queue. The scoped membership is provisioned through the platform's user and escalation APIs (see the [Roles API](../http/roles.md)); these MCP tools supply the `assigned_to` pre-claim.
|
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
Manage human-in-the-loop escalations -- list, claim, resolve, and bulk-operate on workflow escalations.
|
|
4
4
|
|
|
5
|
+
## Work-Surface Scope
|
|
6
|
+
|
|
7
|
+
Escalation methods enforce the caller's role work-surface scope server-side; the SDK method signatures are unchanged. For a `member`:
|
|
8
|
+
|
|
9
|
+
- `read_scope` governs **search** — `list`, `listAvailable`, `findByMetadata`, `getStats`, and a single `get` return only the escalations the member is allowed to see. `read_scope=self` limits this to items assigned to the member; `read_scope=all` exposes the whole role queue.
|
|
10
|
+
- `write_scope` governs **claim / ack (resolve) / delete (cancel)** — a member with `write_scope=self` may only `claim`, `resolve`, and `cancel` items already assigned to them. `release`, `escalate`, and `create` (standalone) are queue-management verbs and require `write_scope=all`.
|
|
11
|
+
|
|
12
|
+
`admin` and `superadmin` ignore scope and act on the whole queue. Scope is set when a role is assigned — see [`lt.users.addRole`](users.md) and [Roles API — Work-Surface Scope](../http/roles.md).
|
|
13
|
+
|
|
5
14
|
## create
|
|
6
15
|
|
|
7
16
|
Create an escalation. The caller must hold the target role or be a superadmin.
|
|
@@ -52,6 +61,18 @@ const result = await lt.escalations.list({
|
|
|
52
61
|
role: 'reviewer',
|
|
53
62
|
limit: 25,
|
|
54
63
|
});
|
|
64
|
+
|
|
65
|
+
// Faceted query — a "facet" is a key/value INSIDE the row's metadata JSONB. The
|
|
66
|
+
// filter AND the count run in SQL, role-scoped; nothing is filtered client-side.
|
|
67
|
+
const faceted = await lt.escalations.list({
|
|
68
|
+
status: 'pending',
|
|
69
|
+
facets: { flags: 'too_short' }, // metadata @> { flags: 'too_short' }
|
|
70
|
+
range: [{ facet: 'confidence', op: '<=', value: 0.7 }],
|
|
71
|
+
block: [{ outcome: 'success' }], // exclude completed
|
|
72
|
+
exists: ['needsReview'],
|
|
73
|
+
orderBy: [{ field: 'metadata.confidence', numeric: true, direction: 'asc' }],
|
|
74
|
+
limit: 50,
|
|
75
|
+
});
|
|
55
76
|
```
|
|
56
77
|
|
|
57
78
|
**Parameters:**
|
|
@@ -60,14 +81,25 @@ const result = await lt.escalations.list({
|
|
|
60
81
|
|-------|------|----------|-------------|
|
|
61
82
|
| `status` | `string` | No | Filter by `pending`, `resolved`, or `cancelled` |
|
|
62
83
|
| `role` | `string` | No | Filter by assigned role |
|
|
84
|
+
| `roles` | `string[]` | No | Restrict to these roles (`role = ANY`) — narrows within the caller's scope, never widens past it |
|
|
63
85
|
| `type` | `string` | No | Filter by workflow type |
|
|
64
86
|
| `subtype` | `string` | No | Filter by subtype |
|
|
65
87
|
| `assigned_to` | `string` | No | Filter by assigned user ID |
|
|
66
88
|
| `priority` | `number` | No | Filter by priority (1--4) |
|
|
89
|
+
| `facets` | `Record<string, any>` | No | Required metadata facets — `metadata @> facets` (AND, GIN-served). `{ k: v }` means `metadata.k == v` for a top-level scalar; for nested/arrays it is JSONB **containment** |
|
|
90
|
+
| `block` | `Record<string, any>[]` | No | Exclude rows whose metadata contains ANY of these facet sets — `NOT (metadata @> ANY(block))` |
|
|
91
|
+
| `range` | `{ facet, op, value }[]` | No | Numeric range over a metadata facet, e.g. `{ facet: 'confidence', op: '<=', value: 0.7 }` |
|
|
92
|
+
| `exists` | `string[]` | No | Metadata keys that must be present — `metadata ? key` |
|
|
93
|
+
| `available` | `boolean` | No | `true` = unclaimed/expired only; `false` = held now |
|
|
67
94
|
| `limit` | `number` | No | Max results (default: 50) |
|
|
68
95
|
| `offset` | `number` | No | Pagination offset |
|
|
69
96
|
| `sort_by` | `string` | No | Column to sort by (e.g. `created_at`, `priority`) |
|
|
70
97
|
| `order` | `string` | No | `asc` or `desc` |
|
|
98
|
+
| `orderBy` | `{ field, direction?, numeric? }[]` | No | Multi-key sort over columns or a metadata path written `metadata.<key>` (set `numeric` for numeric sort) |
|
|
99
|
+
|
|
100
|
+
When any faceted element (`facets`/`block`/`range`/`exists`/`roles`/`available`/`orderBy`) is
|
|
101
|
+
present the request runs through the scoped faceted query; otherwise the simple list path is used.
|
|
102
|
+
See [Faceted Routing — the human / operations query](../../faceted-routing.md#the-human--operations-query).
|
|
71
103
|
|
|
72
104
|
**Returns:** `LTApiResult<{ escalations, total }>`
|
|
73
105
|
|
|
@@ -99,6 +131,9 @@ const result = await lt.escalations.listAvailable({
|
|
|
99
131
|
| `sort_by` | `string` | No | Column to sort by |
|
|
100
132
|
| `order` | `string` | No | `asc` or `desc` |
|
|
101
133
|
|
|
134
|
+
Also accepts the same faceted parameters as [`list`](#list) (`facets`, `block`, `range`,
|
|
135
|
+
`exists`, `roles`, `orderBy`), pinned to the available pool.
|
|
136
|
+
|
|
102
137
|
**Returns:** `LTApiResult<{ escalations, total }>`
|
|
103
138
|
|
|
104
139
|
**Auth:** Required
|
|
@@ -259,6 +294,7 @@ Supports two resolution paths: signal-routed (sends payload to a paused workflow
|
|
|
259
294
|
const result = await lt.escalations.resolve({
|
|
260
295
|
id: 'esc_123',
|
|
261
296
|
resolverPayload: { approved: true, comment: 'Looks good' },
|
|
297
|
+
metadata: { outcome: 'approved', reviewedBy: 'alice', durationMs: 1_240 },
|
|
262
298
|
});
|
|
263
299
|
```
|
|
264
300
|
|
|
@@ -267,7 +303,8 @@ const result = await lt.escalations.resolve({
|
|
|
267
303
|
| Field | Type | Required | Description |
|
|
268
304
|
|-------|------|----------|-------------|
|
|
269
305
|
| `id` | `string` | Yes | Escalation UUID |
|
|
270
|
-
| `resolverPayload` | `Record<string, any>` | Yes | Human decision data |
|
|
306
|
+
| `resolverPayload` | `Record<string, any>` | Yes | Human decision data — resumes the paused workflow; not indexed |
|
|
307
|
+
| `metadata` | `Record<string, any>` | No | Outcome facets merged into the row's GIN-indexed metadata. Records *what happened* (disposition, timing) next to *what was asked*; `@>`-queryable. See [Recording the outcome](#recording-the-outcome-on-resolve) |
|
|
271
308
|
|
|
272
309
|
**Returns:** `LTApiResult<{ signaled, escalationId, workflowId }>` (signal path) or `LTApiResult<{ started, escalationId, workflowId }>` (re-run path) -- returns 404 if not found, 409 if not pending.
|
|
273
310
|
|
|
@@ -275,6 +312,35 @@ const result = await lt.escalations.resolve({
|
|
|
275
312
|
|
|
276
313
|
---
|
|
277
314
|
|
|
315
|
+
## Recording the outcome on resolve
|
|
316
|
+
|
|
317
|
+
Every resolve path — `resolve`, `resolveBySignalKey`, the HTTP routes, the MCP tools, and the
|
|
318
|
+
in-process `EscalationService.resolveEscalation` — takes an optional `metadata` patch. It is
|
|
319
|
+
merged, not replaced, into the row's GIN-indexed metadata, recording the **outcome** on the
|
|
320
|
+
same row that carried the **intent**.
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
await lt.escalations.resolve({
|
|
324
|
+
id: 'esc_123',
|
|
325
|
+
resolverPayload: { approved: true }, // resumes the workflow; not indexed
|
|
326
|
+
metadata: { outcome: 'approved', durationMs: 1_240 }, // recorded on the row; @>-queryable
|
|
327
|
+
});
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
The patch is distinct from `resolverPayload`: the payload is delivered to the waiting workflow
|
|
331
|
+
as `condition()`'s return value; the patch is the durable, queryable record. Intent and
|
|
332
|
+
outcome live on one row — no side table:
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
await lt.escalations.findByMetadata({ key: 'outcome', value: 'approved' });
|
|
336
|
+
// every resolved row that was approved — with its disposition and duration
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
The in-process library takes the same patch as a third argument:
|
|
340
|
+
`resolveEscalation(id, payload, metadata)` and `resolveEscalationBySignalKey(signalKey, payload, metadata)`.
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
278
344
|
## conditionLT (workflow helper)
|
|
279
345
|
|
|
280
346
|
Wait for a signal and automatically resolve the associated escalation. This is the counterpart to `executeLT` — where `executeLT` wraps `startChild` + `condition`, `conditionLT` wraps `condition` + escalation resolution.
|
|
@@ -283,6 +349,16 @@ Wait for a signal and automatically resolve the associated escalation. This is t
|
|
|
283
349
|
conditionLT<T>(signalId: string, escalation?: ConditionQueueConfig): Promise<T | false | null>
|
|
284
350
|
```
|
|
285
351
|
|
|
352
|
+
### Two ways to pause on an escalation
|
|
353
|
+
|
|
354
|
+
There are two ways to make a workflow pause as a claimable escalation, and they are not equivalent in cost:
|
|
355
|
+
|
|
356
|
+
- **Native `condition(signalId, escalationConfig)` — the efficient primitive.** HotMesh's `condition` takes an optional escalation config as its second argument. The row is written inside the workflow's Leg1 checkpoint, with `signal_key = signalId`. Resolving it (`resolve` / `resolveBySignalKey`) marks the row resolved **and** delivers the signal in one guarded transaction, resuming the job in place. No create activity, no enrich step, and **no proxy-activity round-trip on the resume** — the resolve is the whole transaction. This is the path to prefer.
|
|
357
|
+
|
|
358
|
+
- **`conditionLT(signalId, config?)` — long-tail sugar.** With a config it delegates to the native efficient `condition` above (same atomic behavior — use it freely). Without a config it also supports the older **two-step** pattern: an escalation created separately, where the resume injects `$escalation_id` and `conditionLT` resolves it through a durable `proxyActivity` (`ltResolveEscalation`). That extra activity round-trip is the cost of the two-step form; the efficient form (and native `condition`) avoid it.
|
|
359
|
+
|
|
360
|
+
Reach for native `condition(signalId, config)` when you want the leanest path; reach for `conditionLT` for the ergonomic wrapper or to support the legacy two-step flow. Both resume the same row, and both accept the resolve-time `metadata` patch (the efficient path merges it in the single guarded UPDATE; the two-step path forwards it through `ltResolveEscalation` into that same atomic resolve).
|
|
361
|
+
|
|
286
362
|
### Atomic form (recommended)
|
|
287
363
|
|
|
288
364
|
Pass an escalation config as the second argument. The escalation row is written inside the workflow's Leg1 checkpoint — one commit, crash-safe: no separate `ltCreateEscalation` activity, no enrich step. `signal_key` is set to `signalId`, so the dashboard resolve endpoint (resolve-by-id → Path 0) and `POST /escalations/resolve-by-signal-key` resume *this* job in place, and `system.escalation.{id}.created` fires automatically.
|
|
@@ -662,7 +738,7 @@ const result = await lt.escalations.claimByMetadata({
|
|
|
662
738
|
| `metadata` | `object` | No | Merge into escalation metadata (single atomic SQL call with the claim) |
|
|
663
739
|
| `provisionIfAbsent` | `object` | No | JIT-provision the assignee if they don't exist or lack the required role (superadmin only) |
|
|
664
740
|
|
|
665
|
-
`provisionIfAbsent` accepts `{ displayName?, email?, roles?: [{ role, type? }] }`. Only callers with global escalation access can use this flag. The happy path (user exists, has role) adds zero extra queries.
|
|
741
|
+
`provisionIfAbsent` accepts `{ displayName?, email?, roles?: [{ role, type?, read_scope?, write_scope? }] }`. Each role entry forwards the optional work-surface scope fields `read_scope` (`self` or `all`, default `all`) and `write_scope` (`none`, `self`, or `all`, default `all`), subject to the **write ⊆ read** constraint; scope is ignored for `admin`/`superadmin`. To JIT-provision a one-time user who sees and acts on exactly the item being claimed, provision them `read_scope: 'self'` + `write_scope: 'self'`. Only callers with global escalation access can use this flag. The happy path (user exists, has role) adds zero extra queries.
|
|
666
742
|
|
|
667
743
|
**Returns:** `LTApiResult<{ escalation, isExtension }>` -- 404 if no match, 409 if already claimed.
|
|
668
744
|
|
|
@@ -707,3 +783,80 @@ const result = await lt.escalations.resolveByMetadata({
|
|
|
707
783
|
**Returns:** `LTApiResult<{ escalation }>` for non-signal, `LTApiResult<{ signaled, escalationId, workflowId }>` for signal-backed. 404 if no match.
|
|
708
784
|
|
|
709
785
|
**Auth:** Required
|
|
786
|
+
|
|
787
|
+
## resolveByIds
|
|
788
|
+
|
|
789
|
+
Resolve a set of escalations by id in one guarded statement (the set-based sibling of `resolve`). For bookkeeping rows woken collectively — it does not deliver a per-row signal. RBAC: a scoped caller may only resolve rows whose role they hold.
|
|
790
|
+
|
|
791
|
+
```typescript
|
|
792
|
+
const result = await lt.escalations.resolveByIds({
|
|
793
|
+
ids: ['esc_1', 'esc_2', 'esc_3'],
|
|
794
|
+
resolverPayload: { printerId: 'p-7' },
|
|
795
|
+
metadata: { outcome: 'settled' },
|
|
796
|
+
});
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
| Field | Type | Required | Description |
|
|
800
|
+
|-------|------|----------|-------------|
|
|
801
|
+
| `ids` | `string[]` | Yes | Escalation ids to resolve as one set |
|
|
802
|
+
| `resolverPayload` | `Record<string, any>` | Yes | Payload applied to every row |
|
|
803
|
+
| `metadata` | `Record<string, any>` | No | Outcome patch merged into each row |
|
|
804
|
+
|
|
805
|
+
**Returns:** `LTApiResult<{ resolved: number; escalationIds: string[] }>` — only still-`pending` rows are resolved.
|
|
806
|
+
|
|
807
|
+
## resolveBySignalKey
|
|
808
|
+
|
|
809
|
+
Resolve an efficient (atomic) escalation directly by its `signal_key` and resume the waiting workflow in place. For callers that know the deterministic signal id and want to skip the id lookup. RBAC-scoped to the escalation's role.
|
|
810
|
+
|
|
811
|
+
```typescript
|
|
812
|
+
const result = await lt.escalations.resolveBySignalKey({
|
|
813
|
+
signalKey: 'signal-scan-ar-order-42',
|
|
814
|
+
resolverPayload: { approved: true },
|
|
815
|
+
});
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
**Returns:** `LTApiResult<{ signaled: true; escalationId; workflowId }>`.
|
|
819
|
+
|
|
820
|
+
## searchByFacets
|
|
821
|
+
|
|
822
|
+
Item-level faceted search over a single pond `role`, scoped to the caller's role. The faceted-routing read primitive.
|
|
823
|
+
|
|
824
|
+
```typescript
|
|
825
|
+
const result = await lt.escalations.searchByFacets({
|
|
826
|
+
role: 'printer-pool-diabetic',
|
|
827
|
+
status: 'pending',
|
|
828
|
+
available: true,
|
|
829
|
+
facets: { state: 'ready' },
|
|
830
|
+
limit: 50,
|
|
831
|
+
});
|
|
832
|
+
```
|
|
833
|
+
|
|
834
|
+
**Returns:** `LTApiResult<{ escalations; total }>`.
|
|
835
|
+
|
|
836
|
+
## claimGroups
|
|
837
|
+
|
|
838
|
+
Batch-claim complete origin groups (e.g. all units of an order) in priority order over a pond, assigned to the caller. RBAC-scoped to the pond role.
|
|
839
|
+
|
|
840
|
+
```typescript
|
|
841
|
+
const result = await lt.escalations.claimGroups({
|
|
842
|
+
query: { role: 'print-farm-diabetic', available: true, facets: { filament: 'pla', size_class: 'standard' } },
|
|
843
|
+
limit: 4,
|
|
844
|
+
durationMinutes: 30,
|
|
845
|
+
sizeFacet: 'order_size',
|
|
846
|
+
});
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
**Returns:** `LTApiResult<{ groups }>`.
|
|
850
|
+
|
|
851
|
+
## claimByFacets
|
|
852
|
+
|
|
853
|
+
Batch-claim individual rows matching a facet query (`FOR UPDATE SKIP LOCKED`), assigned to the caller. With `allOrNone`, commits only when the full `limit` is acquired. RBAC-scoped to the pond role.
|
|
854
|
+
|
|
855
|
+
```typescript
|
|
856
|
+
const result = await lt.escalations.claimByFacets({
|
|
857
|
+
query: { role: 'printer-pool-diabetic', facets: { state: 'ready', filament: 'pla' } },
|
|
858
|
+
limit: 3,
|
|
859
|
+
});
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
**Returns:** `LTApiResult<{ claimed }>`.
|
package/docs/api/sdk/roles.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
Manage roles and escalation chain routing between roles.
|
|
4
4
|
|
|
5
|
+
## Work-Surface Scope
|
|
6
|
+
|
|
7
|
+
A role is a task queue worked by its members. Each `member` assignment carries two work-surface scope axes that set how much of the queue that member touches:
|
|
8
|
+
|
|
9
|
+
- `read_scope` (`self` or `all`, default `all`) governs **search** — which escalations the member sees.
|
|
10
|
+
- `write_scope` (`none`, `self`, or `all`, default `all`) governs **claim / ack (resolve) / delete (cancel)** — which escalations the member may act on.
|
|
11
|
+
|
|
12
|
+
`self` means items assigned to the member; `all` means the whole role queue. The constraint is **write ⊆ read** — `write_scope=all` requires `read_scope=all`. `admin` and `superadmin` ignore scope and always act on the whole queue. The default `all`/`all` is the full-queue worker.
|
|
13
|
+
|
|
14
|
+
Scope is set when a role is assigned to a user, via [`lt.users.addRole`](users.md) and [`lt.users.create`](users.md). See [Roles API — Work-Surface Scope](../http/roles.md) for the five member profiles.
|
|
15
|
+
|
|
5
16
|
## list
|
|
6
17
|
|
|
7
18
|
List all distinct role names in the system.
|
package/docs/api/sdk/users.md
CHANGED
|
@@ -70,9 +70,19 @@ const result = await lt.users.create({
|
|
|
70
70
|
| `external_id` | `string` | Yes | External system identifier |
|
|
71
71
|
| `email` | `string` | No | Email address |
|
|
72
72
|
| `display_name` | `string` | No | Display name |
|
|
73
|
-
| `roles` | `{ role: string; type: string }[]` | No | Initial role assignments (type: `superadmin`, `admin`, or `member`) |
|
|
73
|
+
| `roles` | `{ role: string; type: string; read_scope?: string; write_scope?: string }[]` | No | Initial role assignments (type: `superadmin`, `admin`, or `member`) |
|
|
74
74
|
| `metadata` | `Record<string, any>` | No | Arbitrary key-value metadata |
|
|
75
75
|
|
|
76
|
+
Each role entry forwards the optional work-surface scope fields `read_scope` (`self` or `all`, default `all`) and `write_scope` (`none`, `self`, or `all`, default `all`) to the API. Scope refines a `member` grant and is ignored for `admin`/`superadmin`. The constraint is **write ⊆ read** — `write_scope=all` requires `read_scope=all`. The default `all`/`all` is the full-queue worker. See [Roles API — Work-Surface Scope](../http/roles.md) for the five member profiles.
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// A one-time user who sees and acts only on their own pre-assigned item
|
|
80
|
+
const result = await lt.users.create({
|
|
81
|
+
external_id: 'new-user',
|
|
82
|
+
roles: [{ role: 'customer-triage', type: 'member', read_scope: 'self', write_scope: 'self' }],
|
|
83
|
+
});
|
|
84
|
+
```
|
|
85
|
+
|
|
76
86
|
**Returns:** `LTApiResult<User>` (status 201) -- returns 409 if `external_id` already exists.
|
|
77
87
|
|
|
78
88
|
**Auth:** Not required
|
|
@@ -166,6 +176,21 @@ const result = await lt.users.addRole({
|
|
|
166
176
|
| `id` | `string` | Yes | User UUID |
|
|
167
177
|
| `role` | `string` | Yes | Role name to assign |
|
|
168
178
|
| `type` | `string` | Yes | Role type (`superadmin`, `admin`, or `member`) |
|
|
179
|
+
| `read_scope` | `string` | No | `self` or `all` (default `all`). Search breadth for a `member`; ignored for admin/superadmin |
|
|
180
|
+
| `write_scope` | `string` | No | `none`, `self`, or `all` (default `all`). Claim/ack/delete breadth for a `member` |
|
|
181
|
+
|
|
182
|
+
`read_scope` and `write_scope` are the work-surface scope axes for a `member` grant: `read_scope` governs which escalations the member sees in search; `write_scope` governs which they may claim, ack (resolve), or delete (cancel). `self` means items assigned to the member; `all` means the whole role queue. The constraint is **write ⊆ read** — `write_scope=all` requires `read_scope=all`. Both default to `all` (full-queue worker), and both are ignored for `admin`/`superadmin`, which always act on the whole queue. The returned role object includes `read_scope` and `write_scope`. See [Roles API — Work-Surface Scope](../http/roles.md) for the five member profiles.
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
// See the whole queue, act only on own items (e.g. a chat-style room)
|
|
186
|
+
const result = await lt.users.addRole({
|
|
187
|
+
id: 'user_123',
|
|
188
|
+
role: 'reviewer',
|
|
189
|
+
type: 'member',
|
|
190
|
+
read_scope: 'all',
|
|
191
|
+
write_scope: 'self',
|
|
192
|
+
});
|
|
193
|
+
```
|
|
169
194
|
|
|
170
195
|
**Returns:** `LTApiResult<UserRole>` (status 201)
|
|
171
196
|
|
package/docs/auth.md
CHANGED
|
@@ -239,7 +239,7 @@ When SSO is configured and a request arrives without a Bearer token, `requireAut
|
|
|
239
239
|
|
|
240
240
|
Roles are resolved once during the token exchange (not per-request) and baked into the JWT — the same pattern as the built-in login. When the host system changes a user's roles, the new roles take effect on the next token refresh.
|
|
241
241
|
|
|
242
|
-
If `roleMap` is provided, only mapped roles are assigned. If omitted, host role names are passed through directly as LT role names. Roles named `superadmin` or `admin` are assigned the corresponding role type; all others default to `member`.
|
|
242
|
+
If `roleMap` is provided, only mapped roles are assigned. If omitted, host role names are passed through directly as LT role names. Roles named `superadmin` or `admin` are assigned the corresponding role type; all others default to `member`. Provisioned `member` grants take the default work-surface scope of `read_all`/`write_all` — the full-queue worker. Narrower scopes (for one-time or read-only users) are set through the [Roles API](api/http/roles.md#work-surface-scope) or the dashboard Scope picker.
|
|
243
243
|
|
|
244
244
|
### Standalone Deployments
|
|
245
245
|
|
package/docs/dashboard.md
CHANGED
|
@@ -187,18 +187,19 @@ Lists all durable workflow runs across the system.
|
|
|
187
187
|
|
|
188
188
|
User Accounts and Service Accounts live on the same page, separated by a tab toggle.
|
|
189
189
|
|
|
190
|
-
- **User Accounts** — human operators. Create users, assign display names, and grant roles. Roles determine which escalations a user can see and claim, and which workflows they can invoke from the dashboard.
|
|
190
|
+
- **User Accounts** — human operators. Create users, assign display names, and grant roles. Roles determine which escalations a user can see and claim, and which workflows they can invoke from the dashboard. A `member` grant carries a work-surface scope (read/write breadth) chosen from the Scope picker; see [Roles](#roles).
|
|
191
191
|
- **Service Accounts** — programmatic callers (bots, CI pipelines, external systems). Each service account has an API key for authentication. Assign roles to control access just like human users. Service accounts with the `reviewer` role can claim and resolve escalations programmatically.
|
|
192
192
|
- **Role assignment** — both account types participate in the same role system. Click any account to edit roles, change display name, or manage credentials.
|
|
193
193
|
|
|
194
194
|
**API:** `GET /api/users` lists accounts. `POST /api/users` creates. `PUT /api/users/:id/roles` assigns roles.
|
|
195
195
|
|
|
196
|
-
### Roles
|
|
196
|
+
### Roles
|
|
197
197
|
|
|
198
198
|
Define roles and configure escalation chains that control how work flows between teams.
|
|
199
199
|
|
|
200
200
|
- **Role list** — all roles in the system with their type (admin, operator, custom). Click to view assigned users.
|
|
201
201
|
- **Create Role** — add a new role. Roles referenced in workflow configs are auto-created, but you can also create them here for organizational clarity.
|
|
202
|
+
- **Scope picker** — when granting a role at `member` type, a Scope picker offers the five named work-surface profiles: full worker (`all`/`all`, default), see-all-act-own (`all`/`self`), own-items-only (`self`/`self`), read-only auditor (`all`/`none`), and read-only own (`self`/`none`). `admin` and `superadmin` grants show no Scope picker — they always work the whole queue. The picker enforces **write ⊆ read**, so a write breadth wider than the read breadth cannot be selected.
|
|
202
203
|
- **Escalation chains** — define source → target role mappings. When a reviewer escalates, the chain determines which roles receive the escalation next. Chains are directional (reviewer → engineer → admin) and support multiple targets per source.
|
|
203
204
|
|
|
204
205
|
**API:** `GET /api/roles` lists roles. `POST /api/roles` creates. `GET /api/roles/escalation-chains` lists chains. `POST /api/roles/escalation-chains` adds a chain.
|
|
@@ -245,8 +246,8 @@ The central queue for all escalation activity across every workflow.
|
|
|
245
246
|
|
|
246
247
|
- **Filter bar** — filter by status (pending/claimed/resolved), role, workflow type, priority, and time window.
|
|
247
248
|
- **Columns:** Escalation ID, workflow type, role, status, priority, created time, and claimed-by user.
|
|
248
|
-
- **Claim** — click the claim action to lock an escalation to your user. Only users with matching roles see pending escalations.
|
|
249
|
-
- **Resolve** — after claiming, submit a resolver payload (pre-filled from the workflow's `resolver_schema` if configured). Resolution triggers a workflow re-run with the resolver data injected.
|
|
249
|
+
- **Claim** — click the claim action to lock an escalation to your user. Only users with matching roles see pending escalations. The queue list and aggregate stats reflect `read_all` memberships — a member scoped to `read_self` lands directly on their own assigned item in user mode rather than browsing the full queue.
|
|
250
|
+
- **Resolve** — after claiming, submit a resolver payload (pre-filled from the workflow's `resolver_schema` if configured). Resolution triggers a workflow re-run with the resolver data injected. A `member` whose `write_scope` is `self` can resolve only items already assigned to them; `write_scope=none` is read-only.
|
|
250
251
|
- **Escalate** — forward a claimed escalation to a higher-tier role via the escalation chain.
|
|
251
252
|
|
|
252
253
|
**API:** `GET /api/escalations` lists with filters. `POST /api/escalations/:id/claim` claims. `POST /api/escalations/:id/resolve` resolves.
|
package/docs/data.md
CHANGED
|
@@ -74,6 +74,11 @@ backward-compatible **view** over it — `SELECT *` plus a computed `available`
|
|
|
74
74
|
column — so existing read queries and the public API are unchanged. Indexes are
|
|
75
75
|
managed by the SDK on `hmsh_escalations` (see below).
|
|
76
76
|
|
|
77
|
+
Role read/write scope does **not** add columns here. An escalation carries a `role`
|
|
78
|
+
and an optional `assigned_to`; work-surface scope lives on the membership table
|
|
79
|
+
(`lt_user_roles`) and is applied at read time. `condition()` / `conditionLT()` and
|
|
80
|
+
the escalation engine are unaffected.
|
|
81
|
+
|
|
77
82
|
The columns below are the `hmsh_escalations` table. The public API record
|
|
78
83
|
(`LTEscalationRecord`) is mapped from these: the JSONB `envelope` /
|
|
79
84
|
`escalation_payload` / `resolver_payload` are serialized to JSON **strings**, and
|
|
@@ -179,12 +184,14 @@ Maps users to roles. Each user can hold multiple roles with different permission
|
|
|
179
184
|
|--------|------|---------|-------------|
|
|
180
185
|
| `user_id` | `UUID NOT NULL` | — | FK to `lt_users(id)`, CASCADE on delete |
|
|
181
186
|
| `role` | `TEXT NOT NULL` | — | Role name (e.g., `reviewer`, `senior-reviewer`) |
|
|
182
|
-
| `type` | `TEXT NOT NULL` | `'member'` | `superadmin`, `admin`, or `member` |
|
|
187
|
+
| `type` | `TEXT NOT NULL` | `'member'` | `superadmin`, `admin`, or `member` — the management tier |
|
|
188
|
+
| `read_scope` | `TEXT NOT NULL` | `'all'` | `self` or `all` — search breadth for a `member`: which escalations in the role queue the member sees. `self` = items where `assigned_to = user`; `all` = the whole queue. Ignored for `admin`/`superadmin`, which always see the whole queue. |
|
|
189
|
+
| `write_scope` | `TEXT NOT NULL` | `'all'` | `none`, `self`, or `all` — claim/ack/delete breadth for a `member`. `none` = read-only; `self` = items assigned to the member; `all` = the whole queue. Ignored for `admin`/`superadmin`. |
|
|
183
190
|
| `created_at` | `TIMESTAMPTZ NOT NULL` | `NOW()` | When the role was assigned |
|
|
184
191
|
|
|
185
192
|
Primary key: `(user_id, role)` — a user can hold each role at most once.
|
|
186
193
|
|
|
187
|
-
Type is enforced by a CHECK constraint: `type IN ('superadmin', 'admin', 'member')`.
|
|
194
|
+
Type is enforced by a CHECK constraint: `type IN ('superadmin', 'admin', 'member')`. Scope is enforced by CHECK constraints: `read_scope IN ('self', 'all')`, `write_scope IN ('none', 'self', 'all')`, and **write ⊆ read** — `write_scope = 'all'` requires `read_scope = 'all'` (a member cannot act on what it cannot see). Both scopes default to `all`, the full-queue worker.
|
|
188
195
|
|
|
189
196
|
### lt_bot_api_keys
|
|
190
197
|
|