@hotmeshio/long-tail 0.10.1 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/api/me.d.ts +16 -0
- package/build/api/me.js +79 -0
- package/build/api/roles.d.ts +6 -0
- package/build/api/roles.js +10 -0
- package/build/lib/db/schemas/022_user_preferences.sql +18 -0
- package/build/routes/index.js +2 -0
- package/build/routes/me.d.ts +2 -0
- package/build/routes/me.js +57 -0
- package/build/sdk/index.d.ts +6 -0
- package/build/sdk/index.js +11 -0
- package/build/services/role/index.js +1 -0
- package/build/services/role/sql.d.ts +5 -2
- package/build/services/role/sql.js +7 -1
- package/build/services/role/types.d.ts +16 -0
- package/build/services/user/index.d.ts +1 -0
- package/build/services/user/index.js +5 -1
- package/build/services/user/preferences.d.ts +15 -0
- package/build/services/user/preferences.js +38 -0
- package/build/system/mcp-servers/admin/schemas.d.ts +26 -0
- package/build/system/mcp-servers/admin/schemas.js +6 -0
- package/build/system/mcp-servers/admin/users.js +6 -3
- package/build/system/seed/tool-manifests-admin.d.ts +167 -0
- package/build/system/seed/tool-manifests-admin.js +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/dashboard/dist/assets/{AdminDashboard-D7Amh-EJ.js → AdminDashboard-Dy031e9g.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-D7Amh-EJ.js.map → AdminDashboard-Dy031e9g.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-CW2udbSO.js → AgentConfigPage-CqmtYBbC.js} +6 -6
- package/dashboard/dist/assets/{AgentConfigPage-CW2udbSO.js.map → AgentConfigPage-CqmtYBbC.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-Dy3Qvlfk.js → AgentDetailPage-oYLBrN74.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-Dy3Qvlfk.js.map → AgentDetailPage-oYLBrN74.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-D7WePZ0o.js → AgentsPage-CHczRx5N.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-D7WePZ0o.js.map → AgentsPage-CHczRx5N.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-DDVuivEE.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-DDVuivEE.js.map +1 -0
- package/dashboard/dist/assets/BotPicker-2QEIpc-K.js +2 -0
- package/dashboard/dist/assets/{BotPicker-KebTxTDi.js.map → BotPicker-2QEIpc-K.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-3VTLEPGO.js → CapabilitiesPage-lQJGZ_-t.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-3VTLEPGO.js.map → CapabilitiesPage-lQJGZ_-t.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-BYgeZz9M.js → CollapsibleSection-CHWP0WI6.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-BYgeZz9M.js.map → CollapsibleSection-CHWP0WI6.js.map} +1 -1
- package/dashboard/dist/assets/CountdownTimer-TXsRlTU4.js +2 -0
- package/dashboard/dist/assets/CountdownTimer-TXsRlTU4.js.map +1 -0
- package/dashboard/dist/assets/{CredentialsPage-CaH3J3SE.js → CredentialsPage-BKxS-1sA.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-CaH3J3SE.js.map → CredentialsPage-BKxS-1sA.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-Bma_4AC2.js → CronLabel-Bd2G0Rap.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-Bma_4AC2.js.map → CronLabel-Bd2G0Rap.js.map} +1 -1
- package/dashboard/dist/assets/{CustomDurationPicker-BxyjEX27.js → CustomDurationPicker-j4bBrDJ6.js} +2 -2
- package/dashboard/dist/assets/{CustomDurationPicker-BxyjEX27.js.map → CustomDurationPicker-j4bBrDJ6.js.map} +1 -1
- package/dashboard/dist/assets/{DropZone-zxH-9B8c.js → DropZone-DNDEgMpJ.js} +2 -2
- package/dashboard/dist/assets/{DropZone-zxH-9B8c.js.map → DropZone-DNDEgMpJ.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-Dr1cEwoi.js → ElapsedCell-g7GO7f8L.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-Dr1cEwoi.js.map → ElapsedCell-g7GO7f8L.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-CLdsR-hK.js → EscalationListSchemaPage-CIJ-OgVC.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-CLdsR-hK.js.map → EscalationListSchemaPage-CIJ-OgVC.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-DnEnvolM.js → EscalationSchemaPage-C7dHgG8e.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-DnEnvolM.js.map → EscalationSchemaPage-C7dHgG8e.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-BH8cxgLI.js → EscalationsOverview-D8NrATg2.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-BH8cxgLI.js.map → EscalationsOverview-D8NrATg2.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-p-xsfYYg.js → EventTable-DBV1P2ME.js} +2 -2
- package/dashboard/dist/assets/{EventTable-p-xsfYYg.js.map → EventTable-DBV1P2ME.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-Cf9c_LJ-.js → GraphInvokePage-DbHvggQ_.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-Cf9c_LJ-.js.map → GraphInvokePage-DbHvggQ_.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-BdCtKXAV.js → HomePage-BpexnDO_.js} +2 -2
- package/dashboard/dist/assets/{HomePage-BdCtKXAV.js.map → HomePage-BpexnDO_.js.map} +1 -1
- package/dashboard/dist/assets/ListToolbar-KC6LGtKP.js +2 -0
- package/dashboard/dist/assets/{ListToolbar-CDlol8XJ.js.map → ListToolbar-KC6LGtKP.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-ChZ36p9t.js → McpOverview-BDZC9Hvl.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-ChZ36p9t.js.map → McpOverview-BDZC9Hvl.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-X4j_jm3r.js → McpQueryDetailPage-CXhgX1pS.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-X4j_jm3r.js.map → McpQueryDetailPage-CXhgX1pS.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-C30HsQfZ.js → McpQueryPage-CsKNXUhb.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-C30HsQfZ.js.map → McpQueryPage-CsKNXUhb.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-18d7Iqfy.js → McpRunDetailPage-BM3mUSlH.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-18d7Iqfy.js.map → McpRunDetailPage-BM3mUSlH.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-BHZHCwMM.js → McpRunsPage-f5hDbpLo.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-BHZHCwMM.js.map → McpRunsPage-f5hDbpLo.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-BQNMfY0m.js → NamespacePill-C4u6Go1W.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-BQNMfY0m.js.map → NamespacePill-C4u6Go1W.js.map} +1 -1
- package/dashboard/dist/assets/OperationsPage-D37cZ8Qh.js +2 -0
- package/dashboard/dist/assets/{OperationsPage-GMojwL3q.js.map → OperationsPage-D37cZ8Qh.js.map} +1 -1
- package/dashboard/dist/assets/OperatorDashboard-_axS17fp.js +2 -0
- package/dashboard/dist/assets/{OperatorDashboard-BGJrxLMU.js.map → OperatorDashboard-_axS17fp.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-BIY1YvKR.js → PageHeader-Bxa1XFz0.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-BIY1YvKR.js.map → PageHeader-Bxa1XFz0.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-TUyglVW0.js → PageHeaderWithStats-D_sO0MqJ.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-TUyglVW0.js.map → PageHeaderWithStats-D_sO0MqJ.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-Bcp3GKFo.js → ProcessDetailPage-D8pAWUXx.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-Bcp3GKFo.js.map → ProcessDetailPage-D8pAWUXx.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-DPrvuLoU.js → ProcessesListPage-CoQEi_Su.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-DPrvuLoU.js.map → ProcessesListPage-CoQEi_Su.js.map} +1 -1
- package/dashboard/dist/assets/RoleDetailPage-ufbypNNR.js +8 -0
- package/dashboard/dist/assets/RoleDetailPage-ufbypNNR.js.map +1 -0
- package/dashboard/dist/assets/{RolePill-4LO_CuO3.js → RolePill-DLwmVMam.js} +2 -2
- package/dashboard/dist/assets/{RolePill-4LO_CuO3.js.map → RolePill-DLwmVMam.js.map} +1 -1
- package/dashboard/dist/assets/RolesPage-CxpXm4Sw.js +2 -0
- package/dashboard/dist/assets/{RolesPage-D3NNU92h.js.map → RolesPage-CxpXm4Sw.js.map} +1 -1
- package/dashboard/dist/assets/RunAsSelector-BebF8Lib.js +2 -0
- package/dashboard/dist/assets/{RunAsSelector-Z2Yunqdf.js.map → RunAsSelector-BebF8Lib.js.map} +1 -1
- package/dashboard/dist/assets/{SlidePanel-DK4sWXmp.js → SlidePanel-BDVDuwIf.js} +2 -2
- package/dashboard/dist/assets/{SlidePanel-DK4sWXmp.js.map → SlidePanel-BDVDuwIf.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-CeLsnCIS.js → StickyPagination-Cd83AHd_.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-CeLsnCIS.js.map → StickyPagination-Cd83AHd_.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-DWs7XkmH.js → StreamMessageDetail-BIXbrZM0.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-DWs7XkmH.js.map → StreamMessageDetail-BIXbrZM0.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-Dxl9a51q.js → SwimlaneTimeline-CC5qZjYo.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-Dxl9a51q.js.map → SwimlaneTimeline-CC5qZjYo.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-CK-JhBG2.js → TagInput-C2gi47M8.js} +2 -2
- package/dashboard/dist/assets/{TagInput-CK-JhBG2.js.map → TagInput-C2gi47M8.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-DVr31zDE.js → TaskDetailPage-DnjhW7qv.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-DVr31zDE.js.map → TaskDetailPage-DnjhW7qv.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-C_Vo2Clc.js → TaskQueuePill-BPP0Almh.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-C_Vo2Clc.js.map → TaskQueuePill-BPP0Almh.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-DNGp5lfi.js → TasksListPage-DySfZFgs.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-DNGp5lfi.js.map → TasksListPage-DySfZFgs.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-j2Q4w4lY.js → TimeAgo-BKOl-7Tt.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-j2Q4w4lY.js.map → TimeAgo-BKOl-7Tt.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-BLEfob2C.js → TimestampCell-DGOsba-A.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-BLEfob2C.js.map → TimestampCell-DGOsba-A.js.map} +1 -1
- package/dashboard/dist/assets/ToolPill-D74TkYB-.js +2 -0
- package/dashboard/dist/assets/{ToolPill-BCi101Jh.js.map → ToolPill-D74TkYB-.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-ZJZT_mDP.js → ToolTestPanel-Bez6OyRL.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-ZJZT_mDP.js.map → ToolTestPanel-Bez6OyRL.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-ynUkO1A8.js → TopicDetailPage-BHccgkU_.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-ynUkO1A8.js.map → TopicDetailPage-BHccgkU_.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-Ctb_85Tw.js → TopicsPage-5yW63ELl.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-Ctb_85Tw.js.map → TopicsPage-5yW63ELl.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-CkFpUqVK.js → UserName-DcXhOSVm.js} +2 -2
- package/dashboard/dist/assets/{UserName-CkFpUqVK.js.map → UserName-DcXhOSVm.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-CSw2aQJC.js → WorkflowExecutionPage-CDDLled5.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-CSw2aQJC.js.map → WorkflowExecutionPage-CDDLled5.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowPill-Fjc2q9U9.js +2 -0
- package/dashboard/dist/assets/{WorkflowPill-DHxrAkp3.js.map → WorkflowPill-Fjc2q9U9.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-DOyZbqzf.js → WorkflowsDashboard-C0Bbrd5M.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-DOyZbqzf.js.map → WorkflowsDashboard-C0Bbrd5M.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-CRyHvUBx.js → WorkflowsOverview-D8MkSMex.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-CRyHvUBx.js.map → WorkflowsOverview-D8MkSMex.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-DRBmQXY6.js → YamlWorkflowDetailPage-BcbrYhDI.js} +11 -11
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-DRBmQXY6.js.map → YamlWorkflowDetailPage-BcbrYhDI.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-HnI-9eBW.js → YamlWorkflowsPage-9Ki54d-9.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-HnI-9eBW.js.map → YamlWorkflowsPage-9Ki54d-9.js.map} +1 -1
- package/dashboard/dist/assets/{agents-BA2CvQO9.js → agents-CopQ3t5o.js} +2 -2
- package/dashboard/dist/assets/{agents-BA2CvQO9.js.map → agents-CopQ3t5o.js.map} +1 -1
- package/dashboard/dist/assets/{bots-DHHnoo8x.js → bots-CAYJYL9E.js} +2 -2
- package/dashboard/dist/assets/{bots-DHHnoo8x.js.map → bots-CAYJYL9E.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-BYBKLRRI.js → capabilities-5JRieYUy.js} +2 -2
- package/dashboard/dist/assets/{capabilities-BYBKLRRI.js.map → capabilities-5JRieYUy.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-H0Ljhb-1.js → controlplane-B4rT6tIw.js} +2 -2
- package/dashboard/dist/assets/{controlplane-H0Ljhb-1.js.map → controlplane-B4rT6tIw.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-BV3Ztn7D.js → escalation-columns-BbS5X61l.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-BV3Ztn7D.js.map → escalation-columns-BbS5X61l.js.map} +1 -1
- package/dashboard/dist/assets/{index-D1Q8WfGN.js → index-B68A3v-S.js} +2 -2
- package/dashboard/dist/assets/{index-D1Q8WfGN.js.map → index-B68A3v-S.js.map} +1 -1
- package/dashboard/dist/assets/{index-DSjih1iX.js → index-BAi89Xpm.js} +2 -2
- package/dashboard/dist/assets/{index-DSjih1iX.js.map → index-BAi89Xpm.js.map} +1 -1
- package/dashboard/dist/assets/index-BJ0jjFsI.js +5 -0
- package/dashboard/dist/assets/index-BJ0jjFsI.js.map +1 -0
- package/dashboard/dist/assets/index-BOJMUk4F.js +2 -0
- package/dashboard/dist/assets/{index-BXrm76Hm.js.map → index-BOJMUk4F.js.map} +1 -1
- package/dashboard/dist/assets/{index-Dx6-4esw.js → index-BrgYykPV.js} +2 -2
- package/dashboard/dist/assets/{index-Dx6-4esw.js.map → index-BrgYykPV.js.map} +1 -1
- package/dashboard/dist/assets/{index-BI-9M7z3.js → index-BxgtIqvl.js} +2 -2
- package/dashboard/dist/assets/{index-BI-9M7z3.js.map → index-BxgtIqvl.js.map} +1 -1
- package/dashboard/dist/assets/index-C0cHXaX-.css +1 -0
- package/dashboard/dist/assets/{index-YWvrMcqh.js → index-CDHDoHYz.js} +2 -2
- package/dashboard/dist/assets/{index-YWvrMcqh.js.map → index-CDHDoHYz.js.map} +1 -1
- package/dashboard/dist/assets/index-CUZJHXew.js +2 -0
- package/dashboard/dist/assets/{index-B4FaugP1.js.map → index-CUZJHXew.js.map} +1 -1
- package/dashboard/dist/assets/index-D5n_e59T.js +2 -0
- package/dashboard/dist/assets/{index-CVMA5PVQ.js.map → index-D5n_e59T.js.map} +1 -1
- package/dashboard/dist/assets/index-DIgiIoou.js +63 -0
- package/dashboard/dist/assets/index-DIgiIoou.js.map +1 -0
- package/dashboard/dist/assets/{index-CP6D_Gtw.js → index-Dd1RxGNw.js} +2 -2
- package/dashboard/dist/assets/{index-CP6D_Gtw.js.map → index-Dd1RxGNw.js.map} +1 -1
- package/dashboard/dist/assets/index-iOb3sGsC.js +5 -0
- package/dashboard/dist/assets/{index-O2wWcCLo.js.map → index-iOb3sGsC.js.map} +1 -1
- package/dashboard/dist/assets/{index-CWkAN6wc.js → index-mcAkQblr.js} +2 -2
- package/dashboard/dist/assets/{index-CWkAN6wc.js.map → index-mcAkQblr.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-BVbElRHf.js → knowledge-B9bmoXOe.js} +2 -2
- package/dashboard/dist/assets/{knowledge-BVbElRHf.js.map → knowledge-B9bmoXOe.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-CstDdowJ.js → mcp-DYMFBOFz.js} +2 -2
- package/dashboard/dist/assets/{mcp-CstDdowJ.js.map → mcp-DYMFBOFz.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-DHUs0N8H.js → mcp-query-wloSpyPM.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-DHUs0N8H.js.map → mcp-query-wloSpyPM.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-BDmAzE3U.js → pipelines-DBXX6TEi.js} +2 -2
- package/dashboard/dist/assets/{pipelines-BDmAzE3U.js.map → pipelines-DBXX6TEi.js.map} +1 -1
- package/dashboard/dist/assets/{tasks--qZocuG-.js → tasks-CD3-C7tP.js} +2 -2
- package/dashboard/dist/assets/{tasks--qZocuG-.js.map → tasks-CD3-C7tP.js.map} +1 -1
- package/dashboard/dist/assets/{topics-P3jkjMsx.js → topics-D8pKi6zA.js} +2 -2
- package/dashboard/dist/assets/{topics-P3jkjMsx.js.map → topics-D8pKi6zA.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-CqH8Pasj.js → useEventHooks-DV9pLDOW.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-CqH8Pasj.js.map → useEventHooks-DV9pLDOW.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-aI3tPfo3.js → useNamespace-DykYhZY9.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-aI3tPfo3.js.map → useNamespace-DykYhZY9.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-CPVyuW8i.js → useYamlActivityEvents-By044UAv.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-CPVyuW8i.js.map → useYamlActivityEvents-By044UAv.js.map} +1 -1
- package/dashboard/dist/assets/{users-BrcmIH7O.js → users-mI9goDjj.js} +2 -2
- package/dashboard/dist/assets/{users-BrcmIH7O.js.map → users-mI9goDjj.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-Qk9qLjF_.js → vendor-icons-ihWGa7_d.js} +147 -132
- package/dashboard/dist/assets/vendor-icons-ihWGa7_d.js.map +1 -0
- package/dashboard/dist/assets/{workflows-DPhX5L5C.js → workflows-DCUilz68.js} +2 -2
- package/dashboard/dist/assets/{workflows-DPhX5L5C.js.map → workflows-DCUilz68.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-KZI2cufF.js → yaml-workflows-DWNMP1PT.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-KZI2cufF.js.map → yaml-workflows-DWNMP1PT.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/api/http/escalations.md +1 -0
- package/docs/api/http/roles.md +2 -0
- package/docs/api/http/users.md +39 -0
- package/docs/api/sdk/roles.md +5 -0
- package/docs/api/sdk/users.md +39 -0
- package/docs/hitl/pinned-views.md +45 -0
- package/docs/hitl/x-lt-list-schema.md +30 -2
- package/docs/hitl/x-lt-show-if.md +11 -0
- package/docs/hitl/x-lt-widget.md +22 -0
- package/docs/hitl-guide.md +6 -3
- package/package.json +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-Dx51E6s_.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-Dx51E6s_.js.map +0 -1
- package/dashboard/dist/assets/BotPicker-KebTxTDi.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-DFqEYmiF.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-DFqEYmiF.js.map +0 -1
- package/dashboard/dist/assets/ListToolbar-CDlol8XJ.js +0 -2
- package/dashboard/dist/assets/OperationsPage-GMojwL3q.js +0 -2
- package/dashboard/dist/assets/OperatorDashboard-BGJrxLMU.js +0 -2
- package/dashboard/dist/assets/RoleDetailPage-Ws3umQKQ.js +0 -8
- package/dashboard/dist/assets/RoleDetailPage-Ws3umQKQ.js.map +0 -1
- package/dashboard/dist/assets/RolesPage-D3NNU92h.js +0 -2
- package/dashboard/dist/assets/RunAsSelector-Z2Yunqdf.js +0 -2
- package/dashboard/dist/assets/ToolPill-BCi101Jh.js +0 -2
- package/dashboard/dist/assets/WorkflowPill-DHxrAkp3.js +0 -2
- package/dashboard/dist/assets/index-B4FaugP1.js +0 -2
- package/dashboard/dist/assets/index-BXrm76Hm.js +0 -2
- package/dashboard/dist/assets/index-BeFjLCIQ.js +0 -5
- package/dashboard/dist/assets/index-BeFjLCIQ.js.map +0 -1
- package/dashboard/dist/assets/index-BrEcQQ1p.css +0 -1
- package/dashboard/dist/assets/index-CVMA5PVQ.js +0 -2
- package/dashboard/dist/assets/index-O2wWcCLo.js +0 -5
- package/dashboard/dist/assets/index-iX8HLLB9.js +0 -63
- package/dashboard/dist/assets/index-iX8HLLB9.js.map +0 -1
- package/dashboard/dist/assets/vendor-icons-Qk9qLjF_.js.map +0 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { LTApiResult, LTApiAuth } from '../types/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* The caller's preferences document — a generic per-user JSON store for
|
|
4
|
+
* presentation state (pinned views are the first tenant). Always an object;
|
|
5
|
+
* an unset store reads as {}.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getMyPreferences(auth: LTApiAuth): Promise<LTApiResult>;
|
|
8
|
+
/**
|
|
9
|
+
* Shallow-merge a patch into the caller's preferences. Top-level keys
|
|
10
|
+
* overwrite; a `null` value deletes its key. The patch and the merged
|
|
11
|
+
* document are both size-capped; the merge itself is a single guarded
|
|
12
|
+
* UPDATE (no read-then-write).
|
|
13
|
+
*/
|
|
14
|
+
export declare function patchMyPreferences(input: {
|
|
15
|
+
patch: unknown;
|
|
16
|
+
}, auth: LTApiAuth): Promise<LTApiResult>;
|
package/build/api/me.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.getMyPreferences = getMyPreferences;
|
|
37
|
+
exports.patchMyPreferences = patchMyPreferences;
|
|
38
|
+
const userService = __importStar(require("../services/user"));
|
|
39
|
+
// ── Self-service surface (/api/me) ─────────────────────────────────────────
|
|
40
|
+
// Operations on the AUTHENTICATED user only — no ids, no admin gates.
|
|
41
|
+
/**
|
|
42
|
+
* The caller's preferences document — a generic per-user JSON store for
|
|
43
|
+
* presentation state (pinned views are the first tenant). Always an object;
|
|
44
|
+
* an unset store reads as {}.
|
|
45
|
+
*/
|
|
46
|
+
async function getMyPreferences(auth) {
|
|
47
|
+
try {
|
|
48
|
+
const preferences = await userService.getPreferences(auth.userId);
|
|
49
|
+
return { status: 200, data: { preferences } };
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
return { status: 500, error: err.message };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Shallow-merge a patch into the caller's preferences. Top-level keys
|
|
57
|
+
* overwrite; a `null` value deletes its key. The patch and the merged
|
|
58
|
+
* document are both size-capped; the merge itself is a single guarded
|
|
59
|
+
* UPDATE (no read-then-write).
|
|
60
|
+
*/
|
|
61
|
+
async function patchMyPreferences(input, auth) {
|
|
62
|
+
try {
|
|
63
|
+
const { patch } = input;
|
|
64
|
+
if (!patch || typeof patch !== 'object' || Array.isArray(patch)) {
|
|
65
|
+
return { status: 400, error: 'Body must be a JSON object of preference keys' };
|
|
66
|
+
}
|
|
67
|
+
if (JSON.stringify(patch).length > userService.PREFERENCES_MAX_BYTES) {
|
|
68
|
+
return { status: 413, error: `Preferences patch exceeds ${userService.PREFERENCES_MAX_BYTES} bytes` };
|
|
69
|
+
}
|
|
70
|
+
const preferences = await userService.patchPreferences(auth.userId, patch);
|
|
71
|
+
if (preferences === null) {
|
|
72
|
+
return { status: 413, error: `Merged preferences would exceed ${userService.PREFERENCES_MAX_BYTES} bytes` };
|
|
73
|
+
}
|
|
74
|
+
return { status: 200, data: { preferences } };
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
return { status: 500, error: err.message };
|
|
78
|
+
}
|
|
79
|
+
}
|
package/build/api/roles.d.ts
CHANGED
|
@@ -88,6 +88,12 @@ export declare function updateRole(input: {
|
|
|
88
88
|
metadata_schema?: Record<string, any> | null;
|
|
89
89
|
/** The escalation LIST schema — rich formatting for this role's list page. */
|
|
90
90
|
list_schema?: Record<string, any> | null;
|
|
91
|
+
/** Pinned-view seeds for the role's members: [{ label, url, badge? }] or null to clear. */
|
|
92
|
+
default_pins?: {
|
|
93
|
+
label: string;
|
|
94
|
+
url: string;
|
|
95
|
+
badge?: boolean;
|
|
96
|
+
}[] | null;
|
|
91
97
|
properties?: Record<string, any> | null;
|
|
92
98
|
ops_visible?: boolean;
|
|
93
99
|
parent_role?: string | null;
|
package/build/api/roles.js
CHANGED
|
@@ -228,6 +228,15 @@ async function updateRole(input) {
|
|
|
228
228
|
if (input.parent_role != null && input.parent_role === input.role) {
|
|
229
229
|
return { status: 400, error: 'parent_role must reference a different role' };
|
|
230
230
|
}
|
|
231
|
+
if (input.default_pins != null) {
|
|
232
|
+
const pinsValid = Array.isArray(input.default_pins) && input.default_pins.every((p) => p && typeof p === 'object'
|
|
233
|
+
&& typeof p.label === 'string' && p.label.trim() !== ''
|
|
234
|
+
&& typeof p.url === 'string' && p.url.startsWith('/')
|
|
235
|
+
&& (p.badge === undefined || typeof p.badge === 'boolean'));
|
|
236
|
+
if (!pinsValid) {
|
|
237
|
+
return { status: 400, error: 'default_pins must be [{ label, url, badge? }] with dashboard-relative urls' };
|
|
238
|
+
}
|
|
239
|
+
}
|
|
231
240
|
if (input.upstream_roles != null) {
|
|
232
241
|
if (!Array.isArray(input.upstream_roles) || input.upstream_roles.some((u) => typeof u !== 'string' || !u.trim())) {
|
|
233
242
|
return { status: 400, error: 'upstream_roles must be an array of role names' };
|
|
@@ -247,6 +256,7 @@ async function updateRole(input) {
|
|
|
247
256
|
form_schema: input.form_schema,
|
|
248
257
|
metadata_schema: input.metadata_schema,
|
|
249
258
|
list_schema: input.list_schema,
|
|
259
|
+
default_pins: input.default_pins,
|
|
250
260
|
properties: input.properties,
|
|
251
261
|
ops_visible: input.ops_visible,
|
|
252
262
|
parent_role: input.parent_role,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
-- Migration 022: Per-user preferences + role default pins
|
|
2
|
+
--
|
|
3
|
+
-- lt_users.preferences is a generic per-user JSON store (pinned views are the
|
|
4
|
+
-- first tenant, not the schema): read via GET /api/me/preferences, written via
|
|
5
|
+
-- PATCH with shallow top-level merge (null deletes a key), size-capped at the
|
|
6
|
+
-- API layer. Preferences carry presentation state only — never data and never
|
|
7
|
+
-- authorization; read-scope enforcement stays with the queries a preference
|
|
8
|
+
-- may point at.
|
|
9
|
+
--
|
|
10
|
+
-- lt_roles.default_pins seeds a role's members with the persona's starting
|
|
11
|
+
-- pinned views ([{ label, url, badge? }]). Users promote, hide, or reorder
|
|
12
|
+
-- them through their own preferences.
|
|
13
|
+
|
|
14
|
+
ALTER TABLE lt_users
|
|
15
|
+
ADD COLUMN IF NOT EXISTS preferences JSONB;
|
|
16
|
+
|
|
17
|
+
ALTER TABLE lt_roles
|
|
18
|
+
ADD COLUMN IF NOT EXISTS default_pins JSONB;
|
package/build/routes/index.js
CHANGED
|
@@ -14,6 +14,7 @@ const escalations_1 = __importDefault(require("./escalations"));
|
|
|
14
14
|
const workflows_1 = __importDefault(require("./workflows"));
|
|
15
15
|
const exports_1 = __importDefault(require("./exports"));
|
|
16
16
|
const users_1 = __importDefault(require("./users"));
|
|
17
|
+
const me_1 = __importDefault(require("./me"));
|
|
17
18
|
const roles_1 = __importDefault(require("./roles"));
|
|
18
19
|
const dba_1 = __importDefault(require("./dba"));
|
|
19
20
|
const maintenance_1 = __importDefault(require("./maintenance"));
|
|
@@ -51,6 +52,7 @@ router.use('/workflows', workflows_1.default);
|
|
|
51
52
|
router.use('/workflow-states', exports_1.default);
|
|
52
53
|
router.use('/config/maintenance', maintenance_1.default);
|
|
53
54
|
router.use('/users', users_1.default);
|
|
55
|
+
router.use('/me', me_1.default);
|
|
54
56
|
router.use('/roles', roles_1.default);
|
|
55
57
|
router.use('/dba', dba_1.default);
|
|
56
58
|
router.use('/mcp', mcp_1.default);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const express_1 = require("express");
|
|
37
|
+
const api = __importStar(require("../api/me"));
|
|
38
|
+
const router = (0, express_1.Router)();
|
|
39
|
+
// ── Self-service (/api/me) — the authenticated user, no admin gates ─────────
|
|
40
|
+
/**
|
|
41
|
+
* GET /api/me/preferences
|
|
42
|
+
* The caller's preferences document ({} when unset).
|
|
43
|
+
*/
|
|
44
|
+
router.get('/preferences', async (req, res) => {
|
|
45
|
+
const result = await api.getMyPreferences(req.auth);
|
|
46
|
+
res.status(result.status).json(result.data ?? { error: result.error });
|
|
47
|
+
});
|
|
48
|
+
/**
|
|
49
|
+
* PATCH /api/me/preferences
|
|
50
|
+
* Shallow-merge the body into the caller's preferences; null deletes a key.
|
|
51
|
+
* Returns the merged document. 413 when the result would exceed the cap.
|
|
52
|
+
*/
|
|
53
|
+
router.patch('/preferences', async (req, res) => {
|
|
54
|
+
const result = await api.patchMyPreferences({ patch: req.body }, req.auth);
|
|
55
|
+
res.status(result.status).json(result.data ?? { error: result.error });
|
|
56
|
+
});
|
|
57
|
+
exports.default = router;
|
package/build/sdk/index.d.ts
CHANGED
|
@@ -275,6 +275,12 @@ export declare function createClient(options?: LTClientOptions): {
|
|
|
275
275
|
addRole: typeof usersApi.addUserRole;
|
|
276
276
|
removeRole: typeof usersApi.removeUserRole;
|
|
277
277
|
};
|
|
278
|
+
me: {
|
|
279
|
+
getPreferences: (callAuth?: LTApiAuth) => Promise<LTApiResult<any>>;
|
|
280
|
+
patchPreferences: (input: {
|
|
281
|
+
patch: unknown;
|
|
282
|
+
}, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
|
|
283
|
+
};
|
|
278
284
|
roles: {
|
|
279
285
|
list: typeof rolesApi.listRoles;
|
|
280
286
|
listWithDetails: typeof rolesApi.listRolesWithDetails;
|
package/build/sdk/index.js
CHANGED
|
@@ -39,6 +39,7 @@ const escalationsApi = __importStar(require("../api/escalations"));
|
|
|
39
39
|
const workflowsApi = __importStar(require("../api/workflows"));
|
|
40
40
|
const yamlWorkflowsApi = __importStar(require("../api/yaml-workflows"));
|
|
41
41
|
const usersApi = __importStar(require("../api/users"));
|
|
42
|
+
const meApi = __importStar(require("../api/me"));
|
|
42
43
|
const rolesApi = __importStar(require("../api/roles"));
|
|
43
44
|
const authApi = __importStar(require("../api/auth"));
|
|
44
45
|
const mcpApi = __importStar(require("../api/mcp"));
|
|
@@ -190,6 +191,16 @@ function createClient(options = {}) {
|
|
|
190
191
|
addRole: usersApi.addUserRole,
|
|
191
192
|
removeRole: usersApi.removeUserRole,
|
|
192
193
|
},
|
|
194
|
+
// ── Me — the authenticated caller (preferences, presentation state) ────
|
|
195
|
+
me: {
|
|
196
|
+
getPreferences: (callAuth) => {
|
|
197
|
+
const resolved = callAuth ?? auth;
|
|
198
|
+
if (!resolved)
|
|
199
|
+
return Promise.resolve({ status: 401, error: 'Auth context required' });
|
|
200
|
+
return meApi.getMyPreferences(resolved);
|
|
201
|
+
},
|
|
202
|
+
patchPreferences: bindAuth(meApi.patchMyPreferences, auth),
|
|
203
|
+
},
|
|
193
204
|
// ── Roles ──────────────────────────────────────────────────────────────
|
|
194
205
|
roles: {
|
|
195
206
|
list: rolesApi.listRoles,
|
|
@@ -146,6 +146,7 @@ async function updateRoleMetadata(role, input) {
|
|
|
146
146
|
input.change_summary ?? null,
|
|
147
147
|
provided('upstream_roles'), upstreams,
|
|
148
148
|
provided('list_schema'), input.list_schema != null ? JSON.stringify(input.list_schema) : null,
|
|
149
|
+
provided('default_pins'), input.default_pins != null ? JSON.stringify(input.default_pins) : null,
|
|
149
150
|
]);
|
|
150
151
|
if (!rows[0])
|
|
151
152
|
return null;
|
|
@@ -39,8 +39,11 @@ export declare const DELETE_ROLE = "\n DELETE FROM lt_roles WHERE role = $1";
|
|
|
39
39
|
* of the form/metadata pair: its own current_list_schema_version and its own
|
|
40
40
|
* snapshot table (lt_role_list_schemas), so a list-view edit never advances the
|
|
41
41
|
* resolve form's version. It shares $26 as the change summary.
|
|
42
|
+
*
|
|
43
|
+
* default_pins ($31 = provided sentinel, $32 = value) is unversioned config:
|
|
44
|
+
* the pinned-view seeds a role hands its members.
|
|
42
45
|
*/
|
|
43
|
-
export declare const UPDATE_ROLE_METADATA = "\n WITH updated AS (\n UPDATE lt_roles SET\n title = CASE WHEN $2::boolean THEN $3 ELSE title END,\n description = CASE WHEN $4::boolean THEN $5 ELSE description END,\n form_schema = CASE WHEN $6::boolean THEN $7::jsonb ELSE form_schema END,\n metadata_schema = CASE WHEN $8::boolean THEN $9::jsonb ELSE metadata_schema END,\n properties = CASE WHEN $10::boolean THEN COALESCE($11::jsonb, '{}'::jsonb) ELSE properties END,\n ops_visible = CASE WHEN $12::boolean THEN $13::boolean ELSE ops_visible END,\n parent_role = CASE WHEN $14::boolean THEN $15 ELSE parent_role END,\n sla_minutes = CASE WHEN $16::boolean THEN $17::numeric ELSE sla_minutes END,\n target_per_hour = CASE WHEN $18::boolean THEN $19::numeric ELSE target_per_hour END,\n worker_count = CASE WHEN $20::boolean THEN $21::int ELSE worker_count END,\n priority_threshold_minutes\n = CASE WHEN $22::boolean THEN $23::numeric ELSE priority_threshold_minutes END,\n priority_facet = CASE WHEN $24::boolean THEN $25 ELSE priority_facet END,\n list_schema = CASE WHEN $29::boolean THEN $30::jsonb ELSE list_schema END,\n current_schema_version = CASE\n WHEN ($6::boolean AND $7::jsonb IS DISTINCT FROM form_schema)\n OR ($8::boolean AND $9::jsonb IS DISTINCT FROM metadata_schema)\n THEN COALESCE(current_schema_version, 0) + 1\n ELSE current_schema_version END,\n current_list_schema_version = CASE\n WHEN $29::boolean AND $30::jsonb IS DISTINCT FROM list_schema\n THEN COALESCE(current_list_schema_version, 0) + 1\n ELSE current_list_schema_version END\n WHERE role = $1\n RETURNING\n role, title, description, form_schema, metadata_schema, properties,\n ops_visible, parent_role, sla_minutes, target_per_hour, worker_count,\n priority_threshold_minutes, priority_facet,\n current_schema_version, list_schema, current_list_schema_version\n ), snapshot AS (\n INSERT INTO lt_role_schemas (role, version, form_schema, metadata_schema, change_summary)\n SELECT role, current_schema_version, form_schema, metadata_schema, $26\n FROM updated\n WHERE ($6::boolean OR $8::boolean) AND current_schema_version IS NOT NULL\n ON CONFLICT (role, version) DO NOTHING\n ), list_snapshot AS (\n INSERT INTO lt_role_list_schemas (role, version, list_schema, change_summary)\n SELECT role, current_list_schema_version, list_schema, $26\n FROM updated\n WHERE $29::boolean AND current_list_schema_version IS NOT NULL\n ON CONFLICT (role, version) DO NOTHING\n ), upstream_prune AS (\n DELETE FROM lt_role_upstreams\n WHERE $27::boolean AND role = $1 AND upstream_role <> ALL($28::text[])\n ), upstream_add AS (\n INSERT INTO lt_role_upstreams (role, upstream_role)\n SELECT $1, u FROM unnest($28::text[]) AS u\n WHERE $27::boolean\n ON CONFLICT DO NOTHING\n )\n SELECT * FROM updated";
|
|
46
|
+
export declare const UPDATE_ROLE_METADATA = "\n WITH updated AS (\n UPDATE lt_roles SET\n title = CASE WHEN $2::boolean THEN $3 ELSE title END,\n description = CASE WHEN $4::boolean THEN $5 ELSE description END,\n form_schema = CASE WHEN $6::boolean THEN $7::jsonb ELSE form_schema END,\n metadata_schema = CASE WHEN $8::boolean THEN $9::jsonb ELSE metadata_schema END,\n properties = CASE WHEN $10::boolean THEN COALESCE($11::jsonb, '{}'::jsonb) ELSE properties END,\n ops_visible = CASE WHEN $12::boolean THEN $13::boolean ELSE ops_visible END,\n parent_role = CASE WHEN $14::boolean THEN $15 ELSE parent_role END,\n sla_minutes = CASE WHEN $16::boolean THEN $17::numeric ELSE sla_minutes END,\n target_per_hour = CASE WHEN $18::boolean THEN $19::numeric ELSE target_per_hour END,\n worker_count = CASE WHEN $20::boolean THEN $21::int ELSE worker_count END,\n priority_threshold_minutes\n = CASE WHEN $22::boolean THEN $23::numeric ELSE priority_threshold_minutes END,\n priority_facet = CASE WHEN $24::boolean THEN $25 ELSE priority_facet END,\n list_schema = CASE WHEN $29::boolean THEN $30::jsonb ELSE list_schema END,\n default_pins = CASE WHEN $31::boolean THEN $32::jsonb ELSE default_pins END,\n current_schema_version = CASE\n WHEN ($6::boolean AND $7::jsonb IS DISTINCT FROM form_schema)\n OR ($8::boolean AND $9::jsonb IS DISTINCT FROM metadata_schema)\n THEN COALESCE(current_schema_version, 0) + 1\n ELSE current_schema_version END,\n current_list_schema_version = CASE\n WHEN $29::boolean AND $30::jsonb IS DISTINCT FROM list_schema\n THEN COALESCE(current_list_schema_version, 0) + 1\n ELSE current_list_schema_version END\n WHERE role = $1\n RETURNING\n role, title, description, form_schema, metadata_schema, properties,\n ops_visible, parent_role, sla_minutes, target_per_hour, worker_count,\n priority_threshold_minutes, priority_facet,\n current_schema_version, list_schema, current_list_schema_version,\n default_pins\n ), snapshot AS (\n INSERT INTO lt_role_schemas (role, version, form_schema, metadata_schema, change_summary)\n SELECT role, current_schema_version, form_schema, metadata_schema, $26\n FROM updated\n WHERE ($6::boolean OR $8::boolean) AND current_schema_version IS NOT NULL\n ON CONFLICT (role, version) DO NOTHING\n ), list_snapshot AS (\n INSERT INTO lt_role_list_schemas (role, version, list_schema, change_summary)\n SELECT role, current_list_schema_version, list_schema, $26\n FROM updated\n WHERE $29::boolean AND current_list_schema_version IS NOT NULL\n ON CONFLICT (role, version) DO NOTHING\n ), upstream_prune AS (\n DELETE FROM lt_role_upstreams\n WHERE $27::boolean AND role = $1 AND upstream_role <> ALL($28::text[])\n ), upstream_add AS (\n INSERT INTO lt_role_upstreams (role, upstream_role)\n SELECT $1, u FROM unnest($28::text[]) AS u\n WHERE $27::boolean\n ON CONFLICT DO NOTHING\n )\n SELECT * FROM updated";
|
|
44
47
|
export declare const GET_ROLE_FORM_SCHEMA = "\n SELECT form_schema FROM lt_roles WHERE role = $1";
|
|
45
48
|
export declare const GET_ROLE_METADATA_SCHEMA = "\n SELECT metadata_schema FROM lt_roles WHERE role = $1";
|
|
46
49
|
export declare const GET_ROLE_UPSTREAMS = "\n SELECT upstream_role FROM lt_role_upstreams WHERE role = $1 ORDER BY upstream_role";
|
|
@@ -58,7 +61,7 @@ export declare const GET_ROLE_LIST_SCHEMA_VERSION = "\n SELECT s.role, s.versio
|
|
|
58
61
|
* never versioned its list schema still answers, with version NULL).
|
|
59
62
|
*/
|
|
60
63
|
export declare const GET_ROLE_LIST_SCHEMA_CURRENT = "\n SELECT r.role, r.current_list_schema_version AS version, r.list_schema,\n s.change_summary, s.created_at,\n r.current_list_schema_version AS latest_version\n FROM lt_roles r\n LEFT JOIN lt_role_list_schemas s\n ON s.role = r.role AND s.version = r.current_list_schema_version\n WHERE r.role = $1";
|
|
61
|
-
export declare const LIST_ROLES_WITH_DETAILS = "\n WITH\n user_counts AS (\n SELECT role, COUNT(DISTINCT user_id)::int AS cnt\n FROM lt_user_roles\n GROUP BY role\n ),\n chain_counts AS (\n SELECT role, COUNT(*)::int AS cnt\n FROM (\n SELECT source_role AS role FROM lt_config_role_escalations\n UNION ALL\n SELECT target_role AS role FROM lt_config_role_escalations\n ) c\n GROUP BY role\n ),\n workflow_counts AS (\n SELECT role, COUNT(*)::int AS cnt\n FROM lt_config_roles\n GROUP BY role\n ),\n upstreams AS (\n SELECT role, array_agg(upstream_role ORDER BY upstream_role) AS ups\n FROM lt_role_upstreams\n GROUP BY role\n )\n SELECT\n r.role,\n r.title,\n r.description,\n r.form_schema,\n r.metadata_schema,\n r.properties,\n r.ops_visible,\n r.parent_role,\n r.sla_minutes,\n r.target_per_hour,\n r.worker_count,\n r.priority_threshold_minutes,\n r.priority_facet,\n r.current_schema_version,\n r.list_schema,\n r.current_list_schema_version,\n COALESCE(up.ups, '{}') AS upstream_roles,\n COALESCE(uc.cnt, 0) AS user_count,\n COALESCE(cc.cnt, 0) AS chain_count,\n COALESCE(wc.cnt, 0) AS workflow_count\n FROM lt_roles r\n LEFT JOIN user_counts uc ON uc.role = r.role\n LEFT JOIN chain_counts cc ON cc.role = r.role\n LEFT JOIN workflow_counts wc ON wc.role = r.role\n LEFT JOIN upstreams up ON up.role = r.role\n ORDER BY r.role";
|
|
64
|
+
export declare const LIST_ROLES_WITH_DETAILS = "\n WITH\n user_counts AS (\n SELECT role, COUNT(DISTINCT user_id)::int AS cnt\n FROM lt_user_roles\n GROUP BY role\n ),\n chain_counts AS (\n SELECT role, COUNT(*)::int AS cnt\n FROM (\n SELECT source_role AS role FROM lt_config_role_escalations\n UNION ALL\n SELECT target_role AS role FROM lt_config_role_escalations\n ) c\n GROUP BY role\n ),\n workflow_counts AS (\n SELECT role, COUNT(*)::int AS cnt\n FROM lt_config_roles\n GROUP BY role\n ),\n upstreams AS (\n SELECT role, array_agg(upstream_role ORDER BY upstream_role) AS ups\n FROM lt_role_upstreams\n GROUP BY role\n )\n SELECT\n r.role,\n r.title,\n r.description,\n r.form_schema,\n r.metadata_schema,\n r.properties,\n r.ops_visible,\n r.parent_role,\n r.sla_minutes,\n r.target_per_hour,\n r.worker_count,\n r.priority_threshold_minutes,\n r.priority_facet,\n r.current_schema_version,\n r.list_schema,\n r.current_list_schema_version,\n r.default_pins,\n COALESCE(up.ups, '{}') AS upstream_roles,\n COALESCE(uc.cnt, 0) AS user_count,\n COALESCE(cc.cnt, 0) AS chain_count,\n COALESCE(wc.cnt, 0) AS workflow_count\n FROM lt_roles r\n LEFT JOIN user_counts uc ON uc.role = r.role\n LEFT JOIN chain_counts cc ON cc.role = r.role\n LEFT JOIN workflow_counts wc ON wc.role = r.role\n LEFT JOIN upstreams up ON up.role = r.role\n ORDER BY r.role";
|
|
62
65
|
export declare const COUNT_USER_ROLE_REFS = "\n SELECT COUNT(*)::int AS cnt FROM lt_user_roles WHERE role = $1";
|
|
63
66
|
export declare const COUNT_CHAIN_REFS = "\n SELECT COUNT(*)::int AS cnt\n FROM lt_config_role_escalations\n WHERE source_role = $1 OR target_role = $1";
|
|
64
67
|
export declare const COUNT_WORKFLOW_REFS = "\n SELECT COUNT(*)::int AS cnt FROM lt_config_roles WHERE role = $1";
|
|
@@ -73,6 +73,9 @@ exports.DELETE_ROLE = `
|
|
|
73
73
|
* of the form/metadata pair: its own current_list_schema_version and its own
|
|
74
74
|
* snapshot table (lt_role_list_schemas), so a list-view edit never advances the
|
|
75
75
|
* resolve form's version. It shares $26 as the change summary.
|
|
76
|
+
*
|
|
77
|
+
* default_pins ($31 = provided sentinel, $32 = value) is unversioned config:
|
|
78
|
+
* the pinned-view seeds a role hands its members.
|
|
76
79
|
*/
|
|
77
80
|
exports.UPDATE_ROLE_METADATA = `
|
|
78
81
|
WITH updated AS (
|
|
@@ -91,6 +94,7 @@ exports.UPDATE_ROLE_METADATA = `
|
|
|
91
94
|
= CASE WHEN $22::boolean THEN $23::numeric ELSE priority_threshold_minutes END,
|
|
92
95
|
priority_facet = CASE WHEN $24::boolean THEN $25 ELSE priority_facet END,
|
|
93
96
|
list_schema = CASE WHEN $29::boolean THEN $30::jsonb ELSE list_schema END,
|
|
97
|
+
default_pins = CASE WHEN $31::boolean THEN $32::jsonb ELSE default_pins END,
|
|
94
98
|
current_schema_version = CASE
|
|
95
99
|
WHEN ($6::boolean AND $7::jsonb IS DISTINCT FROM form_schema)
|
|
96
100
|
OR ($8::boolean AND $9::jsonb IS DISTINCT FROM metadata_schema)
|
|
@@ -105,7 +109,8 @@ exports.UPDATE_ROLE_METADATA = `
|
|
|
105
109
|
role, title, description, form_schema, metadata_schema, properties,
|
|
106
110
|
ops_visible, parent_role, sla_minutes, target_per_hour, worker_count,
|
|
107
111
|
priority_threshold_minutes, priority_facet,
|
|
108
|
-
current_schema_version, list_schema, current_list_schema_version
|
|
112
|
+
current_schema_version, list_schema, current_list_schema_version,
|
|
113
|
+
default_pins
|
|
109
114
|
), snapshot AS (
|
|
110
115
|
INSERT INTO lt_role_schemas (role, version, form_schema, metadata_schema, change_summary)
|
|
111
116
|
SELECT role, current_schema_version, form_schema, metadata_schema, $26
|
|
@@ -239,6 +244,7 @@ exports.LIST_ROLES_WITH_DETAILS = `
|
|
|
239
244
|
r.current_schema_version,
|
|
240
245
|
r.list_schema,
|
|
241
246
|
r.current_list_schema_version,
|
|
247
|
+
r.default_pins,
|
|
242
248
|
COALESCE(up.ups, '{}') AS upstream_roles,
|
|
243
249
|
COALESCE(uc.cnt, 0) AS user_count,
|
|
244
250
|
COALESCE(cc.cnt, 0) AS chain_count,
|
|
@@ -54,6 +54,17 @@ export interface RoleDetail {
|
|
|
54
54
|
list_schema: Record<string, any> | null;
|
|
55
55
|
/** Version of the live list_schema; null until the role first carries one. */
|
|
56
56
|
current_list_schema_version: number | null;
|
|
57
|
+
/**
|
|
58
|
+
* Pinned-view seeds this role hands its members: [{ label, url, badge? }].
|
|
59
|
+
* On first render, a member without an own pin of the same label sees these
|
|
60
|
+
* in their Pinned nav section (marked role-provided); users promote, hide,
|
|
61
|
+
* or reorder them through their own preferences. URLs only — never data.
|
|
62
|
+
*/
|
|
63
|
+
default_pins: {
|
|
64
|
+
label: string;
|
|
65
|
+
url: string;
|
|
66
|
+
badge?: boolean;
|
|
67
|
+
}[] | null;
|
|
57
68
|
/**
|
|
58
69
|
* Roles this station draws input from that live in OTHER sequences.
|
|
59
70
|
* parent_role is the single "prior step" placing the role in one sequence;
|
|
@@ -109,6 +120,11 @@ export interface UpdateRoleInput {
|
|
|
109
120
|
metadata_schema?: Record<string, any> | null;
|
|
110
121
|
/** JSON contract that richly formats this role's escalation list page. */
|
|
111
122
|
list_schema?: Record<string, any> | null;
|
|
123
|
+
default_pins?: {
|
|
124
|
+
label: string;
|
|
125
|
+
url: string;
|
|
126
|
+
badge?: boolean;
|
|
127
|
+
}[] | null;
|
|
112
128
|
properties?: Record<string, any> | null;
|
|
113
129
|
ops_visible?: boolean;
|
|
114
130
|
parent_role?: string | null;
|
|
@@ -5,3 +5,4 @@ export { isSuperAdmin, isGroupAdmin, canManageRole, hasGlobalEscalationAccess, h
|
|
|
5
5
|
export { READ_SCOPES, WRITE_SCOPES, DEFAULT_READ_SCOPE, DEFAULT_WRITE_SCOPE, isValidReadScope, isValidWriteScope, isValidScopePair, effectiveScope, } from './scope';
|
|
6
6
|
export { verifyPassword } from './auth';
|
|
7
7
|
export { seedAdmin } from './seed-admin';
|
|
8
|
+
export { getPreferences, patchPreferences, PREFERENCES_MAX_BYTES } from './preferences';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
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.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");
|
|
@@ -39,3 +39,7 @@ var auth_1 = require("./auth");
|
|
|
39
39
|
Object.defineProperty(exports, "verifyPassword", { enumerable: true, get: function () { return auth_1.verifyPassword; } });
|
|
40
40
|
var seed_admin_1 = require("./seed-admin");
|
|
41
41
|
Object.defineProperty(exports, "seedAdmin", { enumerable: true, get: function () { return seed_admin_1.seedAdmin; } });
|
|
42
|
+
var preferences_1 = require("./preferences");
|
|
43
|
+
Object.defineProperty(exports, "getPreferences", { enumerable: true, get: function () { return preferences_1.getPreferences; } });
|
|
44
|
+
Object.defineProperty(exports, "patchPreferences", { enumerable: true, get: function () { return preferences_1.patchPreferences; } });
|
|
45
|
+
Object.defineProperty(exports, "PREFERENCES_MAX_BYTES", { enumerable: true, get: function () { return preferences_1.PREFERENCES_MAX_BYTES; } });
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-user preferences — a generic JSON store for presentation state (pinned
|
|
3
|
+
* views are the first tenant, not the schema). Preferences carry URLs and UI
|
|
4
|
+
* choices only, never data and never authorization.
|
|
5
|
+
*/
|
|
6
|
+
/** Server-side ceiling on the stored document (the API rejects beyond it). */
|
|
7
|
+
export declare const PREFERENCES_MAX_BYTES: number;
|
|
8
|
+
export declare function getPreferences(userId: string): Promise<Record<string, unknown>>;
|
|
9
|
+
/**
|
|
10
|
+
* Shallow-merge `patch` into the user's preferences in ONE guarded UPDATE:
|
|
11
|
+
* top-level keys overwrite, a `null` value deletes its key, and the statement
|
|
12
|
+
* refuses to commit a document over the size cap (returns null → 413 at the
|
|
13
|
+
* API). No read-then-write — concurrent patches serialize on the row.
|
|
14
|
+
*/
|
|
15
|
+
export declare function patchPreferences(userId: string, patch: Record<string, unknown>): Promise<Record<string, unknown> | null>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PREFERENCES_MAX_BYTES = void 0;
|
|
4
|
+
exports.getPreferences = getPreferences;
|
|
5
|
+
exports.patchPreferences = patchPreferences;
|
|
6
|
+
const db_1 = require("../../lib/db");
|
|
7
|
+
/**
|
|
8
|
+
* Per-user preferences — a generic JSON store for presentation state (pinned
|
|
9
|
+
* views are the first tenant, not the schema). Preferences carry URLs and UI
|
|
10
|
+
* choices only, never data and never authorization.
|
|
11
|
+
*/
|
|
12
|
+
/** Server-side ceiling on the stored document (the API rejects beyond it). */
|
|
13
|
+
exports.PREFERENCES_MAX_BYTES = 32 * 1024;
|
|
14
|
+
async function getPreferences(userId) {
|
|
15
|
+
const { rows } = await (0, db_1.getPool)().query('SELECT preferences FROM lt_users WHERE id = $1', [userId]);
|
|
16
|
+
return rows[0]?.preferences ?? {};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Shallow-merge `patch` into the user's preferences in ONE guarded UPDATE:
|
|
20
|
+
* top-level keys overwrite, a `null` value deletes its key, and the statement
|
|
21
|
+
* refuses to commit a document over the size cap (returns null → 413 at the
|
|
22
|
+
* API). No read-then-write — concurrent patches serialize on the row.
|
|
23
|
+
*/
|
|
24
|
+
async function patchPreferences(userId, patch) {
|
|
25
|
+
const deletions = Object.keys(patch).filter((k) => patch[k] === null);
|
|
26
|
+
const additions = {};
|
|
27
|
+
for (const [k, v] of Object.entries(patch)) {
|
|
28
|
+
if (v !== null)
|
|
29
|
+
additions[k] = v;
|
|
30
|
+
}
|
|
31
|
+
const { rows } = await (0, db_1.getPool)().query(`UPDATE lt_users u
|
|
32
|
+
SET preferences = ((COALESCE(u.preferences, '{}'::jsonb) || $2::jsonb) - $3::text[]),
|
|
33
|
+
updated_at = NOW()
|
|
34
|
+
WHERE u.id = $1
|
|
35
|
+
AND length(((COALESCE(u.preferences, '{}'::jsonb) || $2::jsonb) - $3::text[])::text) <= $4
|
|
36
|
+
RETURNING u.preferences`, [userId, JSON.stringify(additions), deletions, exports.PREFERENCES_MAX_BYTES]);
|
|
37
|
+
return rows[0]?.preferences ?? null;
|
|
38
|
+
}
|
|
@@ -568,6 +568,20 @@ export declare const updateRoleSchema: z.ZodObject<{
|
|
|
568
568
|
priority_threshold_minutes: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
569
569
|
priority_facet: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
570
570
|
upstream_roles: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString, "many">>>;
|
|
571
|
+
list_schema: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodAny>>>;
|
|
572
|
+
default_pins: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
573
|
+
label: z.ZodString;
|
|
574
|
+
url: z.ZodString;
|
|
575
|
+
badge: z.ZodOptional<z.ZodBoolean>;
|
|
576
|
+
}, "strip", z.ZodTypeAny, {
|
|
577
|
+
url: string;
|
|
578
|
+
label: string;
|
|
579
|
+
badge?: boolean | undefined;
|
|
580
|
+
}, {
|
|
581
|
+
url: string;
|
|
582
|
+
label: string;
|
|
583
|
+
badge?: boolean | undefined;
|
|
584
|
+
}>, "many">>>;
|
|
571
585
|
change_summary: z.ZodOptional<z.ZodString>;
|
|
572
586
|
}, "strip", z.ZodTypeAny, {
|
|
573
587
|
role: string;
|
|
@@ -576,6 +590,12 @@ export declare const updateRoleSchema: z.ZodObject<{
|
|
|
576
590
|
title?: string | null | undefined;
|
|
577
591
|
properties?: Record<string, any> | null | undefined;
|
|
578
592
|
metadata_schema?: Record<string, any> | null | undefined;
|
|
593
|
+
list_schema?: Record<string, any> | null | undefined;
|
|
594
|
+
default_pins?: {
|
|
595
|
+
url: string;
|
|
596
|
+
label: string;
|
|
597
|
+
badge?: boolean | undefined;
|
|
598
|
+
}[] | null | undefined;
|
|
579
599
|
ops_visible?: boolean | undefined;
|
|
580
600
|
parent_role?: string | null | undefined;
|
|
581
601
|
sla_minutes?: number | null | undefined;
|
|
@@ -592,6 +612,12 @@ export declare const updateRoleSchema: z.ZodObject<{
|
|
|
592
612
|
title?: string | null | undefined;
|
|
593
613
|
properties?: Record<string, any> | null | undefined;
|
|
594
614
|
metadata_schema?: Record<string, any> | null | undefined;
|
|
615
|
+
list_schema?: Record<string, any> | null | undefined;
|
|
616
|
+
default_pins?: {
|
|
617
|
+
url: string;
|
|
618
|
+
label: string;
|
|
619
|
+
badge?: boolean | undefined;
|
|
620
|
+
}[] | null | undefined;
|
|
595
621
|
ops_visible?: boolean | undefined;
|
|
596
622
|
parent_role?: string | null | undefined;
|
|
597
623
|
sla_minutes?: number | null | undefined;
|
|
@@ -250,6 +250,12 @@ exports.updateRoleSchema = zod_1.z.object({
|
|
|
250
250
|
priority_threshold_minutes: zod_1.z.number().min(0).nullable().optional().describe('Max age in minutes before a pending unclaimed escalation counts toward the Pace Board priority count. Falls back to sla_minutes when null.'),
|
|
251
251
|
priority_facet: zod_1.z.string().regex(facet_sql_1.FACET_KEY).nullable().optional().describe('lt_escalations.metadata key holding the age origin for the priority count as an ISO 8601 UTC timestamp (e.g. authorized_at). Falls back to created_at when null. When set, items missing the key or holding an unparseable value are not counted.'),
|
|
252
252
|
upstream_roles: zod_1.z.array(zod_1.z.string()).nullable().optional().describe('Replace the set of roles this station draws input from across other sequences (parent_role stays the single prior step in its own sequence). Omitted = preserve; null or [] = clear.'),
|
|
253
|
+
list_schema: zod_1.z.record(zod_1.z.any()).nullable().optional().describe('JSON contract (x-lt-* markup) that richly formats this role\'s escalation LIST page. Versioned independently of form_schema; the list always renders the latest version.'),
|
|
254
|
+
default_pins: zod_1.z.array(zod_1.z.object({
|
|
255
|
+
label: zod_1.z.string().describe('Pin label shown in the member\'s Pinned nav section'),
|
|
256
|
+
url: zod_1.z.string().describe('Dashboard-relative deep link (must start with /)'),
|
|
257
|
+
badge: zod_1.z.boolean().optional().describe('Render a live count beside the label (escalations-list URLs)'),
|
|
258
|
+
})).nullable().optional().describe('Pinned-view seeds handed to every member of this role. Members promote, hide, or reorder them via their own preferences. Null clears.'),
|
|
253
259
|
change_summary: zod_1.z.string().optional().describe('Recorded on the schema version snapshot when this update changes form_schema or metadata_schema'),
|
|
254
260
|
});
|
|
255
261
|
exports.getRoleSchemaSchema = zod_1.z.object({
|
|
@@ -194,9 +194,10 @@ function registerUserTools(server) {
|
|
|
194
194
|
server.registerTool('update_role', {
|
|
195
195
|
title: 'Update Role',
|
|
196
196
|
description: 'Update role metadata with PATCH semantics — omitted fields keep their ' +
|
|
197
|
-
'values. Covers display name, description, form/metadata schemas,
|
|
198
|
-
'free properties bag, ops_visible flag, parent role,
|
|
199
|
-
'
|
|
197
|
+
'values. Covers display name, description, form/metadata/list schemas, ' +
|
|
198
|
+
'the free properties bag, ops_visible flag, parent role, default_pins ' +
|
|
199
|
+
'(member pinned-view seeds), and the typed operational targets ' +
|
|
200
|
+
'(sla_minutes, target_per_hour, worker_count, ' +
|
|
200
201
|
'priority_threshold_minutes, priority_facet).',
|
|
201
202
|
inputSchema: schemas_1.updateRoleSchema,
|
|
202
203
|
}, async (args) => {
|
|
@@ -214,6 +215,8 @@ function registerUserTools(server) {
|
|
|
214
215
|
priority_threshold_minutes: args.priority_threshold_minutes,
|
|
215
216
|
priority_facet: args.priority_facet,
|
|
216
217
|
upstream_roles: args.upstream_roles,
|
|
218
|
+
list_schema: args.list_schema,
|
|
219
|
+
default_pins: args.default_pins,
|
|
217
220
|
change_summary: args.change_summary,
|
|
218
221
|
});
|
|
219
222
|
if (!updated) {
|