@hotmeshio/long-tail 0.10.14 → 0.11.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/build/api/escalations/analytics.d.ts +6 -0
- package/build/api/escalations/analytics.js +123 -0
- package/build/api/escalations/index.d.ts +1 -0
- package/build/api/escalations/index.js +4 -1
- package/build/api/roles.d.ts +4 -0
- package/build/api/roles.js +8 -0
- package/build/api/scan-codes/choice.d.ts +11 -0
- package/build/api/scan-codes/choice.js +136 -0
- package/build/api/scan-codes/context.d.ts +24 -0
- package/build/api/scan-codes/context.js +86 -0
- package/build/api/scan-codes/execute.d.ts +1 -0
- package/build/api/scan-codes/execute.js +49 -244
- package/build/api/scan-codes/identity.d.ts +18 -0
- package/build/api/scan-codes/identity.js +116 -0
- package/build/api/scan-codes/index.d.ts +2 -0
- package/build/api/scan-codes/index.js +6 -1
- package/build/api/scan-codes/locate.d.ts +14 -0
- package/build/api/scan-codes/locate.js +127 -0
- package/build/api/scan-codes/present.d.ts +9 -0
- package/build/api/scan-codes/present.js +59 -0
- package/build/api/scan-codes/verbs.d.ts +15 -0
- package/build/api/scan-codes/verbs.js +205 -0
- package/build/bin/ltc.js +33 -0
- package/build/lib/cli/commands/escalations.d.ts +31 -0
- package/build/lib/cli/commands/escalations.js +88 -0
- package/build/lib/db/schemas/028_role_entity_facet.sql +18 -0
- package/build/lib/db/schemas/029_scan_scheme_kind.sql +31 -0
- package/build/modules/config.d.ts +5 -0
- package/build/modules/config.js +12 -0
- package/build/routes/escalations/acting.d.ts +12 -0
- package/build/routes/escalations/acting.js +25 -0
- package/build/routes/escalations/analytics.d.ts +8 -0
- package/build/routes/escalations/analytics.js +63 -0
- package/build/routes/escalations/index.js +3 -0
- package/build/routes/escalations/resolve.js +8 -1
- package/build/routes/escalations/single.js +13 -4
- package/build/routes/roles.js +1 -1
- package/build/routes/scan-codes.js +28 -2
- package/build/scripts/ortho-populate.js +14 -0
- package/build/scripts/printer-cycle.d.ts +25 -0
- package/build/scripts/printer-cycle.js +169 -0
- package/build/scripts/twin-farm.js +19 -5
- package/build/sdk/index.d.ts +2 -0
- package/build/sdk/index.js +3 -0
- package/build/services/escalation/aggregate-sql.d.ts +36 -0
- package/build/services/escalation/aggregate-sql.js +253 -0
- package/build/services/escalation/aggregate-validate.d.ts +57 -0
- package/build/services/escalation/aggregate-validate.js +218 -0
- package/build/services/escalation/aggregates.d.ts +26 -0
- package/build/services/escalation/aggregates.js +204 -0
- package/build/services/escalation/client.js +57 -21
- package/build/services/escalation/facet-sql.js +17 -0
- package/build/services/escalation/index.d.ts +2 -0
- package/build/services/escalation/index.js +8 -1
- package/build/services/escalation/metrics-cache.d.ts +18 -0
- package/build/services/escalation/metrics-cache.js +47 -1
- package/build/services/escalation/queries.js +2 -0
- package/build/services/iam/acting-identity.d.ts +16 -0
- package/build/services/iam/acting-identity.js +60 -0
- package/build/services/role/index.js +2 -0
- package/build/services/role/sql.d.ts +10 -2
- package/build/services/role/sql.js +14 -1
- package/build/services/role/types.d.ts +16 -0
- package/build/services/scan-code/read.js +4 -0
- package/build/services/scan-code/sql.d.ts +4 -4
- package/build/services/scan-code/sql.js +14 -8
- package/build/services/scan-code/validate.d.ts +2 -0
- package/build/services/scan-code/validate.js +86 -0
- package/build/services/scan-code/write.d.ts +4 -0
- package/build/services/scan-code/write.js +16 -2
- package/build/services/user/crud.d.ts +6 -0
- package/build/services/user/crud.js +16 -0
- package/build/services/user/index.d.ts +1 -1
- package/build/services/user/index.js +2 -1
- package/build/services/user/sql.d.ts +8 -0
- package/build/services/user/sql.js +9 -1
- package/build/system/mcp-servers/admin/escalations.js +34 -0
- package/build/system/mcp-servers/admin/scan-codes.js +17 -1
- package/build/system/mcp-servers/admin/schemas.d.ts +643 -25
- package/build/system/mcp-servers/admin/schemas.js +127 -19
- package/build/system/mcp-servers/admin/users.js +3 -1
- package/build/system/mcp-servers/human-queue-schemas.d.ts +2 -2
- package/build/system/seed/tool-manifests-admin.d.ts +2283 -0
- package/build/system/seed/tool-manifests-admin.js +8 -5
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/analytics.d.ts +154 -0
- package/build/types/analytics.js +14 -0
- package/build/types/facets.d.ts +13 -0
- package/build/types/index.d.ts +5 -2
- package/build/types/index.js +5 -1
- package/build/types/scan-choice.d.ts +49 -0
- package/build/types/scan-choice.js +9 -0
- package/build/types/scan-code.d.ts +72 -1
- package/build/types/scan-code.js +30 -1
- package/dashboard/dist/assets/{AdminDashboard-Chg69wlx.js → AdminDashboard-DJ3LJQ09.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-Chg69wlx.js.map → AdminDashboard-DJ3LJQ09.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-DRTFwbfC.js → AgentConfigPage-BMMvaD0z.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-DRTFwbfC.js.map → AgentConfigPage-BMMvaD0z.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-JKByfFIi.js → AgentDetailPage-C6wfsnRe.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-JKByfFIi.js.map → AgentDetailPage-C6wfsnRe.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-BlgEmKhA.js → AgentsPage-Cwqka7nE.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-BlgEmKhA.js.map → AgentsPage-Cwqka7nE.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-CVlG_AVC.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-CVlG_AVC.js.map +1 -0
- package/dashboard/dist/assets/{BotPicker-CCVcz4Cq.js → BotPicker-BBkJBXZB.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-CCVcz4Cq.js.map → BotPicker-BBkJBXZB.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-Czi9jUwD.js → CapabilitiesPage-wxmE4917.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-Czi9jUwD.js.map → CapabilitiesPage-wxmE4917.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-8YE965QX.js → CollapsibleSection-B3FsrHwH.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-8YE965QX.js.map → CollapsibleSection-B3FsrHwH.js.map} +1 -1
- package/dashboard/dist/assets/{CountdownTimer-Bxvq3D7j.js → CountdownTimer-B3nCqJdC.js} +2 -2
- package/dashboard/dist/assets/{CountdownTimer-Bxvq3D7j.js.map → CountdownTimer-B3nCqJdC.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-Bn7_SX6-.js → CredentialsPage-Bv875IHe.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-Bn7_SX6-.js.map → CredentialsPage-Bv875IHe.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-Bn4mX_Yn.js → CronLabel-CSzjWuwj.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-Bn4mX_Yn.js.map → CronLabel-CSzjWuwj.js.map} +1 -1
- package/dashboard/dist/assets/{CustomDurationPicker-pMcrFyW6.js → CustomDurationPicker-CCpqf3e4.js} +2 -2
- package/dashboard/dist/assets/{CustomDurationPicker-pMcrFyW6.js.map → CustomDurationPicker-CCpqf3e4.js.map} +1 -1
- package/dashboard/dist/assets/{DropZone-zCEGjjk-.js → DropZone-CJkk-U3o.js} +2 -2
- package/dashboard/dist/assets/{DropZone-zCEGjjk-.js.map → DropZone-CJkk-U3o.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-BGO7IXEg.js → ElapsedCell-WV6pUaKo.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-BGO7IXEg.js.map → ElapsedCell-WV6pUaKo.js.map} +1 -1
- package/dashboard/dist/assets/EntityTimelinePanel-DrL86Yrf.js +2 -0
- package/dashboard/dist/assets/EntityTimelinePanel-DrL86Yrf.js.map +1 -0
- package/dashboard/dist/assets/{EscalationListSchemaPage-CFDxbd50.js → EscalationListSchemaPage-CTQCALw4.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-CFDxbd50.js.map → EscalationListSchemaPage-CTQCALw4.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-DnXPnDkz.js → EscalationSchemaPage-D_UgP0pv.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-DnXPnDkz.js.map → EscalationSchemaPage-D_UgP0pv.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-BZMVXrkK.js → EscalationsOverview-DuIUyxr0.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-BZMVXrkK.js.map → EscalationsOverview-DuIUyxr0.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-Bfi-f8as.js → EventTable-BV6unphX.js} +2 -2
- package/dashboard/dist/assets/{EventTable-Bfi-f8as.js.map → EventTable-BV6unphX.js.map} +1 -1
- package/dashboard/dist/assets/FilterBar-DYFgzXNB.js +2 -0
- package/dashboard/dist/assets/{FilterBar-Do7yR4xM.js.map → FilterBar-DYFgzXNB.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-d1ie4T7f.js → GraphInvokePage-BGHVUipJ.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-d1ie4T7f.js.map → GraphInvokePage-BGHVUipJ.js.map} +1 -1
- package/dashboard/dist/assets/HomePage-B-S2cK3E.js +2 -0
- package/dashboard/dist/assets/{HomePage-BEeodImU.js.map → HomePage-B-S2cK3E.js.map} +1 -1
- package/dashboard/dist/assets/ListToolbar-Bl7F3A28.js +2 -0
- package/dashboard/dist/assets/{ListToolbar-CLtw-1QN.js.map → ListToolbar-Bl7F3A28.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-DIsy9TB3.js → McpOverview-_T9IsCD_.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-DIsy9TB3.js.map → McpOverview-_T9IsCD_.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-6PomdsyD.js → McpQueryDetailPage-DtsVqKPw.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-6PomdsyD.js.map → McpQueryDetailPage-DtsVqKPw.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-YMdQCXm9.js → McpQueryPage-DX5u-1bx.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-YMdQCXm9.js.map → McpQueryPage-DX5u-1bx.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-DsD1Gm2o.js → McpRunDetailPage-BhcqqtYS.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-DsD1Gm2o.js.map → McpRunDetailPage-BhcqqtYS.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage--a5Jgb33.js → McpRunsPage-L-1y8wnX.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage--a5Jgb33.js.map → McpRunsPage-L-1y8wnX.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-wV6L4VW1.js → NamespacePill-in1SLd0W.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-wV6L4VW1.js.map → NamespacePill-in1SLd0W.js.map} +1 -1
- package/dashboard/dist/assets/OperationsPage-i8KcDpKo.js +3 -0
- package/dashboard/dist/assets/OperationsPage-i8KcDpKo.js.map +1 -0
- package/dashboard/dist/assets/OperatorDashboard-CIbDzOlh.js +2 -0
- package/dashboard/dist/assets/{OperatorDashboard-CkLfbxEh.js.map → OperatorDashboard-CIbDzOlh.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-BtIr6r-8.js → PageHeader-BJgWMZtw.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-BtIr6r-8.js.map → PageHeader-BJgWMZtw.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-C2sGqFQG.js → PageHeaderWithStats-Ccio4vyG.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-C2sGqFQG.js.map → PageHeaderWithStats-Ccio4vyG.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-CCmOgKQb.js → PersonaDetailPage-BOaf0TW1.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-CCmOgKQb.js.map → PersonaDetailPage-BOaf0TW1.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-BJkSuDTN.js → PersonasPage-DSdRb90f.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-BJkSuDTN.js.map → PersonasPage-DSdRb90f.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-DT9BlJXK.js → ProcessDetailPage-DN9NqfeP.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-DT9BlJXK.js.map → ProcessDetailPage-DN9NqfeP.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-DgSGzTDT.js → ProcessesListPage-CfQEWaD4.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-DgSGzTDT.js.map → ProcessesListPage-CfQEWaD4.js.map} +1 -1
- package/dashboard/dist/assets/RoleDetailPage-BC5HL7ls.js +8 -0
- package/dashboard/dist/assets/RoleDetailPage-BC5HL7ls.js.map +1 -0
- package/dashboard/dist/assets/{RolePill-BBYjhAPj.js → RolePill-BNAP-uK6.js} +2 -2
- package/dashboard/dist/assets/{RolePill-BBYjhAPj.js.map → RolePill-BNAP-uK6.js.map} +1 -1
- package/dashboard/dist/assets/RolesPage-DCnW0VmD.js +2 -0
- package/dashboard/dist/assets/RolesPage-DCnW0VmD.js.map +1 -0
- package/dashboard/dist/assets/{RunAsSelector-CateuvcC.js → RunAsSelector-twbuX7fB.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-CateuvcC.js.map → RunAsSelector-twbuX7fB.js.map} +1 -1
- package/dashboard/dist/assets/ScanCodesPage-CPNg6K--.js +2 -0
- package/dashboard/dist/assets/ScanCodesPage-CPNg6K--.js.map +1 -0
- package/dashboard/dist/assets/ScanSchemeDetailPage-DyLmCamO.js +2 -0
- package/dashboard/dist/assets/ScanSchemeDetailPage-DyLmCamO.js.map +1 -0
- package/dashboard/dist/assets/ScanStationPage-DoZccU5B.js +2 -0
- package/dashboard/dist/assets/ScanStationPage-DoZccU5B.js.map +1 -0
- package/dashboard/dist/assets/{ScopeBadge-xs2Nhjy4.js → ScopeBadge-BG7KkZ8Q.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-xs2Nhjy4.js.map → ScopeBadge-BG7KkZ8Q.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-Cg-QdYWL.js → StickyPagination-DIeYMPPd.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-Cg-QdYWL.js.map → StickyPagination-DIeYMPPd.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-DEeuh4_-.js → StreamMessageDetail-gU4CUeQI.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-DEeuh4_-.js.map → StreamMessageDetail-gU4CUeQI.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-DMY0jL2F.js → SwimlaneTimeline-Br-nBA4l.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-DMY0jL2F.js.map → SwimlaneTimeline-Br-nBA4l.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-BMmiV-MD.js → TagInput-CvM5n6ww.js} +2 -2
- package/dashboard/dist/assets/{TagInput-BMmiV-MD.js.map → TagInput-CvM5n6ww.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-CPbkIvfF.js → TaskDetailPage-_9cr_R0u.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-CPbkIvfF.js.map → TaskDetailPage-_9cr_R0u.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-DLgYaw1x.js → TaskQueuePill-D4JPHXOq.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-DLgYaw1x.js.map → TaskQueuePill-D4JPHXOq.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-CtHudKhQ.js → TasksListPage-DVENC9Jp.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-CtHudKhQ.js.map → TasksListPage-DVENC9Jp.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-BdHOizWg.js → TimeAgo-C9yYnOui.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-BdHOizWg.js.map → TimeAgo-C9yYnOui.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-FVukzKRe.js → TimestampCell-DoB8cYgw.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-FVukzKRe.js.map → TimestampCell-DoB8cYgw.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-BvS53hxP.js → ToolPill-BUjbC-Tj.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-BvS53hxP.js.map → ToolPill-BUjbC-Tj.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-HN0OCYTL.js → ToolTestPanel-CBtsIP8K.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-HN0OCYTL.js.map → ToolTestPanel-CBtsIP8K.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-DHdSpN61.js → TopicDetailPage-mR4Jaz83.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-DHdSpN61.js.map → TopicDetailPage-mR4Jaz83.js.map} +1 -1
- package/dashboard/dist/assets/TopicsPage-CP7HFxIC.js +2 -0
- package/dashboard/dist/assets/{TopicsPage-Clr6Tl5P.js.map → TopicsPage-CP7HFxIC.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-BUVYyIAS.js → UserName-BnLF6yhz.js} +2 -2
- package/dashboard/dist/assets/{UserName-BUVYyIAS.js.map → UserName-BnLF6yhz.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-kncWFfe5.js → WorkflowExecutionPage-xL956RZi.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-kncWFfe5.js.map → WorkflowExecutionPage-xL956RZi.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill-BPC_Dc_I.js → WorkflowPill-tXU0-eXu.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-BPC_Dc_I.js.map → WorkflowPill-tXU0-eXu.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-4ypPDGKx.js → WorkflowsDashboard-B-u7zFKM.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-4ypPDGKx.js.map → WorkflowsDashboard-B-u7zFKM.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-CeQlZkkd.js → WorkflowsOverview-CqZVarK-.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-CeQlZkkd.js.map → WorkflowsOverview-CqZVarK-.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-DLAlEzwT.js → YamlWorkflowDetailPage-DiFLavW0.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-DLAlEzwT.js.map → YamlWorkflowDetailPage-DiFLavW0.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-DQhenKFT.js → YamlWorkflowsPage-BuQM6uZA.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-DQhenKFT.js.map → YamlWorkflowsPage-BuQM6uZA.js.map} +1 -1
- package/dashboard/dist/assets/{agents-s3feet3W.js → agents-DU9GPovp.js} +2 -2
- package/dashboard/dist/assets/{agents-s3feet3W.js.map → agents-DU9GPovp.js.map} +1 -1
- package/dashboard/dist/assets/{bots-CkSd2rn9.js → bots-Cy-Hmg7w.js} +2 -2
- package/dashboard/dist/assets/{bots-CkSd2rn9.js.map → bots-Cy-Hmg7w.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-DA_r09tM.js → capabilities-sSJJqrp-.js} +2 -2
- package/dashboard/dist/assets/{capabilities-DA_r09tM.js.map → capabilities-sSJJqrp-.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-C9c25q21.js → controlplane-TVCjDHQ-.js} +2 -2
- package/dashboard/dist/assets/{controlplane-C9c25q21.js.map → controlplane-TVCjDHQ-.js.map} +1 -1
- package/dashboard/dist/assets/escalation-columns-BpkjKYGd.js +2 -0
- package/dashboard/dist/assets/escalation-columns-BpkjKYGd.js.map +1 -0
- package/dashboard/dist/assets/index-5TblaCXQ.css +1 -0
- package/dashboard/dist/assets/{index-WxE3ONia.js → index-7BP6FaCZ.js} +2 -2
- package/dashboard/dist/assets/{index-WxE3ONia.js.map → index-7BP6FaCZ.js.map} +1 -1
- package/dashboard/dist/assets/{index-C7ABSOU2.js → index-B7IaBPBg.js} +4 -4
- package/dashboard/dist/assets/{index-C7ABSOU2.js.map → index-B7IaBPBg.js.map} +1 -1
- package/dashboard/dist/assets/{index-BU5FFAJo.js → index-BE0phFw0.js} +2 -2
- package/dashboard/dist/assets/{index-BU5FFAJo.js.map → index-BE0phFw0.js.map} +1 -1
- package/dashboard/dist/assets/{index-C-MmR-jf.js → index-BYNN9N1T.js} +2 -2
- package/dashboard/dist/assets/{index-C-MmR-jf.js.map → index-BYNN9N1T.js.map} +1 -1
- package/dashboard/dist/assets/{index-S13oPvuS.js → index-CLPVqbVY.js} +2 -2
- package/dashboard/dist/assets/{index-S13oPvuS.js.map → index-CLPVqbVY.js.map} +1 -1
- package/dashboard/dist/assets/{index-Cw9poaez.js → index-Cfv86_L9.js} +2 -2
- package/dashboard/dist/assets/{index-Cw9poaez.js.map → index-Cfv86_L9.js.map} +1 -1
- package/dashboard/dist/assets/{index-Bo5TtX9l.js → index-CtwbQ_-m.js} +2 -2
- package/dashboard/dist/assets/{index-Bo5TtX9l.js.map → index-CtwbQ_-m.js.map} +1 -1
- package/dashboard/dist/assets/index-DOai950R.js +3 -0
- package/dashboard/dist/assets/index-DOai950R.js.map +1 -0
- package/dashboard/dist/assets/{index-Cmxzk4ay.js → index-DTtHNC-D.js} +2 -2
- package/dashboard/dist/assets/{index-Cmxzk4ay.js.map → index-DTtHNC-D.js.map} +1 -1
- package/dashboard/dist/assets/{index--7Vdkzwd.js → index-DsWnVyVN.js} +2 -2
- package/dashboard/dist/assets/{index--7Vdkzwd.js.map → index-DsWnVyVN.js.map} +1 -1
- package/dashboard/dist/assets/{index-DvoMXQqO.js → index-Dy-MMYti.js} +2 -2
- package/dashboard/dist/assets/{index-DvoMXQqO.js.map → index-Dy-MMYti.js.map} +1 -1
- package/dashboard/dist/assets/index-errgQT5x.js +65 -0
- package/dashboard/dist/assets/index-errgQT5x.js.map +1 -0
- package/dashboard/dist/assets/{index-BIcYbDVf.js → index-fgBDhnI6.js} +2 -2
- package/dashboard/dist/assets/{index-BIcYbDVf.js.map → index-fgBDhnI6.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-Bpln0zy_.js → knowledge-arh4NfmL.js} +2 -2
- package/dashboard/dist/assets/{knowledge-Bpln0zy_.js.map → knowledge-arh4NfmL.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-BqDq3RZH.js → mcp-QGf5jHCo.js} +2 -2
- package/dashboard/dist/assets/{mcp-BqDq3RZH.js.map → mcp-QGf5jHCo.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-DGue75R6.js → mcp-query-BEJN1nMZ.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-DGue75R6.js.map → mcp-query-BEJN1nMZ.js.map} +1 -1
- package/dashboard/dist/assets/{personas-B8z_sTiJ.js → personas-DYtw1COf.js} +2 -2
- package/dashboard/dist/assets/{personas-B8z_sTiJ.js.map → personas-DYtw1COf.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-DYgNd9nB.js → pipelines-Byi6PnbE.js} +2 -2
- package/dashboard/dist/assets/{pipelines-DYgNd9nB.js.map → pipelines-Byi6PnbE.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-CJdjjhgO.js → tasks-D0SQdENz.js} +2 -2
- package/dashboard/dist/assets/{tasks-CJdjjhgO.js.map → tasks-D0SQdENz.js.map} +1 -1
- package/dashboard/dist/assets/{topics-DPrL8Dtq.js → topics-DgDv5ZXP.js} +2 -2
- package/dashboard/dist/assets/{topics-DPrL8Dtq.js.map → topics-DgDv5ZXP.js.map} +1 -1
- package/dashboard/dist/assets/useEventHooks-DZaYzE7s.js +2 -0
- package/dashboard/dist/assets/{useEventHooks-DXCgDgiu.js.map → useEventHooks-DZaYzE7s.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-DnFZfy7N.js → useNamespace-C1OqiNXN.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-DnFZfy7N.js.map → useNamespace-C1OqiNXN.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-kx5CLENv.js → useYamlActivityEvents-CkmXDm-Z.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-kx5CLENv.js.map → useYamlActivityEvents-CkmXDm-Z.js.map} +1 -1
- package/dashboard/dist/assets/{users-DKng7vAG.js → users-D4DCFPH1.js} +2 -2
- package/dashboard/dist/assets/{users-DKng7vAG.js.map → users-D4DCFPH1.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-CN-bAo9U.js → vendor-icons-BxuyFxH2.js} +152 -137
- package/dashboard/dist/assets/vendor-icons-BxuyFxH2.js.map +1 -0
- package/dashboard/dist/assets/{workflows-C4V0rMkM.js → workflows-qyc0ku_5.js} +2 -2
- package/dashboard/dist/assets/{workflows-C4V0rMkM.js.map → workflows-qyc0ku_5.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-D3PAiJ9d.js → yaml-workflows-DWFww9Xn.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-D3PAiJ9d.js.map → yaml-workflows-DWFww9Xn.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/api/http/escalations.md +133 -0
- package/docs/api/http/roles.md +6 -0
- package/docs/api/mcp/admin.md +53 -0
- package/docs/api/sdk/escalations.md +58 -0
- package/docs/cli.md +11 -0
- package/docs/dashboard.md +22 -20
- package/docs/data.md +12 -4
- package/docs/escalation-analytics.md +251 -0
- package/docs/hitl/roles.md +1 -1
- package/docs/hitl/x-lt-footer.md +1 -2
- package/docs/hitl-guide.md +3 -3
- package/docs/iam.md +12 -0
- package/docs/operations.md +17 -0
- package/docs/scan-codes.md +112 -0
- package/docs/sdk.md +1 -1
- package/package.json +2 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-C_7y692Q.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-C_7y692Q.js.map +0 -1
- package/dashboard/dist/assets/FilterBar-Do7yR4xM.js +0 -2
- package/dashboard/dist/assets/HomePage-BEeodImU.js +0 -2
- package/dashboard/dist/assets/ListToolbar-CLtw-1QN.js +0 -2
- package/dashboard/dist/assets/OperationsPage-B2v9k3DT.js +0 -2
- package/dashboard/dist/assets/OperationsPage-B2v9k3DT.js.map +0 -1
- package/dashboard/dist/assets/OperatorDashboard-CkLfbxEh.js +0 -2
- package/dashboard/dist/assets/RoleDetailPage-DMphTvro.js +0 -8
- package/dashboard/dist/assets/RoleDetailPage-DMphTvro.js.map +0 -1
- package/dashboard/dist/assets/RolesPage-gi_kaot1.js +0 -2
- package/dashboard/dist/assets/RolesPage-gi_kaot1.js.map +0 -1
- package/dashboard/dist/assets/ScanCodesPage-CQ8RxMug.js +0 -2
- package/dashboard/dist/assets/ScanCodesPage-CQ8RxMug.js.map +0 -1
- package/dashboard/dist/assets/ScanSchemeDetailPage-puSbuxcV.js +0 -2
- package/dashboard/dist/assets/ScanSchemeDetailPage-puSbuxcV.js.map +0 -1
- package/dashboard/dist/assets/TopicsPage-Clr6Tl5P.js +0 -2
- package/dashboard/dist/assets/escalation-columns-Cp3UrT48.js +0 -2
- package/dashboard/dist/assets/escalation-columns-Cp3UrT48.js.map +0 -1
- package/dashboard/dist/assets/index--DG-qQBT.js +0 -65
- package/dashboard/dist/assets/index--DG-qQBT.js.map +0 -1
- package/dashboard/dist/assets/index-DEbY57_c.js +0 -3
- package/dashboard/dist/assets/index-DEbY57_c.js.map +0 -1
- package/dashboard/dist/assets/index-DnV6LSeY.css +0 -1
- package/dashboard/dist/assets/useEventHooks-DXCgDgiu.js +0 -2
- package/dashboard/dist/assets/vendor-icons-CN-bAo9U.js.map +0 -1
|
@@ -84,6 +84,14 @@ exports.DELETE_ROLE = `
|
|
|
84
84
|
* ops_home_default ($35 = provided sentinel, $36 = value) is single-holder:
|
|
85
85
|
* setting it true clears the flag on every other role in the same statement
|
|
86
86
|
* (the home_clear CTE touches only OTHER rows, so the two UPDATEs never meet).
|
|
87
|
+
*
|
|
88
|
+
* entity_facet ($37 = provided sentinel, $38 = value) is unversioned config:
|
|
89
|
+
* the metadata key naming the entity that moves through this role (powers the
|
|
90
|
+
* analytics surfaces — entity counts, per-entity dwell, timelines).
|
|
91
|
+
*
|
|
92
|
+
* entity_state_source ($39 = provided sentinel, $40 = value) is unversioned
|
|
93
|
+
* config: 'role' | 'subtype' — how this role names its contribution to the
|
|
94
|
+
* entity's state space (the station itself, or its subtypes).
|
|
87
95
|
*/
|
|
88
96
|
exports.UPDATE_ROLE_METADATA = `
|
|
89
97
|
WITH home_clear AS (
|
|
@@ -104,6 +112,9 @@ exports.UPDATE_ROLE_METADATA = `
|
|
|
104
112
|
priority_threshold_minutes
|
|
105
113
|
= CASE WHEN $22::boolean THEN $23::numeric ELSE priority_threshold_minutes END,
|
|
106
114
|
priority_facet = CASE WHEN $24::boolean THEN $25 ELSE priority_facet END,
|
|
115
|
+
entity_facet = CASE WHEN $37::boolean THEN $38 ELSE entity_facet END,
|
|
116
|
+
entity_state_source
|
|
117
|
+
= CASE WHEN $39::boolean THEN COALESCE($40, 'role') ELSE entity_state_source END,
|
|
107
118
|
list_schema = CASE WHEN $29::boolean THEN $30::jsonb ELSE list_schema END,
|
|
108
119
|
default_pins = CASE WHEN $31::boolean THEN $32::jsonb ELSE default_pins END,
|
|
109
120
|
enforce_schema = CASE WHEN $33::boolean THEN COALESCE($34::boolean, false) ELSE enforce_schema END,
|
|
@@ -121,7 +132,7 @@ exports.UPDATE_ROLE_METADATA = `
|
|
|
121
132
|
RETURNING
|
|
122
133
|
role, title, description, form_schema, metadata_schema, properties,
|
|
123
134
|
ops_visible, ops_home_default, parent_role, sla_minutes, target_per_hour, worker_count,
|
|
124
|
-
priority_threshold_minutes, priority_facet,
|
|
135
|
+
priority_threshold_minutes, priority_facet, entity_facet, entity_state_source,
|
|
125
136
|
current_schema_version, list_schema, current_list_schema_version,
|
|
126
137
|
default_pins, enforce_schema
|
|
127
138
|
), snapshot AS (
|
|
@@ -262,6 +273,8 @@ exports.LIST_ROLES_WITH_DETAILS = `
|
|
|
262
273
|
r.worker_count,
|
|
263
274
|
r.priority_threshold_minutes,
|
|
264
275
|
r.priority_facet,
|
|
276
|
+
r.entity_facet,
|
|
277
|
+
r.entity_state_source,
|
|
265
278
|
r.current_schema_version,
|
|
266
279
|
r.list_schema,
|
|
267
280
|
r.current_list_schema_version,
|
|
@@ -46,6 +46,19 @@ export interface RoleDetail {
|
|
|
46
46
|
* an unparseable value are not counted.
|
|
47
47
|
*/
|
|
48
48
|
priority_facet: string | null;
|
|
49
|
+
/**
|
|
50
|
+
* lt_escalations.metadata key identifying the ENTITY that moves through
|
|
51
|
+
* this role (e.g. serialNumber, orderId). Powers the analytics surfaces —
|
|
52
|
+
* distinct-entity counts, per-entity dwell, entity timelines. Null = the
|
|
53
|
+
* role has no entity notion.
|
|
54
|
+
*/
|
|
55
|
+
entity_facet: string | null;
|
|
56
|
+
/**
|
|
57
|
+
* How this role names its contribution to the entity's state space:
|
|
58
|
+
* 'role' (the station itself is the state) or 'subtype' (the role's
|
|
59
|
+
* subtypes are its states). Only meaningful while entity_facet is set.
|
|
60
|
+
*/
|
|
61
|
+
entity_state_source: 'role' | 'subtype';
|
|
49
62
|
/**
|
|
50
63
|
* Version of the live form_schema. Advances whenever the form (or
|
|
51
64
|
* metadata_schema) changes; each version is snapshotted in lt_role_schemas so
|
|
@@ -149,6 +162,9 @@ export interface UpdateRoleInput {
|
|
|
149
162
|
worker_count?: number | null;
|
|
150
163
|
priority_threshold_minutes?: number | null;
|
|
151
164
|
priority_facet?: string | null;
|
|
165
|
+
entity_facet?: string | null;
|
|
166
|
+
/** 'role' | 'subtype' — null resets to the 'role' default. */
|
|
167
|
+
entity_state_source?: 'role' | 'subtype' | null;
|
|
152
168
|
/** Turn server-side resolver schema validation on/off for this role. */
|
|
153
169
|
enforce_schema?: boolean;
|
|
154
170
|
/**
|
|
@@ -15,6 +15,9 @@ function mapScheme(row) {
|
|
|
15
15
|
encoding: row.encoding,
|
|
16
16
|
delimiter: row.delimiter,
|
|
17
17
|
target_length: row.target_length ?? null,
|
|
18
|
+
kind: row.kind ?? 'action',
|
|
19
|
+
grant_ttl_seconds: row.grant_ttl_seconds ?? null,
|
|
20
|
+
grant_max_uses: row.grant_max_uses ?? 0,
|
|
18
21
|
enabled: row.enabled,
|
|
19
22
|
created_at: row.created_at,
|
|
20
23
|
updated_at: row.updated_at,
|
|
@@ -27,6 +30,7 @@ function mapRule(row) {
|
|
|
27
30
|
name: row.name,
|
|
28
31
|
steps: row.steps ?? [],
|
|
29
32
|
fallback: row.fallback ?? {},
|
|
33
|
+
notPrimed: row.not_primed ?? {},
|
|
30
34
|
enabled: row.enabled,
|
|
31
35
|
created_at: row.created_at,
|
|
32
36
|
updated_at: row.updated_at,
|
|
@@ -2,9 +2,9 @@ export declare const LIST_SCHEMES = "SELECT * FROM lt_config_scan_schemes ORDER
|
|
|
2
2
|
export declare const GET_SCHEME = "SELECT * FROM lt_config_scan_schemes WHERE version = $1";
|
|
3
3
|
export declare const LIST_ACTIONS = "SELECT * FROM lt_config_scan_actions WHERE scheme_version = $1 ORDER BY category";
|
|
4
4
|
export declare const GET_ACTION = "SELECT * FROM lt_config_scan_actions WHERE scheme_version = $1 AND category = $2";
|
|
5
|
-
export declare const UPSERT_SCHEME = "INSERT INTO lt_config_scan_schemes\n (version, name, description, target_facet, encoding, delimiter, target_length, enabled)\nVALUES ($1, $2, $3, $4, $5, $6, $7, $8)\nON CONFLICT (version) DO UPDATE SET\n name = EXCLUDED.name,\n description = EXCLUDED.description,\n target_facet = EXCLUDED.target_facet,\n encoding = EXCLUDED.encoding,\n delimiter = EXCLUDED.delimiter,\n target_length = EXCLUDED.target_length,\n enabled = EXCLUDED.enabled\nRETURNING *";
|
|
5
|
+
export declare const UPSERT_SCHEME = "INSERT INTO lt_config_scan_schemes\n (version, name, description, target_facet, encoding, delimiter, target_length,\n kind, grant_ttl_seconds, grant_max_uses, enabled)\nVALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)\nON CONFLICT (version) DO UPDATE SET\n name = EXCLUDED.name,\n description = EXCLUDED.description,\n target_facet = EXCLUDED.target_facet,\n encoding = EXCLUDED.encoding,\n delimiter = EXCLUDED.delimiter,\n target_length = EXCLUDED.target_length,\n kind = EXCLUDED.kind,\n grant_ttl_seconds = EXCLUDED.grant_ttl_seconds,\n grant_max_uses = EXCLUDED.grant_max_uses,\n enabled = EXCLUDED.enabled\nRETURNING *";
|
|
6
6
|
export declare const DELETE_SCHEME = "DELETE FROM lt_config_scan_schemes WHERE version = $1";
|
|
7
|
-
export declare const UPSERT_ACTION = "INSERT INTO lt_config_scan_actions\n (scheme_version, category, name, steps, fallback, enabled)\nVALUES ($1, $2, $3, $4, $5, $6)\nON CONFLICT (scheme_version, category) DO UPDATE SET\n name = EXCLUDED.name,\n steps = EXCLUDED.steps,\n fallback = EXCLUDED.fallback,\n enabled = EXCLUDED.enabled\nRETURNING *";
|
|
7
|
+
export declare const UPSERT_ACTION = "INSERT INTO lt_config_scan_actions\n (scheme_version, category, name, steps, fallback, not_primed, enabled)\nVALUES ($1, $2, $3, $4, $5, $6, $7)\nON CONFLICT (scheme_version, category) DO UPDATE SET\n name = EXCLUDED.name,\n steps = EXCLUDED.steps,\n fallback = EXCLUDED.fallback,\n not_primed = EXCLUDED.not_primed,\n enabled = EXCLUDED.enabled\nRETURNING *";
|
|
8
8
|
export declare const DELETE_ACTION = "DELETE FROM lt_config_scan_actions WHERE scheme_version = $1 AND category = $2";
|
|
9
|
-
export declare const SEED_SCHEME = "INSERT INTO lt_config_scan_schemes\n (version, name, description, target_facet, encoding, delimiter, target_length, enabled)\nVALUES ($1, $2, $3, $4, $5, $6, $7, $8)\nON CONFLICT (version) DO NOTHING";
|
|
10
|
-
export declare const SEED_ACTION = "INSERT INTO lt_config_scan_actions\n (scheme_version, category, name, steps, fallback, enabled)\nVALUES ($1, $2, $3, $4, $5, $6)\nON CONFLICT (scheme_version, category) DO NOTHING";
|
|
9
|
+
export declare const SEED_SCHEME = "INSERT INTO lt_config_scan_schemes\n (version, name, description, target_facet, encoding, delimiter, target_length,\n kind, grant_ttl_seconds, grant_max_uses, enabled)\nVALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)\nON CONFLICT (version) DO NOTHING";
|
|
10
|
+
export declare const SEED_ACTION = "INSERT INTO lt_config_scan_actions\n (scheme_version, category, name, steps, fallback, not_primed, enabled)\nVALUES ($1, $2, $3, $4, $5, $6, $7)\nON CONFLICT (scheme_version, category) DO NOTHING";
|
|
@@ -17,8 +17,9 @@ SELECT * FROM lt_config_scan_actions WHERE scheme_version = $1 AND category = $2
|
|
|
17
17
|
// ------------------------------------------------------------------ //
|
|
18
18
|
exports.UPSERT_SCHEME = `\
|
|
19
19
|
INSERT INTO lt_config_scan_schemes
|
|
20
|
-
(version, name, description, target_facet, encoding, delimiter, target_length,
|
|
21
|
-
|
|
20
|
+
(version, name, description, target_facet, encoding, delimiter, target_length,
|
|
21
|
+
kind, grant_ttl_seconds, grant_max_uses, enabled)
|
|
22
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
|
|
22
23
|
ON CONFLICT (version) DO UPDATE SET
|
|
23
24
|
name = EXCLUDED.name,
|
|
24
25
|
description = EXCLUDED.description,
|
|
@@ -26,18 +27,22 @@ ON CONFLICT (version) DO UPDATE SET
|
|
|
26
27
|
encoding = EXCLUDED.encoding,
|
|
27
28
|
delimiter = EXCLUDED.delimiter,
|
|
28
29
|
target_length = EXCLUDED.target_length,
|
|
30
|
+
kind = EXCLUDED.kind,
|
|
31
|
+
grant_ttl_seconds = EXCLUDED.grant_ttl_seconds,
|
|
32
|
+
grant_max_uses = EXCLUDED.grant_max_uses,
|
|
29
33
|
enabled = EXCLUDED.enabled
|
|
30
34
|
RETURNING *`;
|
|
31
35
|
exports.DELETE_SCHEME = `\
|
|
32
36
|
DELETE FROM lt_config_scan_schemes WHERE version = $1`;
|
|
33
37
|
exports.UPSERT_ACTION = `\
|
|
34
38
|
INSERT INTO lt_config_scan_actions
|
|
35
|
-
(scheme_version, category, name, steps, fallback, enabled)
|
|
36
|
-
VALUES ($1, $2, $3, $4, $5, $6)
|
|
39
|
+
(scheme_version, category, name, steps, fallback, not_primed, enabled)
|
|
40
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
37
41
|
ON CONFLICT (scheme_version, category) DO UPDATE SET
|
|
38
42
|
name = EXCLUDED.name,
|
|
39
43
|
steps = EXCLUDED.steps,
|
|
40
44
|
fallback = EXCLUDED.fallback,
|
|
45
|
+
not_primed = EXCLUDED.not_primed,
|
|
41
46
|
enabled = EXCLUDED.enabled
|
|
42
47
|
RETURNING *`;
|
|
43
48
|
exports.DELETE_ACTION = `\
|
|
@@ -47,11 +52,12 @@ DELETE FROM lt_config_scan_actions WHERE scheme_version = $1 AND category = $2`;
|
|
|
47
52
|
// ------------------------------------------------------------------ //
|
|
48
53
|
exports.SEED_SCHEME = `\
|
|
49
54
|
INSERT INTO lt_config_scan_schemes
|
|
50
|
-
(version, name, description, target_facet, encoding, delimiter, target_length,
|
|
51
|
-
|
|
55
|
+
(version, name, description, target_facet, encoding, delimiter, target_length,
|
|
56
|
+
kind, grant_ttl_seconds, grant_max_uses, enabled)
|
|
57
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
|
|
52
58
|
ON CONFLICT (version) DO NOTHING`;
|
|
53
59
|
exports.SEED_ACTION = `\
|
|
54
60
|
INSERT INTO lt_config_scan_actions
|
|
55
|
-
(scheme_version, category, name, steps, fallback, enabled)
|
|
56
|
-
VALUES ($1, $2, $3, $4, $5, $6)
|
|
61
|
+
(scheme_version, category, name, steps, fallback, not_primed, enabled)
|
|
62
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
57
63
|
ON CONFLICT (scheme_version, category) DO NOTHING`;
|
|
@@ -5,6 +5,8 @@ import { type ScanScheme, type ScanStep } from '../../types';
|
|
|
5
5
|
* than a loud upsert failure.
|
|
6
6
|
*/
|
|
7
7
|
export declare function assertValidScheme(scheme: Partial<ScanScheme>): void;
|
|
8
|
+
/** Identity rules never walk steps — their fallback is the unknown-badge screen. */
|
|
9
|
+
export declare function assertValidIdentityRule(steps: ScanStep[]): void;
|
|
8
10
|
/**
|
|
9
11
|
* Reject incoherent rule steps at write time: a rule that can never
|
|
10
12
|
* execute its verb must fail the upsert, not the factory-floor scan.
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.assertValidScheme = assertValidScheme;
|
|
4
|
+
exports.assertValidIdentityRule = assertValidIdentityRule;
|
|
4
5
|
exports.assertValidSteps = assertValidSteps;
|
|
5
6
|
const types_1 = require("../../types");
|
|
6
7
|
const VALID_VERBS = new Set(Object.values(types_1.SCAN_VERBS));
|
|
8
|
+
/** Double-scan selection tokens — short, label-printable, never scheme-shaped. */
|
|
9
|
+
const CHOICE_CODE = /^[A-Za-z0-9_-]{1,32}$/;
|
|
7
10
|
/**
|
|
8
11
|
* Reject incoherent scheme config at write time. Throws with the exact
|
|
9
12
|
* problem — a bad scheme silently misparsing every scan is far worse
|
|
@@ -32,6 +35,64 @@ function assertValidScheme(scheme) {
|
|
|
32
35
|
throw new Error('delimiter must not be a digit');
|
|
33
36
|
}
|
|
34
37
|
}
|
|
38
|
+
const kind = scheme.kind ?? types_1.SCAN_SCHEME_KINDS.ACTION;
|
|
39
|
+
if (kind !== types_1.SCAN_SCHEME_KINDS.ACTION && kind !== types_1.SCAN_SCHEME_KINDS.IDENTITY) {
|
|
40
|
+
throw new Error(`unknown scheme kind "${kind}"`);
|
|
41
|
+
}
|
|
42
|
+
if (kind === types_1.SCAN_SCHEME_KINDS.IDENTITY) {
|
|
43
|
+
const ttl = scheme.grant_ttl_seconds;
|
|
44
|
+
if (!Number.isInteger(ttl) || ttl < 1 || ttl > 86_400) {
|
|
45
|
+
throw new Error('identity schemes require grant_ttl_seconds between 1 and 86400');
|
|
46
|
+
}
|
|
47
|
+
if (!Number.isInteger(scheme.grant_max_uses ?? 0) || (scheme.grant_max_uses ?? 0) < 0) {
|
|
48
|
+
throw new Error('grant_max_uses must be a non-negative integer');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else if (scheme.grant_ttl_seconds != null || (scheme.grant_max_uses ?? 0) !== 0) {
|
|
52
|
+
throw new Error('grant policy applies only to identity schemes');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** Identity rules never walk steps — their fallback is the unknown-badge screen. */
|
|
56
|
+
function assertValidIdentityRule(steps) {
|
|
57
|
+
if (Array.isArray(steps) && steps.length > 0) {
|
|
58
|
+
throw new Error('identity-scheme rules must have no steps (the fallback is the unknown-badge screen)');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/** Per-choice validation — a choice is a step verb with a label, minus locate concerns. */
|
|
62
|
+
function assertValidChoices(choices, at) {
|
|
63
|
+
if (!Array.isArray(choices) || choices.length === 0) {
|
|
64
|
+
throw new Error(`${at}: present requires a non-empty choices array`);
|
|
65
|
+
}
|
|
66
|
+
const codes = new Set();
|
|
67
|
+
choices.forEach((choice, j) => {
|
|
68
|
+
const cat = `${at} choice ${j + 1}`;
|
|
69
|
+
if (!choice || typeof choice !== 'object')
|
|
70
|
+
throw new Error(`${cat} must be an object`);
|
|
71
|
+
if (!choice.label)
|
|
72
|
+
throw new Error(`${cat}: label is required`);
|
|
73
|
+
if (!VALID_VERBS.has(choice.verb))
|
|
74
|
+
throw new Error(`${cat}: unknown verb "${choice.verb}"`);
|
|
75
|
+
if (choice.verb === types_1.SCAN_VERBS.PRESENT || choice.verb === types_1.SCAN_VERBS.SHOW_LIST) {
|
|
76
|
+
throw new Error(`${cat}: ${choice.verb} cannot be a choice verb`);
|
|
77
|
+
}
|
|
78
|
+
if (choice.confirm && !choice.confirm.prompt) {
|
|
79
|
+
throw new Error(`${cat}: confirm requires a prompt`);
|
|
80
|
+
}
|
|
81
|
+
if (choice.verb === types_1.SCAN_VERBS.ESCALATE && !choice.params?.targetRole) {
|
|
82
|
+
throw new Error(`${cat}: escalate requires params.targetRole`);
|
|
83
|
+
}
|
|
84
|
+
if (choice.verb === types_1.SCAN_VERBS.RESOLVE && !choice.params?.resolverPayload) {
|
|
85
|
+
throw new Error(`${cat}: resolve requires params.resolverPayload`);
|
|
86
|
+
}
|
|
87
|
+
if (choice.code !== undefined) {
|
|
88
|
+
if (!CHOICE_CODE.test(choice.code)) {
|
|
89
|
+
throw new Error(`${cat}: code must be 1-32 letters, digits, underscore, or dash`);
|
|
90
|
+
}
|
|
91
|
+
if (codes.has(choice.code))
|
|
92
|
+
throw new Error(`${cat}: duplicate code "${choice.code}"`);
|
|
93
|
+
codes.add(choice.code);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
35
96
|
}
|
|
36
97
|
/**
|
|
37
98
|
* Reject incoherent rule steps at write time: a rule that can never
|
|
@@ -53,6 +114,31 @@ function assertValidSteps(steps) {
|
|
|
53
114
|
if (step.confirm && !step.confirm.prompt) {
|
|
54
115
|
throw new Error(`${at}: confirm requires a prompt`);
|
|
55
116
|
}
|
|
117
|
+
// The classic confirm flow completes through per-id endpoints as the
|
|
118
|
+
// logged-in principal — it cannot carry an acting identity. Identity-gated
|
|
119
|
+
// ask-first flows are authored as PRESENT choices with confirm.
|
|
120
|
+
if (step.confirm && step.requireActingIdentity) {
|
|
121
|
+
throw new Error(`${at}: confirm and requireActingIdentity are incompatible — use a present step with a confirming choice`);
|
|
122
|
+
}
|
|
123
|
+
if (step.verb === types_1.SCAN_VERBS.PRESENT) {
|
|
124
|
+
if (step.confirm)
|
|
125
|
+
throw new Error(`${at}: present steps cannot carry confirm (choices confirm individually)`);
|
|
126
|
+
if (step.cardinality === 'many')
|
|
127
|
+
throw new Error(`${at}: present locates a single row (cardinality first)`);
|
|
128
|
+
assertValidChoices(step.choices, at);
|
|
129
|
+
if (step.autoSelectSingle && step.choices.length !== 1) {
|
|
130
|
+
throw new Error(`${at}: autoSelectSingle requires exactly one choice`);
|
|
131
|
+
}
|
|
132
|
+
if (step.autoSelectSingle && step.choices[0].confirm) {
|
|
133
|
+
throw new Error(`${at}: autoSelectSingle cannot skip a confirming choice — drop the confirm or the auto-select`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
if (step.choices !== undefined)
|
|
138
|
+
throw new Error(`${at}: choices apply only to present steps`);
|
|
139
|
+
if (step.autoSelectSingle)
|
|
140
|
+
throw new Error(`${at}: autoSelectSingle applies only to present steps`);
|
|
141
|
+
}
|
|
56
142
|
if (step.verb === types_1.SCAN_VERBS.ESCALATE && !step.params?.targetRole) {
|
|
57
143
|
throw new Error(`${at}: escalate requires params.targetRole`);
|
|
58
144
|
}
|
|
@@ -7,6 +7,9 @@ export interface ScanSchemeInput {
|
|
|
7
7
|
encoding?: ScanScheme['encoding'];
|
|
8
8
|
delimiter?: string;
|
|
9
9
|
target_length?: number | null;
|
|
10
|
+
kind?: ScanScheme['kind'];
|
|
11
|
+
grant_ttl_seconds?: number | null;
|
|
12
|
+
grant_max_uses?: number;
|
|
10
13
|
enabled?: boolean;
|
|
11
14
|
}
|
|
12
15
|
export interface ScanRuleInput {
|
|
@@ -15,6 +18,7 @@ export interface ScanRuleInput {
|
|
|
15
18
|
name: string;
|
|
16
19
|
steps: ScanStep[];
|
|
17
20
|
fallback?: ScanRuleFallback;
|
|
21
|
+
notPrimed?: ScanRuleFallback;
|
|
18
22
|
enabled?: boolean;
|
|
19
23
|
}
|
|
20
24
|
export declare function upsertScanScheme(input: ScanSchemeInput): Promise<ScanScheme>;
|
|
@@ -10,6 +10,7 @@ const db_1 = require("../../lib/db");
|
|
|
10
10
|
const types_1 = require("../../types");
|
|
11
11
|
const sql_1 = require("./sql");
|
|
12
12
|
const validate_1 = require("./validate");
|
|
13
|
+
const read_1 = require("./read");
|
|
13
14
|
function schemeParams(input) {
|
|
14
15
|
return [
|
|
15
16
|
input.version,
|
|
@@ -19,6 +20,9 @@ function schemeParams(input) {
|
|
|
19
20
|
input.encoding ?? types_1.SCAN_ENCODINGS.FIXED,
|
|
20
21
|
input.delimiter ?? ':',
|
|
21
22
|
input.target_length ?? null,
|
|
23
|
+
input.kind ?? types_1.SCAN_SCHEME_KINDS.ACTION,
|
|
24
|
+
input.grant_ttl_seconds ?? null,
|
|
25
|
+
input.grant_max_uses ?? 0,
|
|
22
26
|
input.enabled ?? true,
|
|
23
27
|
];
|
|
24
28
|
}
|
|
@@ -29,9 +33,19 @@ function ruleParams(input) {
|
|
|
29
33
|
input.name,
|
|
30
34
|
JSON.stringify(input.steps),
|
|
31
35
|
JSON.stringify(input.fallback ?? {}),
|
|
36
|
+
JSON.stringify(input.notPrimed ?? {}),
|
|
32
37
|
input.enabled ?? true,
|
|
33
38
|
];
|
|
34
39
|
}
|
|
40
|
+
/** Identity-scheme rules never walk steps; validated against the OWNING scheme's kind. */
|
|
41
|
+
async function assertStepsForScheme(input) {
|
|
42
|
+
const scheme = await (0, read_1.getScanScheme)(input.scheme_version);
|
|
43
|
+
if (scheme?.kind === types_1.SCAN_SCHEME_KINDS.IDENTITY) {
|
|
44
|
+
(0, validate_1.assertValidIdentityRule)(input.steps);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
(0, validate_1.assertValidSteps)(input.steps);
|
|
48
|
+
}
|
|
35
49
|
async function upsertScanScheme(input) {
|
|
36
50
|
(0, validate_1.assertValidScheme)(input);
|
|
37
51
|
const { rows } = await (0, db_1.getPool)().query(sql_1.UPSERT_SCHEME, schemeParams(input));
|
|
@@ -47,7 +61,7 @@ async function upsertScanRule(input) {
|
|
|
47
61
|
}
|
|
48
62
|
if (!input.name)
|
|
49
63
|
throw new Error('rule name is required');
|
|
50
|
-
|
|
64
|
+
await assertStepsForScheme(input);
|
|
51
65
|
if (input.steps.length === 0 && !input.fallback?.markdown && !input.fallback?.route) {
|
|
52
66
|
throw new Error('a rule needs at least one step or a fallback');
|
|
53
67
|
}
|
|
@@ -65,7 +79,7 @@ async function seedScanScheme(input) {
|
|
|
65
79
|
return (rowCount ?? 0) > 0;
|
|
66
80
|
}
|
|
67
81
|
async function seedScanRule(input) {
|
|
68
|
-
|
|
82
|
+
await assertStepsForScheme(input);
|
|
69
83
|
const { rowCount } = await (0, db_1.getPool)().query(sql_1.SEED_ACTION, ruleParams(input));
|
|
70
84
|
return (rowCount ?? 0) > 0;
|
|
71
85
|
}
|
|
@@ -5,6 +5,12 @@ export declare function createUser(input: CreateUserInput): Promise<LTUserRecord
|
|
|
5
5
|
export declare function getUser(id: string): Promise<LTUserRecord | null>;
|
|
6
6
|
export declare function getUserByExternalId(externalId: string): Promise<LTUserRecord | null>;
|
|
7
7
|
export declare function getUserByEmail(email: string): Promise<LTUserRecord | null>;
|
|
8
|
+
/**
|
|
9
|
+
* Resolve an ACTIVE user by a metadata binding (e.g. metadata.badge_id).
|
|
10
|
+
* Two users carrying the same value is a configuration fault, not a pick —
|
|
11
|
+
* it throws so the binding gets fixed instead of misattributing work.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getUserByMetadataValue(key: string, value: string): Promise<LTUserRecord | null>;
|
|
8
14
|
export declare function updateUser(id: string, input: UpdateUserInput): Promise<LTUserRecord | null>;
|
|
9
15
|
export declare function deleteUser(id: string): Promise<boolean>;
|
|
10
16
|
export declare function listUsers(filters: {
|
|
@@ -8,6 +8,7 @@ exports.createUser = createUser;
|
|
|
8
8
|
exports.getUser = getUser;
|
|
9
9
|
exports.getUserByExternalId = getUserByExternalId;
|
|
10
10
|
exports.getUserByEmail = getUserByEmail;
|
|
11
|
+
exports.getUserByMetadataValue = getUserByMetadataValue;
|
|
11
12
|
exports.updateUser = updateUser;
|
|
12
13
|
exports.deleteUser = deleteUser;
|
|
13
14
|
exports.listUsers = listUsers;
|
|
@@ -93,6 +94,21 @@ async function getUserByEmail(email) {
|
|
|
93
94
|
return null;
|
|
94
95
|
return attachRoles(rows[0]);
|
|
95
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Resolve an ACTIVE user by a metadata binding (e.g. metadata.badge_id).
|
|
99
|
+
* Two users carrying the same value is a configuration fault, not a pick —
|
|
100
|
+
* it throws so the binding gets fixed instead of misattributing work.
|
|
101
|
+
*/
|
|
102
|
+
async function getUserByMetadataValue(key, value) {
|
|
103
|
+
const pool = (0, db_1.getPool)();
|
|
104
|
+
const { rows } = await pool.query(sql_1.GET_USERS_BY_METADATA_VALUE, [key, value]);
|
|
105
|
+
if (rows.length === 0)
|
|
106
|
+
return null;
|
|
107
|
+
if (rows.length > 1) {
|
|
108
|
+
throw new Error(`metadata binding "${key}" is ambiguous — multiple users carry the same value`);
|
|
109
|
+
}
|
|
110
|
+
return attachRoles(rows[0]);
|
|
111
|
+
}
|
|
96
112
|
async function updateUser(id, input) {
|
|
97
113
|
const pool = (0, db_1.getPool)();
|
|
98
114
|
const sets = [];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { CreateUserInput, UpdateUserInput, VALID_ROLE_TYPES } from './types';
|
|
2
|
-
export { createUser, getUser, getUserByExternalId, getUserByEmail, updateUser, deleteUser, listUsers, } from './crud';
|
|
2
|
+
export { createUser, getUser, getUserByExternalId, getUserByEmail, getUserByMetadataValue, updateUser, deleteUser, listUsers, } from './crud';
|
|
3
3
|
export { isValidRoleType, addUserRole, removeUserRole, getUserRoles, hasRole, hasRoleType, } from './roles';
|
|
4
4
|
export { isSuperAdmin, isGroupAdmin, canManageRole, hasGlobalEscalationAccess, hasRolesAsAdmin, getRoleScope, getRoleWriteScope } from './rbac';
|
|
5
5
|
export { READ_SCOPES, WRITE_SCOPES, DEFAULT_READ_SCOPE, DEFAULT_WRITE_SCOPE, isValidReadScope, isValidWriteScope, isValidScopePair, effectiveScope, } from './scope';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PREFERENCES_MAX_BYTES = exports.patchPreferences = exports.getPreferences = exports.seedAdmin = exports.verifyPassword = exports.effectiveScope = exports.isValidScopePair = exports.isValidWriteScope = exports.isValidReadScope = exports.DEFAULT_WRITE_SCOPE = exports.DEFAULT_READ_SCOPE = exports.WRITE_SCOPES = exports.READ_SCOPES = exports.getRoleWriteScope = exports.getRoleScope = exports.hasRolesAsAdmin = exports.hasGlobalEscalationAccess = exports.canManageRole = exports.isGroupAdmin = exports.isSuperAdmin = exports.hasRoleType = exports.hasRole = exports.getUserRoles = exports.removeUserRole = exports.addUserRole = exports.isValidRoleType = exports.listUsers = exports.deleteUser = exports.updateUser = exports.getUserByEmail = exports.getUserByExternalId = exports.getUser = exports.createUser = exports.VALID_ROLE_TYPES = void 0;
|
|
3
|
+
exports.PREFERENCES_MAX_BYTES = exports.patchPreferences = exports.getPreferences = exports.seedAdmin = exports.verifyPassword = exports.effectiveScope = exports.isValidScopePair = exports.isValidWriteScope = exports.isValidReadScope = exports.DEFAULT_WRITE_SCOPE = exports.DEFAULT_READ_SCOPE = exports.WRITE_SCOPES = exports.READ_SCOPES = exports.getRoleWriteScope = exports.getRoleScope = exports.hasRolesAsAdmin = exports.hasGlobalEscalationAccess = exports.canManageRole = exports.isGroupAdmin = exports.isSuperAdmin = exports.hasRoleType = exports.hasRole = exports.getUserRoles = exports.removeUserRole = exports.addUserRole = exports.isValidRoleType = exports.listUsers = exports.deleteUser = exports.updateUser = exports.getUserByMetadataValue = exports.getUserByEmail = exports.getUserByExternalId = exports.getUser = exports.createUser = exports.VALID_ROLE_TYPES = void 0;
|
|
4
4
|
var types_1 = require("./types");
|
|
5
5
|
Object.defineProperty(exports, "VALID_ROLE_TYPES", { enumerable: true, get: function () { return types_1.VALID_ROLE_TYPES; } });
|
|
6
6
|
var crud_1 = require("./crud");
|
|
@@ -8,6 +8,7 @@ Object.defineProperty(exports, "createUser", { enumerable: true, get: function (
|
|
|
8
8
|
Object.defineProperty(exports, "getUser", { enumerable: true, get: function () { return crud_1.getUser; } });
|
|
9
9
|
Object.defineProperty(exports, "getUserByExternalId", { enumerable: true, get: function () { return crud_1.getUserByExternalId; } });
|
|
10
10
|
Object.defineProperty(exports, "getUserByEmail", { enumerable: true, get: function () { return crud_1.getUserByEmail; } });
|
|
11
|
+
Object.defineProperty(exports, "getUserByMetadataValue", { enumerable: true, get: function () { return crud_1.getUserByMetadataValue; } });
|
|
11
12
|
Object.defineProperty(exports, "updateUser", { enumerable: true, get: function () { return crud_1.updateUser; } });
|
|
12
13
|
Object.defineProperty(exports, "deleteUser", { enumerable: true, get: function () { return crud_1.deleteUser; } });
|
|
13
14
|
Object.defineProperty(exports, "listUsers", { enumerable: true, get: function () { return crud_1.listUsers; } });
|
|
@@ -18,6 +18,14 @@ export declare const GET_USER_BY_EXTERNAL_ID = "SELECT * FROM lt_users WHERE ext
|
|
|
18
18
|
export declare const CREATE_USER_WITH_ROLES = "WITH new_user AS (\n INSERT INTO lt_users (external_id, email, display_name, status, metadata, password_hash, oauth_provider, oauth_provider_id)\n VALUES ($1, $2, $3, $4, $5, $6, $7, $8)\n RETURNING *\n ), ensured_roles AS (\n INSERT INTO lt_roles (role)\n SELECT DISTINCT unnest($9::text[])\n ON CONFLICT DO NOTHING\n ), assigned_roles AS (\n INSERT INTO lt_user_roles (user_id, role, type, read_scope, write_scope)\n SELECT (SELECT id FROM new_user), x.role, x.type, x.read_scope, x.write_scope\n FROM unnest($9::text[], $10::text[], $11::text[], $12::text[]) AS x(role, type, read_scope, write_scope)\n ON CONFLICT DO NOTHING\n )\n SELECT * FROM new_user";
|
|
19
19
|
export declare const GET_USER_BY_EMAIL = "SELECT * FROM lt_users WHERE email = $1 LIMIT 1";
|
|
20
20
|
export declare const GET_USER_BY_ID = "SELECT * FROM lt_users WHERE id = $1";
|
|
21
|
+
/**
|
|
22
|
+
* Lookup by a caller-named metadata key (e.g. a badge binding). LIMIT 2 so an
|
|
23
|
+
* ambiguous binding — two users carrying the same value — is detectable and
|
|
24
|
+
* can fail loudly rather than silently picking one. Seq scan by design: this
|
|
25
|
+
* is the people table (small); revisit with a GIN index on metadata if a
|
|
26
|
+
* deployment ever holds tens of thousands of users.
|
|
27
|
+
*/
|
|
28
|
+
export declare const GET_USERS_BY_METADATA_VALUE = "SELECT * FROM lt_users WHERE metadata->>$1 = $2 AND status = 'active' LIMIT 2";
|
|
21
29
|
/** Check if a user exists by id. Lightweight — returns only the id column. */
|
|
22
30
|
export declare const VERIFY_USER_BY_ID = "SELECT id FROM lt_users WHERE id = $1 LIMIT 1";
|
|
23
31
|
/** Fetch user + roles in a single query. Returns one row per role (or one row with nulls if no roles). */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// ─── Shared queries (used by multiple modules) ──────────────────────────────
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.IS_GROUP_ADMIN = exports.GET_ROLE_SCOPE = exports.HAS_ROLE_TYPE = exports.HAS_ROLE = exports.DELETE_USER_ROLE = exports.UPSERT_USER_ROLE = exports.GET_ROLES_BY_USER_IDS = exports.DELETE_USER_BY_ID = exports.GET_USER_WITH_ROLES = exports.VERIFY_USER_BY_ID = exports.GET_USER_BY_ID = exports.GET_USER_BY_EMAIL = exports.CREATE_USER_WITH_ROLES = exports.GET_USER_BY_EXTERNAL_ID = exports.GET_ROLES_BY_USER_ID = exports.ENSURE_ROLE_EXISTS = void 0;
|
|
4
|
+
exports.IS_GROUP_ADMIN = exports.GET_ROLE_SCOPE = exports.HAS_ROLE_TYPE = exports.HAS_ROLE = exports.DELETE_USER_ROLE = exports.UPSERT_USER_ROLE = exports.GET_ROLES_BY_USER_IDS = exports.DELETE_USER_BY_ID = exports.GET_USER_WITH_ROLES = exports.VERIFY_USER_BY_ID = exports.GET_USERS_BY_METADATA_VALUE = exports.GET_USER_BY_ID = exports.GET_USER_BY_EMAIL = exports.CREATE_USER_WITH_ROLES = exports.GET_USER_BY_EXTERNAL_ID = exports.GET_ROLES_BY_USER_ID = exports.ENSURE_ROLE_EXISTS = void 0;
|
|
5
5
|
/** Ensure a role name exists in the lt_roles lookup table (FK target). */
|
|
6
6
|
exports.ENSURE_ROLE_EXISTS = 'INSERT INTO lt_roles (role) VALUES ($1) ON CONFLICT DO NOTHING';
|
|
7
7
|
/** Fetch roles for a single user, ordered by creation time. granted_by_persona
|
|
@@ -40,6 +40,14 @@ exports.CREATE_USER_WITH_ROLES = `WITH new_user AS (
|
|
|
40
40
|
SELECT * FROM new_user`;
|
|
41
41
|
exports.GET_USER_BY_EMAIL = `SELECT * FROM lt_users WHERE email = $1 LIMIT 1`;
|
|
42
42
|
exports.GET_USER_BY_ID = 'SELECT * FROM lt_users WHERE id = $1';
|
|
43
|
+
/**
|
|
44
|
+
* Lookup by a caller-named metadata key (e.g. a badge binding). LIMIT 2 so an
|
|
45
|
+
* ambiguous binding — two users carrying the same value — is detectable and
|
|
46
|
+
* can fail loudly rather than silently picking one. Seq scan by design: this
|
|
47
|
+
* is the people table (small); revisit with a GIN index on metadata if a
|
|
48
|
+
* deployment ever holds tens of thousands of users.
|
|
49
|
+
*/
|
|
50
|
+
exports.GET_USERS_BY_METADATA_VALUE = `SELECT * FROM lt_users WHERE metadata->>$1 = $2 AND status = 'active' LIMIT 2`;
|
|
43
51
|
/** Check if a user exists by id. Lightweight — returns only the id column. */
|
|
44
52
|
exports.VERIFY_USER_BY_ID = 'SELECT id FROM lt_users WHERE id = $1 LIMIT 1';
|
|
45
53
|
/** Fetch user + roles in a single query. Returns one row per role (or one row with nulls if no roles). */
|
|
@@ -259,6 +259,40 @@ function registerEscalationTools(server) {
|
|
|
259
259
|
}
|
|
260
260
|
return { content: [{ type: 'text', text: JSON.stringify(result.data) }] };
|
|
261
261
|
});
|
|
262
|
+
// mirrors POST /api/escalations/aggregate-by-facets
|
|
263
|
+
server.registerTool('aggregate_by_facets', {
|
|
264
|
+
title: 'Aggregate by Facets',
|
|
265
|
+
description: 'Grouped analytics over the escalation intervals. Every escalation is one open ' +
|
|
266
|
+
'interval [created_at, ended_at); this tool reads it two ways: membership (rows or, ' +
|
|
267
|
+
'with distinctBy, distinct entities open at an instant — a past asOf reconstructs the ' +
|
|
268
|
+
'live set then) and dwell (open-seconds per group within a half-open [from,to) window). ' +
|
|
269
|
+
'Group by role/subtype/status columns plus metadata facet keys; optional states[] label ' +
|
|
270
|
+
'each group. One call replaces N per-filter count round-trips. The filter takes the WHAT ' +
|
|
271
|
+
'fields only — status/available/jeopardy are rejected (liveness derives from the measure).',
|
|
272
|
+
inputSchema: schemas_1.aggregateByFacetsSchema,
|
|
273
|
+
}, async (args) => {
|
|
274
|
+
const result = await escalationApi.aggregateByFacets(args, await systemAuth());
|
|
275
|
+
if (result.error) {
|
|
276
|
+
return { content: [{ type: 'text', text: JSON.stringify({ error: result.error }) }], isError: true };
|
|
277
|
+
}
|
|
278
|
+
return { content: [{ type: 'text', text: JSON.stringify(result.data) }] };
|
|
279
|
+
});
|
|
280
|
+
// mirrors POST /api/escalations/timeline-by-facet
|
|
281
|
+
server.registerTool('timeline_by_facet', {
|
|
282
|
+
title: 'Timeline by Facet',
|
|
283
|
+
description: 'One entity\'s ordered interval sequence — every escalation the entity facet ' +
|
|
284
|
+
'(e.g. a machine id) appeared in, as [startedAt, endedAt) spans with durations, in ' +
|
|
285
|
+
'created_at order. Open intervals report endedAt: null. Gaps between consecutive ' +
|
|
286
|
+
'intervals are untracked time and are preserved, not filled. The entity facet value ' +
|
|
287
|
+
'must be stored as a JSON string (GIN containment match).',
|
|
288
|
+
inputSchema: schemas_1.timelineByFacetSchema,
|
|
289
|
+
}, async (args) => {
|
|
290
|
+
const result = await escalationApi.timelineByFacet(args, await systemAuth());
|
|
291
|
+
if (result.error) {
|
|
292
|
+
return { content: [{ type: 'text', text: JSON.stringify({ error: result.error }) }], isError: true };
|
|
293
|
+
}
|
|
294
|
+
return { content: [{ type: 'text', text: JSON.stringify(result.data) }] };
|
|
295
|
+
});
|
|
262
296
|
// mirrors POST /api/escalations/claim-groups
|
|
263
297
|
server.registerTool('claim_groups', {
|
|
264
298
|
title: 'Claim Groups',
|
|
@@ -56,7 +56,23 @@ function registerScanCodeTools(server) {
|
|
|
56
56
|
'no_match_fallback, unconfigured, invalid_code, forbidden, conflict).',
|
|
57
57
|
inputSchema: schemas_1.executeScanCodeSchema,
|
|
58
58
|
}, async (args) => {
|
|
59
|
-
const result = await scanCodesApi.executeScanCode({
|
|
59
|
+
const result = await scanCodesApi.executeScanCode({
|
|
60
|
+
code: args.code,
|
|
61
|
+
actingToken: args.actingToken,
|
|
62
|
+
previousActingToken: args.previousActingToken,
|
|
63
|
+
}, await systemAuth());
|
|
64
|
+
return asText(result.data ?? { error: result.error });
|
|
65
|
+
});
|
|
66
|
+
// mirrors POST /api/scan-codes/execute-choice
|
|
67
|
+
server.registerTool('execute_scan_choice', {
|
|
68
|
+
title: 'Execute Scan Choice',
|
|
69
|
+
description: 'Execute one choice presented by a PRESENT step (the info-choice screen). ' +
|
|
70
|
+
'The pointer (scheme/category/step/choice + escalationId) is re-validated ' +
|
|
71
|
+
'against live config, the row\'s current state, the acting-identity gate, ' +
|
|
72
|
+
'and RBAC before the verb runs.',
|
|
73
|
+
inputSchema: schemas_1.executeScanChoiceSchema,
|
|
74
|
+
}, async (args) => {
|
|
75
|
+
const result = await scanCodesApi.executeScanChoice(args, await systemAuth());
|
|
60
76
|
return asText(result.data ?? { error: result.error });
|
|
61
77
|
});
|
|
62
78
|
// mirrors GET /api/scan-codes/schemes
|