@hotmeshio/long-tail 0.10.1 → 0.10.3

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.
Files changed (311) hide show
  1. package/README.md +1 -0
  2. package/build/api/bot-accounts.d.ts +4 -0
  3. package/build/api/bot-accounts.js +3 -1
  4. package/build/api/escalations/metadata.js +21 -1
  5. package/build/api/escalations/resolve.d.ts +8 -0
  6. package/build/api/escalations/resolve.js +82 -3
  7. package/build/api/me.d.ts +16 -0
  8. package/build/api/me.js +79 -0
  9. package/build/api/roles.d.ts +8 -0
  10. package/build/api/roles.js +14 -0
  11. package/build/bin/ltc.js +10 -1
  12. package/build/lib/cli/client.d.ts +4 -1
  13. package/build/lib/cli/client.js +4 -2
  14. package/build/lib/db/schemas/022_user_preferences.sql +18 -0
  15. package/build/lib/db/schemas/023_role_enforce_schema.sql +18 -0
  16. package/build/lib/typed-resolution.d.ts +35 -0
  17. package/build/lib/typed-resolution.js +37 -0
  18. package/build/modules/config.d.ts +1 -0
  19. package/build/modules/config.js +5 -0
  20. package/build/routes/bot-accounts.js +3 -1
  21. package/build/routes/index.js +2 -0
  22. package/build/routes/me.d.ts +2 -0
  23. package/build/routes/me.js +57 -0
  24. package/build/sdk/index.d.ts +10 -0
  25. package/build/sdk/index.js +25 -0
  26. package/build/services/escalation/crud.d.ts +18 -6
  27. package/build/services/escalation/crud.js +18 -2
  28. package/build/services/escalation/index.d.ts +1 -0
  29. package/build/services/escalation/index.js +1 -0
  30. package/build/services/escalation/resolver-validation.d.ts +28 -0
  31. package/build/services/escalation/resolver-validation.js +95 -0
  32. package/build/services/escalation/sql.d.ts +12 -2
  33. package/build/services/escalation/sql.js +22 -2
  34. package/build/services/iam/bots.d.ts +4 -1
  35. package/build/services/iam/bots.js +5 -3
  36. package/build/services/iam/sql.d.ts +2 -2
  37. package/build/services/iam/sql.js +15 -1
  38. package/build/services/role/enforcement-cache.d.ts +21 -0
  39. package/build/services/role/enforcement-cache.js +0 -0
  40. package/build/services/role/index.js +6 -0
  41. package/build/services/role/sql.d.ts +15 -2
  42. package/build/services/role/sql.js +21 -2
  43. package/build/services/role/types.d.ts +25 -0
  44. package/build/services/user/index.d.ts +1 -0
  45. package/build/services/user/index.js +5 -1
  46. package/build/services/user/preferences.d.ts +15 -0
  47. package/build/services/user/preferences.js +38 -0
  48. package/build/shared/form-validation/field-validator.d.ts +45 -0
  49. package/build/shared/form-validation/field-validator.js +214 -0
  50. package/build/shared/form-validation/index.d.ts +11 -0
  51. package/build/shared/form-validation/index.js +27 -0
  52. package/build/shared/form-validation/validate-resolver-payload.d.ts +41 -0
  53. package/build/shared/form-validation/validate-resolver-payload.js +62 -0
  54. package/build/shared/form-validation/x-lt-bind.d.ts +41 -0
  55. package/build/shared/form-validation/x-lt-bind.js +110 -0
  56. package/build/shared/form-validation/x-lt-help.d.ts +21 -0
  57. package/build/shared/form-validation/x-lt-help.js +91 -0
  58. package/build/shared/form-validation/x-lt-show-if.d.ts +7 -0
  59. package/build/shared/form-validation/x-lt-show-if.js +84 -0
  60. package/build/system/mcp-servers/admin/schemas.d.ts +29 -0
  61. package/build/system/mcp-servers/admin/schemas.js +7 -0
  62. package/build/system/mcp-servers/admin/users.js +8 -3
  63. package/build/system/mcp-servers/human-queue-schemas.d.ts +4 -4
  64. package/build/system/mcp-servers/human-queue-schemas.js +4 -1
  65. package/build/system/mcp-servers/human-queue.js +41 -2
  66. package/build/system/seed/tool-manifests-admin.d.ts +167 -0
  67. package/build/system/seed/tool-manifests-admin.js +1 -1
  68. package/build/tsconfig.tsbuildinfo +1 -1
  69. package/build/types/sdk.d.ts +6 -1
  70. package/build/types/validation.d.ts +43 -0
  71. package/build/types/validation.js +28 -0
  72. package/dashboard/dist/assets/{AdminDashboard-D7Amh-EJ.js → AdminDashboard-DQLGybZ9.js} +2 -2
  73. package/dashboard/dist/assets/{AdminDashboard-D7Amh-EJ.js.map → AdminDashboard-DQLGybZ9.js.map} +1 -1
  74. package/dashboard/dist/assets/AgentConfigPage-4JgMpuYJ.js +16 -0
  75. package/dashboard/dist/assets/AgentConfigPage-4JgMpuYJ.js.map +1 -0
  76. package/dashboard/dist/assets/{AgentDetailPage-Dy3Qvlfk.js → AgentDetailPage-DCgKokgX.js} +3 -3
  77. package/dashboard/dist/assets/{AgentDetailPage-Dy3Qvlfk.js.map → AgentDetailPage-DCgKokgX.js.map} +1 -1
  78. package/dashboard/dist/assets/{AgentsPage-D7WePZ0o.js → AgentsPage-BK_8VKZO.js} +2 -2
  79. package/dashboard/dist/assets/{AgentsPage-D7WePZ0o.js.map → AgentsPage-BK_8VKZO.js.map} +1 -1
  80. package/dashboard/dist/assets/AvailableEscalationsPage-Dp1rsIHC.js +2 -0
  81. package/dashboard/dist/assets/AvailableEscalationsPage-Dp1rsIHC.js.map +1 -0
  82. package/dashboard/dist/assets/BotPicker-DvUnYEJk.js +2 -0
  83. package/dashboard/dist/assets/BotPicker-DvUnYEJk.js.map +1 -0
  84. package/dashboard/dist/assets/{CapabilitiesPage-3VTLEPGO.js → CapabilitiesPage-CJ5ldY8w.js} +2 -2
  85. package/dashboard/dist/assets/{CapabilitiesPage-3VTLEPGO.js.map → CapabilitiesPage-CJ5ldY8w.js.map} +1 -1
  86. package/dashboard/dist/assets/{CollapsibleSection-BYgeZz9M.js → CollapsibleSection-BXOpfs3z.js} +2 -2
  87. package/dashboard/dist/assets/{CollapsibleSection-BYgeZz9M.js.map → CollapsibleSection-BXOpfs3z.js.map} +1 -1
  88. package/dashboard/dist/assets/CountdownTimer-D20FNwS-.js +2 -0
  89. package/dashboard/dist/assets/CountdownTimer-D20FNwS-.js.map +1 -0
  90. package/dashboard/dist/assets/{CredentialsPage-CaH3J3SE.js → CredentialsPage-vZ2psNnd.js} +2 -2
  91. package/dashboard/dist/assets/{CredentialsPage-CaH3J3SE.js.map → CredentialsPage-vZ2psNnd.js.map} +1 -1
  92. package/dashboard/dist/assets/{CronLabel-Bma_4AC2.js → CronLabel-KRkqNSYs.js} +2 -2
  93. package/dashboard/dist/assets/{CronLabel-Bma_4AC2.js.map → CronLabel-KRkqNSYs.js.map} +1 -1
  94. package/dashboard/dist/assets/{CustomDurationPicker-BxyjEX27.js → CustomDurationPicker-C-vGsrFl.js} +2 -2
  95. package/dashboard/dist/assets/CustomDurationPicker-C-vGsrFl.js.map +1 -0
  96. package/dashboard/dist/assets/{DropZone-zxH-9B8c.js → DropZone-C3NdMtwK.js} +2 -2
  97. package/dashboard/dist/assets/{DropZone-zxH-9B8c.js.map → DropZone-C3NdMtwK.js.map} +1 -1
  98. package/dashboard/dist/assets/{ElapsedCell-Dr1cEwoi.js → ElapsedCell-DNH-XHOS.js} +2 -2
  99. package/dashboard/dist/assets/{ElapsedCell-Dr1cEwoi.js.map → ElapsedCell-DNH-XHOS.js.map} +1 -1
  100. package/dashboard/dist/assets/{EscalationListSchemaPage-CLdsR-hK.js → EscalationListSchemaPage-BIW1qxjC.js} +3 -3
  101. package/dashboard/dist/assets/{EscalationListSchemaPage-CLdsR-hK.js.map → EscalationListSchemaPage-BIW1qxjC.js.map} +1 -1
  102. package/dashboard/dist/assets/{EscalationSchemaPage-DnEnvolM.js → EscalationSchemaPage-Fj2IwQXQ.js} +2 -2
  103. package/dashboard/dist/assets/{EscalationSchemaPage-DnEnvolM.js.map → EscalationSchemaPage-Fj2IwQXQ.js.map} +1 -1
  104. package/dashboard/dist/assets/{EscalationsOverview-BH8cxgLI.js → EscalationsOverview-BVUx0vZH.js} +2 -2
  105. package/dashboard/dist/assets/{EscalationsOverview-BH8cxgLI.js.map → EscalationsOverview-BVUx0vZH.js.map} +1 -1
  106. package/dashboard/dist/assets/{EventTable-p-xsfYYg.js → EventTable-Dm4zZaRl.js} +2 -2
  107. package/dashboard/dist/assets/{EventTable-p-xsfYYg.js.map → EventTable-Dm4zZaRl.js.map} +1 -1
  108. package/dashboard/dist/assets/{GraphInvokePage-Cf9c_LJ-.js → GraphInvokePage-D4f074qh.js} +2 -2
  109. package/dashboard/dist/assets/GraphInvokePage-D4f074qh.js.map +1 -0
  110. package/dashboard/dist/assets/HomePage-DQ0bb_M_.js +2 -0
  111. package/dashboard/dist/assets/HomePage-DQ0bb_M_.js.map +1 -0
  112. package/dashboard/dist/assets/ListToolbar-CItVkLQ-.js +2 -0
  113. package/dashboard/dist/assets/{ListToolbar-CDlol8XJ.js.map → ListToolbar-CItVkLQ-.js.map} +1 -1
  114. package/dashboard/dist/assets/{McpOverview-ChZ36p9t.js → McpOverview-ByYVDldF.js} +2 -2
  115. package/dashboard/dist/assets/{McpOverview-ChZ36p9t.js.map → McpOverview-ByYVDldF.js.map} +1 -1
  116. package/dashboard/dist/assets/{McpQueryDetailPage-X4j_jm3r.js → McpQueryDetailPage-DYuIdJiH.js} +2 -2
  117. package/dashboard/dist/assets/{McpQueryDetailPage-X4j_jm3r.js.map → McpQueryDetailPage-DYuIdJiH.js.map} +1 -1
  118. package/dashboard/dist/assets/{McpQueryPage-C30HsQfZ.js → McpQueryPage-C9C4mPC0.js} +2 -2
  119. package/dashboard/dist/assets/{McpQueryPage-C30HsQfZ.js.map → McpQueryPage-C9C4mPC0.js.map} +1 -1
  120. package/dashboard/dist/assets/McpRunDetailPage-CWHKhx8n.js +2 -0
  121. package/dashboard/dist/assets/McpRunDetailPage-CWHKhx8n.js.map +1 -0
  122. package/dashboard/dist/assets/{McpRunsPage-BHZHCwMM.js → McpRunsPage-DMamEjjr.js} +2 -2
  123. package/dashboard/dist/assets/{McpRunsPage-BHZHCwMM.js.map → McpRunsPage-DMamEjjr.js.map} +1 -1
  124. package/dashboard/dist/assets/{NamespacePill-BQNMfY0m.js → NamespacePill-B3YOa1xo.js} +2 -2
  125. package/dashboard/dist/assets/{NamespacePill-BQNMfY0m.js.map → NamespacePill-B3YOa1xo.js.map} +1 -1
  126. package/dashboard/dist/assets/OperationsPage-CVPDugQz.js +2 -0
  127. package/dashboard/dist/assets/OperationsPage-CVPDugQz.js.map +1 -0
  128. package/dashboard/dist/assets/{OperatorDashboard-BGJrxLMU.js → OperatorDashboard-CK-4GREp.js} +2 -2
  129. package/dashboard/dist/assets/{OperatorDashboard-BGJrxLMU.js.map → OperatorDashboard-CK-4GREp.js.map} +1 -1
  130. package/dashboard/dist/assets/{PageHeader-BIY1YvKR.js → PageHeader-poyTWcUA.js} +2 -2
  131. package/dashboard/dist/assets/{PageHeader-BIY1YvKR.js.map → PageHeader-poyTWcUA.js.map} +1 -1
  132. package/dashboard/dist/assets/{PageHeaderWithStats-TUyglVW0.js → PageHeaderWithStats-CAmspbl9.js} +2 -2
  133. package/dashboard/dist/assets/{PageHeaderWithStats-TUyglVW0.js.map → PageHeaderWithStats-CAmspbl9.js.map} +1 -1
  134. package/dashboard/dist/assets/{ProcessDetailPage-Bcp3GKFo.js → ProcessDetailPage-BBCwv1bQ.js} +2 -2
  135. package/dashboard/dist/assets/{ProcessDetailPage-Bcp3GKFo.js.map → ProcessDetailPage-BBCwv1bQ.js.map} +1 -1
  136. package/dashboard/dist/assets/{ProcessesListPage-DPrvuLoU.js → ProcessesListPage-m70xmTZx.js} +2 -2
  137. package/dashboard/dist/assets/{ProcessesListPage-DPrvuLoU.js.map → ProcessesListPage-m70xmTZx.js.map} +1 -1
  138. package/dashboard/dist/assets/RoleDetailPage-l865Cx3n.js +8 -0
  139. package/dashboard/dist/assets/RoleDetailPage-l865Cx3n.js.map +1 -0
  140. package/dashboard/dist/assets/RolePill-C0SWz9X7.js +2 -0
  141. package/dashboard/dist/assets/RolePill-C0SWz9X7.js.map +1 -0
  142. package/dashboard/dist/assets/RolesPage-Wzfjz7Wc.js +2 -0
  143. package/dashboard/dist/assets/RolesPage-Wzfjz7Wc.js.map +1 -0
  144. package/dashboard/dist/assets/RunAsSelector-DlnIolTf.js +2 -0
  145. package/dashboard/dist/assets/{RunAsSelector-Z2Yunqdf.js.map → RunAsSelector-DlnIolTf.js.map} +1 -1
  146. package/dashboard/dist/assets/{SlidePanel-DK4sWXmp.js → SlidePanel-Bm9B6zIA.js} +2 -2
  147. package/dashboard/dist/assets/{SlidePanel-DK4sWXmp.js.map → SlidePanel-Bm9B6zIA.js.map} +1 -1
  148. package/dashboard/dist/assets/{StickyPagination-CeLsnCIS.js → StickyPagination-BHF5fTt5.js} +2 -2
  149. package/dashboard/dist/assets/{StickyPagination-CeLsnCIS.js.map → StickyPagination-BHF5fTt5.js.map} +1 -1
  150. package/dashboard/dist/assets/{StreamMessageDetail-DWs7XkmH.js → StreamMessageDetail-Dgp1lzay.js} +2 -2
  151. package/dashboard/dist/assets/{StreamMessageDetail-DWs7XkmH.js.map → StreamMessageDetail-Dgp1lzay.js.map} +1 -1
  152. package/dashboard/dist/assets/{SwimlaneTimeline-Dxl9a51q.js → SwimlaneTimeline-BlptZ8lr.js} +2 -2
  153. package/dashboard/dist/assets/{SwimlaneTimeline-Dxl9a51q.js.map → SwimlaneTimeline-BlptZ8lr.js.map} +1 -1
  154. package/dashboard/dist/assets/{TagInput-CK-JhBG2.js → TagInput-CM3AV5Ky.js} +2 -2
  155. package/dashboard/dist/assets/{TagInput-CK-JhBG2.js.map → TagInput-CM3AV5Ky.js.map} +1 -1
  156. package/dashboard/dist/assets/{TaskDetailPage-DVr31zDE.js → TaskDetailPage-f5K9dVPG.js} +2 -2
  157. package/dashboard/dist/assets/{TaskDetailPage-DVr31zDE.js.map → TaskDetailPage-f5K9dVPG.js.map} +1 -1
  158. package/dashboard/dist/assets/{TaskQueuePill-C_Vo2Clc.js → TaskQueuePill-BZYmqdcv.js} +2 -2
  159. package/dashboard/dist/assets/{TaskQueuePill-C_Vo2Clc.js.map → TaskQueuePill-BZYmqdcv.js.map} +1 -1
  160. package/dashboard/dist/assets/{TasksListPage-DNGp5lfi.js → TasksListPage-BPyPG6UY.js} +2 -2
  161. package/dashboard/dist/assets/{TasksListPage-DNGp5lfi.js.map → TasksListPage-BPyPG6UY.js.map} +1 -1
  162. package/dashboard/dist/assets/{TimeAgo-j2Q4w4lY.js → TimeAgo-CBaGbueK.js} +2 -2
  163. package/dashboard/dist/assets/{TimeAgo-j2Q4w4lY.js.map → TimeAgo-CBaGbueK.js.map} +1 -1
  164. package/dashboard/dist/assets/{TimestampCell-BLEfob2C.js → TimestampCell-Z5kDrR9U.js} +2 -2
  165. package/dashboard/dist/assets/{TimestampCell-BLEfob2C.js.map → TimestampCell-Z5kDrR9U.js.map} +1 -1
  166. package/dashboard/dist/assets/ToolPill-D_-m3lUO.js +2 -0
  167. package/dashboard/dist/assets/{ToolPill-BCi101Jh.js.map → ToolPill-D_-m3lUO.js.map} +1 -1
  168. package/dashboard/dist/assets/{ToolTestPanel-ZJZT_mDP.js → ToolTestPanel-DFrP_aMx.js} +2 -2
  169. package/dashboard/dist/assets/{ToolTestPanel-ZJZT_mDP.js.map → ToolTestPanel-DFrP_aMx.js.map} +1 -1
  170. package/dashboard/dist/assets/TopicDetailPage-Cj9qXnTW.js +9 -0
  171. package/dashboard/dist/assets/TopicDetailPage-Cj9qXnTW.js.map +1 -0
  172. package/dashboard/dist/assets/{TopicsPage-Ctb_85Tw.js → TopicsPage-Dyq6niOv.js} +2 -2
  173. package/dashboard/dist/assets/{TopicsPage-Ctb_85Tw.js.map → TopicsPage-Dyq6niOv.js.map} +1 -1
  174. package/dashboard/dist/assets/{UserName-CkFpUqVK.js → UserName-DOX2P-8M.js} +2 -2
  175. package/dashboard/dist/assets/{UserName-CkFpUqVK.js.map → UserName-DOX2P-8M.js.map} +1 -1
  176. package/dashboard/dist/assets/WorkflowExecutionPage-Cb_dSIoq.js +2 -0
  177. package/dashboard/dist/assets/WorkflowExecutionPage-Cb_dSIoq.js.map +1 -0
  178. package/dashboard/dist/assets/WorkflowPill-CyYYPB7b.js +2 -0
  179. package/dashboard/dist/assets/{WorkflowPill-DHxrAkp3.js.map → WorkflowPill-CyYYPB7b.js.map} +1 -1
  180. package/dashboard/dist/assets/{WorkflowsDashboard-DOyZbqzf.js → WorkflowsDashboard-DJpMO5IY.js} +2 -2
  181. package/dashboard/dist/assets/{WorkflowsDashboard-DOyZbqzf.js.map → WorkflowsDashboard-DJpMO5IY.js.map} +1 -1
  182. package/dashboard/dist/assets/{WorkflowsOverview-CRyHvUBx.js → WorkflowsOverview-CCC_KaXz.js} +2 -2
  183. package/dashboard/dist/assets/{WorkflowsOverview-CRyHvUBx.js.map → WorkflowsOverview-CCC_KaXz.js.map} +1 -1
  184. package/dashboard/dist/assets/{YamlWorkflowDetailPage-DRBmQXY6.js → YamlWorkflowDetailPage-C3ntUyoZ.js} +11 -11
  185. package/dashboard/dist/assets/{YamlWorkflowDetailPage-DRBmQXY6.js.map → YamlWorkflowDetailPage-C3ntUyoZ.js.map} +1 -1
  186. package/dashboard/dist/assets/{YamlWorkflowsPage-HnI-9eBW.js → YamlWorkflowsPage-ju-9JDXg.js} +2 -2
  187. package/dashboard/dist/assets/{YamlWorkflowsPage-HnI-9eBW.js.map → YamlWorkflowsPage-ju-9JDXg.js.map} +1 -1
  188. package/dashboard/dist/assets/{agents-BA2CvQO9.js → agents-gs9fea8r.js} +2 -2
  189. package/dashboard/dist/assets/{agents-BA2CvQO9.js.map → agents-gs9fea8r.js.map} +1 -1
  190. package/dashboard/dist/assets/bots-DYxAHrob.js +2 -0
  191. package/dashboard/dist/assets/bots-DYxAHrob.js.map +1 -0
  192. package/dashboard/dist/assets/{capabilities-BYBKLRRI.js → capabilities-BJoxz6DJ.js} +2 -2
  193. package/dashboard/dist/assets/{capabilities-BYBKLRRI.js.map → capabilities-BJoxz6DJ.js.map} +1 -1
  194. package/dashboard/dist/assets/{controlplane-H0Ljhb-1.js → controlplane-BeDZgDDf.js} +2 -2
  195. package/dashboard/dist/assets/{controlplane-H0Ljhb-1.js.map → controlplane-BeDZgDDf.js.map} +1 -1
  196. package/dashboard/dist/assets/escalation-columns-CZ4fl0IE.js +2 -0
  197. package/dashboard/dist/assets/escalation-columns-CZ4fl0IE.js.map +1 -0
  198. package/dashboard/dist/assets/index-BMM3Xug7.js +2 -0
  199. package/dashboard/dist/assets/index-BMM3Xug7.js.map +1 -0
  200. package/dashboard/dist/assets/{index-BXrm76Hm.js → index-BMXkxgnK.js} +2 -2
  201. package/dashboard/dist/assets/{index-BXrm76Hm.js.map → index-BMXkxgnK.js.map} +1 -1
  202. package/dashboard/dist/assets/{index-CWkAN6wc.js → index-Bj1Mjjiv.js} +2 -2
  203. package/dashboard/dist/assets/{index-CWkAN6wc.js.map → index-Bj1Mjjiv.js.map} +1 -1
  204. package/dashboard/dist/assets/index-BqVb13tE.js +5 -0
  205. package/dashboard/dist/assets/index-BqVb13tE.js.map +1 -0
  206. package/dashboard/dist/assets/{index-YWvrMcqh.js → index-CGrtjUdj.js} +2 -2
  207. package/dashboard/dist/assets/{index-YWvrMcqh.js.map → index-CGrtjUdj.js.map} +1 -1
  208. package/dashboard/dist/assets/{index-DSjih1iX.js → index-CQ8cd4JZ.js} +2 -2
  209. package/dashboard/dist/assets/{index-DSjih1iX.js.map → index-CQ8cd4JZ.js.map} +1 -1
  210. package/dashboard/dist/assets/{index-D1Q8WfGN.js → index-CruL35yU.js} +2 -2
  211. package/dashboard/dist/assets/{index-D1Q8WfGN.js.map → index-CruL35yU.js.map} +1 -1
  212. package/dashboard/dist/assets/index-DAM1Dm1F.js +2 -0
  213. package/dashboard/dist/assets/index-DAM1Dm1F.js.map +1 -0
  214. package/dashboard/dist/assets/{index-CP6D_Gtw.js → index-DZ7PWRg1.js} +2 -2
  215. package/dashboard/dist/assets/{index-CP6D_Gtw.js.map → index-DZ7PWRg1.js.map} +1 -1
  216. package/dashboard/dist/assets/{index-BI-9M7z3.js → index-DfbrPOP3.js} +2 -2
  217. package/dashboard/dist/assets/{index-BI-9M7z3.js.map → index-DfbrPOP3.js.map} +1 -1
  218. package/dashboard/dist/assets/index-DwuM7Fka.js +5 -0
  219. package/dashboard/dist/assets/index-DwuM7Fka.js.map +1 -0
  220. package/dashboard/dist/assets/index-DycfrrTK.js +63 -0
  221. package/dashboard/dist/assets/index-DycfrrTK.js.map +1 -0
  222. package/dashboard/dist/assets/{index-Dx6-4esw.js → index-tbvwCdvQ.js} +2 -2
  223. package/dashboard/dist/assets/{index-Dx6-4esw.js.map → index-tbvwCdvQ.js.map} +1 -1
  224. package/dashboard/dist/assets/index-zP2ncT4m.css +1 -0
  225. package/dashboard/dist/assets/{knowledge-BVbElRHf.js → knowledge-DZnI1Fdk.js} +2 -2
  226. package/dashboard/dist/assets/{knowledge-BVbElRHf.js.map → knowledge-DZnI1Fdk.js.map} +1 -1
  227. package/dashboard/dist/assets/{mcp-CstDdowJ.js → mcp-BB_m6UyI.js} +2 -2
  228. package/dashboard/dist/assets/{mcp-CstDdowJ.js.map → mcp-BB_m6UyI.js.map} +1 -1
  229. package/dashboard/dist/assets/{mcp-query-DHUs0N8H.js → mcp-query-BTSWn0de.js} +2 -2
  230. package/dashboard/dist/assets/{mcp-query-DHUs0N8H.js.map → mcp-query-BTSWn0de.js.map} +1 -1
  231. package/dashboard/dist/assets/{pipelines-BDmAzE3U.js → pipelines-CvGQLyUz.js} +2 -2
  232. package/dashboard/dist/assets/{pipelines-BDmAzE3U.js.map → pipelines-CvGQLyUz.js.map} +1 -1
  233. package/dashboard/dist/assets/task-queues-7-sHKPsN.js +2 -0
  234. package/dashboard/dist/assets/task-queues-7-sHKPsN.js.map +1 -0
  235. package/dashboard/dist/assets/{tasks--qZocuG-.js → tasks-BbgOhCVm.js} +2 -2
  236. package/dashboard/dist/assets/{tasks--qZocuG-.js.map → tasks-BbgOhCVm.js.map} +1 -1
  237. package/dashboard/dist/assets/{topics-P3jkjMsx.js → topics-D9usuYHv.js} +2 -2
  238. package/dashboard/dist/assets/{topics-P3jkjMsx.js.map → topics-D9usuYHv.js.map} +1 -1
  239. package/dashboard/dist/assets/{useEventHooks-CqH8Pasj.js → useEventHooks-DxnqYVPg.js} +2 -2
  240. package/dashboard/dist/assets/{useEventHooks-CqH8Pasj.js.map → useEventHooks-DxnqYVPg.js.map} +1 -1
  241. package/dashboard/dist/assets/{useNamespace-aI3tPfo3.js → useNamespace-CBAn0o5z.js} +2 -2
  242. package/dashboard/dist/assets/{useNamespace-aI3tPfo3.js.map → useNamespace-CBAn0o5z.js.map} +1 -1
  243. package/dashboard/dist/assets/{useYamlActivityEvents-CPVyuW8i.js → useYamlActivityEvents-blOlKGDO.js} +2 -2
  244. package/dashboard/dist/assets/{useYamlActivityEvents-CPVyuW8i.js.map → useYamlActivityEvents-blOlKGDO.js.map} +1 -1
  245. package/dashboard/dist/assets/{users-BrcmIH7O.js → users-CYVJHgNM.js} +2 -2
  246. package/dashboard/dist/assets/{users-BrcmIH7O.js.map → users-CYVJHgNM.js.map} +1 -1
  247. package/dashboard/dist/assets/{vendor-icons-Qk9qLjF_.js → vendor-icons-B98-XxNc.js} +147 -132
  248. package/dashboard/dist/assets/vendor-icons-B98-XxNc.js.map +1 -0
  249. package/dashboard/dist/assets/{workflows-DPhX5L5C.js → workflows-csQAJF0G.js} +2 -2
  250. package/dashboard/dist/assets/{workflows-DPhX5L5C.js.map → workflows-csQAJF0G.js.map} +1 -1
  251. package/dashboard/dist/assets/{yaml-workflows-KZI2cufF.js → yaml-workflows-CctsTDby.js} +2 -2
  252. package/dashboard/dist/assets/{yaml-workflows-KZI2cufF.js.map → yaml-workflows-CctsTDby.js.map} +1 -1
  253. package/dashboard/dist/index.html +3 -3
  254. package/docs/api/http/escalations.md +16 -1
  255. package/docs/api/http/roles.md +4 -0
  256. package/docs/api/http/users.md +39 -0
  257. package/docs/api/sdk/roles.md +5 -0
  258. package/docs/api/sdk/users.md +39 -0
  259. package/docs/hitl/pinned-views.md +45 -0
  260. package/docs/hitl/x-lt-list-schema.md +37 -2
  261. package/docs/hitl/x-lt-show-if.md +11 -0
  262. package/docs/hitl/x-lt-widget.md +22 -0
  263. package/docs/hitl-guide.md +9 -5
  264. package/docs/schema-enforcement.md +149 -0
  265. package/package.json +1 -1
  266. package/dashboard/dist/assets/AgentConfigPage-CW2udbSO.js +0 -16
  267. package/dashboard/dist/assets/AgentConfigPage-CW2udbSO.js.map +0 -1
  268. package/dashboard/dist/assets/AvailableEscalationsPage-Dx51E6s_.js +0 -2
  269. package/dashboard/dist/assets/AvailableEscalationsPage-Dx51E6s_.js.map +0 -1
  270. package/dashboard/dist/assets/BotPicker-KebTxTDi.js +0 -2
  271. package/dashboard/dist/assets/BotPicker-KebTxTDi.js.map +0 -1
  272. package/dashboard/dist/assets/CountdownTimer-DFqEYmiF.js +0 -2
  273. package/dashboard/dist/assets/CountdownTimer-DFqEYmiF.js.map +0 -1
  274. package/dashboard/dist/assets/CustomDurationPicker-BxyjEX27.js.map +0 -1
  275. package/dashboard/dist/assets/GraphInvokePage-Cf9c_LJ-.js.map +0 -1
  276. package/dashboard/dist/assets/HomePage-BdCtKXAV.js +0 -2
  277. package/dashboard/dist/assets/HomePage-BdCtKXAV.js.map +0 -1
  278. package/dashboard/dist/assets/ListToolbar-CDlol8XJ.js +0 -2
  279. package/dashboard/dist/assets/McpRunDetailPage-18d7Iqfy.js +0 -2
  280. package/dashboard/dist/assets/McpRunDetailPage-18d7Iqfy.js.map +0 -1
  281. package/dashboard/dist/assets/OperationsPage-GMojwL3q.js +0 -2
  282. package/dashboard/dist/assets/OperationsPage-GMojwL3q.js.map +0 -1
  283. package/dashboard/dist/assets/RoleDetailPage-Ws3umQKQ.js +0 -8
  284. package/dashboard/dist/assets/RoleDetailPage-Ws3umQKQ.js.map +0 -1
  285. package/dashboard/dist/assets/RolePill-4LO_CuO3.js +0 -2
  286. package/dashboard/dist/assets/RolePill-4LO_CuO3.js.map +0 -1
  287. package/dashboard/dist/assets/RolesPage-D3NNU92h.js +0 -2
  288. package/dashboard/dist/assets/RolesPage-D3NNU92h.js.map +0 -1
  289. package/dashboard/dist/assets/RunAsSelector-Z2Yunqdf.js +0 -2
  290. package/dashboard/dist/assets/ToolPill-BCi101Jh.js +0 -2
  291. package/dashboard/dist/assets/TopicDetailPage-ynUkO1A8.js +0 -9
  292. package/dashboard/dist/assets/TopicDetailPage-ynUkO1A8.js.map +0 -1
  293. package/dashboard/dist/assets/WorkflowExecutionPage-CSw2aQJC.js +0 -2
  294. package/dashboard/dist/assets/WorkflowExecutionPage-CSw2aQJC.js.map +0 -1
  295. package/dashboard/dist/assets/WorkflowPill-DHxrAkp3.js +0 -2
  296. package/dashboard/dist/assets/bots-DHHnoo8x.js +0 -2
  297. package/dashboard/dist/assets/bots-DHHnoo8x.js.map +0 -1
  298. package/dashboard/dist/assets/escalation-columns-BV3Ztn7D.js +0 -2
  299. package/dashboard/dist/assets/escalation-columns-BV3Ztn7D.js.map +0 -1
  300. package/dashboard/dist/assets/index-B4FaugP1.js +0 -2
  301. package/dashboard/dist/assets/index-B4FaugP1.js.map +0 -1
  302. package/dashboard/dist/assets/index-BeFjLCIQ.js +0 -5
  303. package/dashboard/dist/assets/index-BeFjLCIQ.js.map +0 -1
  304. package/dashboard/dist/assets/index-BrEcQQ1p.css +0 -1
  305. package/dashboard/dist/assets/index-CVMA5PVQ.js +0 -2
  306. package/dashboard/dist/assets/index-CVMA5PVQ.js.map +0 -1
  307. package/dashboard/dist/assets/index-O2wWcCLo.js +0 -5
  308. package/dashboard/dist/assets/index-O2wWcCLo.js.map +0 -1
  309. package/dashboard/dist/assets/index-iX8HLLB9.js +0 -63
  310. package/dashboard/dist/assets/index-iX8HLLB9.js.map +0 -1
  311. package/dashboard/dist/assets/vendor-icons-Qk9qLjF_.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  // ─── Escalation chain queries ───────────────────────────────────────────────
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.COUNT_ACTIVE_ESCALATION_REFS = exports.COUNT_WORKFLOW_REFS = exports.COUNT_CHAIN_REFS = exports.COUNT_USER_ROLE_REFS = exports.LIST_ROLES_WITH_DETAILS = exports.GET_ROLE_LIST_SCHEMA_CURRENT = exports.GET_ROLE_LIST_SCHEMA_VERSION = exports.LIST_ROLE_LIST_SCHEMA_VERSIONS = exports.GET_ROLE_SCHEMA_CURRENT = exports.GET_ROLE_SCHEMA_VERSION = exports.LIST_ROLE_SCHEMA_VERSIONS = exports.GET_ROLE_UPSTREAMS = exports.GET_ROLE_METADATA_SCHEMA = exports.GET_ROLE_FORM_SCHEMA = exports.UPDATE_ROLE_METADATA = exports.DELETE_ROLE = exports.LIST_ROLES = exports.ENSURE_ROLE_EXISTS = exports.CHECK_ESCALATION_CHAIN_EXISTS = exports.DELETE_ESCALATION_CHAINS_BY_SOURCE = exports.DELETE_ESCALATION_CHAIN = exports.ADD_ESCALATION_CHAIN = exports.INSERT_ESCALATION_CHAIN = exports.GET_ALL_ESCALATION_CHAINS = exports.GET_ESCALATION_TARGETS = void 0;
4
+ exports.COUNT_ACTIVE_ESCALATION_REFS = exports.COUNT_WORKFLOW_REFS = exports.COUNT_CHAIN_REFS = exports.COUNT_USER_ROLE_REFS = exports.LIST_ROLES_WITH_DETAILS = exports.GET_ROLE_LIST_SCHEMA_CURRENT = exports.GET_ROLE_LIST_SCHEMA_VERSION = exports.LIST_ROLE_LIST_SCHEMA_VERSIONS = exports.GET_ROLE_SCHEMA_CURRENT = exports.GET_ROLE_SCHEMA_VERSION = exports.LIST_ROLE_SCHEMA_VERSIONS = exports.GET_ROLE_UPSTREAMS = exports.GET_ROLE_METADATA_SCHEMA = exports.LIST_ENFORCING_ROLES = exports.GET_ROLE_FORM_SCHEMA = exports.UPDATE_ROLE_METADATA = exports.DELETE_ROLE = exports.LIST_ROLES = exports.ENSURE_ROLE_EXISTS = exports.CHECK_ESCALATION_CHAIN_EXISTS = exports.DELETE_ESCALATION_CHAINS_BY_SOURCE = exports.DELETE_ESCALATION_CHAIN = exports.ADD_ESCALATION_CHAIN = exports.INSERT_ESCALATION_CHAIN = exports.GET_ALL_ESCALATION_CHAINS = exports.GET_ESCALATION_TARGETS = void 0;
5
5
  exports.GET_ESCALATION_TARGETS = `
6
6
  SELECT target_role
7
7
  FROM lt_config_role_escalations
@@ -73,6 +73,13 @@ 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.
79
+ *
80
+ * enforce_schema ($33 = provided sentinel, $34 = value) is unversioned config:
81
+ * the server-side resolver-validation opt-in. The service layer invalidates
82
+ * the enforcement cache after this statement commits.
76
83
  */
77
84
  exports.UPDATE_ROLE_METADATA = `
78
85
  WITH updated AS (
@@ -91,6 +98,8 @@ exports.UPDATE_ROLE_METADATA = `
91
98
  = CASE WHEN $22::boolean THEN $23::numeric ELSE priority_threshold_minutes END,
92
99
  priority_facet = CASE WHEN $24::boolean THEN $25 ELSE priority_facet END,
93
100
  list_schema = CASE WHEN $29::boolean THEN $30::jsonb ELSE list_schema END,
101
+ default_pins = CASE WHEN $31::boolean THEN $32::jsonb ELSE default_pins END,
102
+ enforce_schema = CASE WHEN $33::boolean THEN COALESCE($34::boolean, false) ELSE enforce_schema END,
94
103
  current_schema_version = CASE
95
104
  WHEN ($6::boolean AND $7::jsonb IS DISTINCT FROM form_schema)
96
105
  OR ($8::boolean AND $9::jsonb IS DISTINCT FROM metadata_schema)
@@ -105,7 +114,8 @@ exports.UPDATE_ROLE_METADATA = `
105
114
  role, title, description, form_schema, metadata_schema, properties,
106
115
  ops_visible, parent_role, sla_minutes, target_per_hour, worker_count,
107
116
  priority_threshold_minutes, priority_facet,
108
- current_schema_version, list_schema, current_list_schema_version
117
+ current_schema_version, list_schema, current_list_schema_version,
118
+ default_pins, enforce_schema
109
119
  ), snapshot AS (
110
120
  INSERT INTO lt_role_schemas (role, version, form_schema, metadata_schema, change_summary)
111
121
  SELECT role, current_schema_version, form_schema, metadata_schema, $26
@@ -130,6 +140,13 @@ exports.UPDATE_ROLE_METADATA = `
130
140
  SELECT * FROM updated`;
131
141
  exports.GET_ROLE_FORM_SCHEMA = `
132
142
  SELECT form_schema FROM lt_roles WHERE role = $1`;
143
+ /**
144
+ * The set of roles with server-side resolver validation turned on. Small and
145
+ * slow-changing — the enforcement cache holds it under a short TTL so the
146
+ * resolve hot path costs zero SQL when no role (or no involved role) enforces.
147
+ */
148
+ exports.LIST_ENFORCING_ROLES = `
149
+ SELECT role FROM lt_roles WHERE enforce_schema`;
133
150
  exports.GET_ROLE_METADATA_SCHEMA = `
134
151
  SELECT metadata_schema FROM lt_roles WHERE role = $1`;
135
152
  exports.GET_ROLE_UPSTREAMS = `
@@ -239,6 +256,8 @@ exports.LIST_ROLES_WITH_DETAILS = `
239
256
  r.current_schema_version,
240
257
  r.list_schema,
241
258
  r.current_list_schema_version,
259
+ r.default_pins,
260
+ r.enforce_schema,
242
261
  COALESCE(up.ups, '{}') AS upstream_roles,
243
262
  COALESCE(uc.cnt, 0) AS user_count,
244
263
  COALESCE(cc.cnt, 0) AS chain_count,
@@ -54,6 +54,24 @@ 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
+ * When true, every resolve surface validates the submitted resolverPayload
59
+ * against the escalation's resolved form schema (same pass the dashboard
60
+ * runs) and rejects violations with 422 before any state changes. Opt-in
61
+ * per role; false leaves resolution behavior unchanged.
62
+ */
63
+ enforce_schema: boolean;
64
+ /**
65
+ * Pinned-view seeds this role hands its members: [{ label, url, badge? }].
66
+ * On first render, a member without an own pin of the same label sees these
67
+ * in their Pinned nav section (marked role-provided); users promote, hide,
68
+ * or reorder them through their own preferences. URLs only — never data.
69
+ */
70
+ default_pins: {
71
+ label: string;
72
+ url: string;
73
+ badge?: boolean;
74
+ }[] | null;
57
75
  /**
58
76
  * Roles this station draws input from that live in OTHER sequences.
59
77
  * parent_role is the single "prior step" placing the role in one sequence;
@@ -109,6 +127,11 @@ export interface UpdateRoleInput {
109
127
  metadata_schema?: Record<string, any> | null;
110
128
  /** JSON contract that richly formats this role's escalation list page. */
111
129
  list_schema?: Record<string, any> | null;
130
+ default_pins?: {
131
+ label: string;
132
+ url: string;
133
+ badge?: boolean;
134
+ }[] | null;
112
135
  properties?: Record<string, any> | null;
113
136
  ops_visible?: boolean;
114
137
  parent_role?: string | null;
@@ -117,6 +140,8 @@ export interface UpdateRoleInput {
117
140
  worker_count?: number | null;
118
141
  priority_threshold_minutes?: number | null;
119
142
  priority_facet?: string | null;
143
+ /** Turn server-side resolver schema validation on/off for this role. */
144
+ enforce_schema?: boolean;
120
145
  /**
121
146
  * Replace the upstream-input set (omitted = preserve; null or [] = clear).
122
147
  * Every entry must name an existing role other than this one.
@@ -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
+ }
@@ -0,0 +1,45 @@
1
+ export interface FieldError {
2
+ field: string;
3
+ message: string;
4
+ }
5
+ interface ChecklistItem {
6
+ id: string;
7
+ label: string;
8
+ required?: boolean;
9
+ }
10
+ /**
11
+ * Resolve a checklist widget's item definitions from its `x-lt-source`
12
+ * "domain.path" against the escalation context. Missing domain/path or a
13
+ * non-array value yields an empty list.
14
+ */
15
+ export declare function resolveChecklistItems(sourcePath: unknown, ctx: Record<string, unknown> | undefined): ChecklistItem[];
16
+ /**
17
+ * The checklist completion guard (`x-lt-require-all`): every rendered item must
18
+ * be checked, except items whose definition carries `required: false` (the
19
+ * explicit opt-out). Vacuous when the source resolves to no items — never
20
+ * blocks on zero. Returns the panel message, or undefined when satisfied.
21
+ * Stricter than (and composes with) the field-level required-array entry,
22
+ * which remains the at-least-one check.
23
+ */
24
+ export declare function validateRequireAll(value: unknown, fieldSchema: Record<string, unknown> | undefined, ctx?: Record<string, unknown>): string | undefined;
25
+ /**
26
+ * Runtime type check against the field's declared JSON Schema `type`. Guards
27
+ * the payload contract for API-first callers (a form widget already produces
28
+ * the right primitive; a script or agent submitting `"1"` for a number field
29
+ * does not). Absent/empty values pass — presence is the required check's job.
30
+ */
31
+ export declare function validateFieldType(value: unknown, fieldSchema: Record<string, unknown> | undefined): string | undefined;
32
+ /**
33
+ * Per-field JSON Schema validation — subset used by the resolver form.
34
+ *
35
+ * Returns a human-readable error string when the value fails a constraint,
36
+ * or undefined when the value is valid. Callers are responsible for the
37
+ * required check (empty-when-required) before calling this for constraint checks.
38
+ *
39
+ * `ctx` is optional context (ShowIfContext-shaped) used to resolve dynamic
40
+ * constraint paths like `x-lt-minimum: "envelope.min_score"`.
41
+ */
42
+ export declare function validateFieldConstraints(value: unknown, fieldSchema: Record<string, unknown> | undefined, ctx?: Record<string, unknown>): string | undefined;
43
+ /** Full field error including required check then constraints. */
44
+ export declare function validateField(value: unknown, fieldSchema: Record<string, unknown> | undefined, isRequired: boolean, isTouched: boolean, ctx?: Record<string, unknown>): string | undefined;
45
+ export {};
@@ -0,0 +1,214 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveChecklistItems = resolveChecklistItems;
4
+ exports.validateRequireAll = validateRequireAll;
5
+ exports.validateFieldType = validateFieldType;
6
+ exports.validateFieldConstraints = validateFieldConstraints;
7
+ exports.validateField = validateField;
8
+ /**
9
+ * Resolve a checklist widget's item definitions from its `x-lt-source`
10
+ * "domain.path" against the escalation context. Missing domain/path or a
11
+ * non-array value yields an empty list.
12
+ */
13
+ function resolveChecklistItems(sourcePath, ctx) {
14
+ if (typeof sourcePath !== 'string' || !ctx)
15
+ return [];
16
+ const dot = sourcePath.indexOf('.');
17
+ if (dot === -1)
18
+ return [];
19
+ const domainObj = ctx[sourcePath.slice(0, dot)];
20
+ if (!domainObj || typeof domainObj !== 'object')
21
+ return [];
22
+ let cur = domainObj;
23
+ for (const p of sourcePath.slice(dot + 1).split('.')) {
24
+ cur = cur[p];
25
+ if (cur === undefined)
26
+ return [];
27
+ }
28
+ return Array.isArray(cur) ? cur : [];
29
+ }
30
+ /**
31
+ * The checklist completion guard (`x-lt-require-all`): every rendered item must
32
+ * be checked, except items whose definition carries `required: false` (the
33
+ * explicit opt-out). Vacuous when the source resolves to no items — never
34
+ * blocks on zero. Returns the panel message, or undefined when satisfied.
35
+ * Stricter than (and composes with) the field-level required-array entry,
36
+ * which remains the at-least-one check.
37
+ */
38
+ function validateRequireAll(value, fieldSchema, ctx) {
39
+ if (fieldSchema?.['x-lt-widget'] !== 'checklist')
40
+ return undefined;
41
+ if (fieldSchema['x-lt-require-all'] !== true)
42
+ return undefined;
43
+ const items = resolveChecklistItems(fieldSchema['x-lt-source'], ctx);
44
+ const mandatory = items.filter((i) => i.required !== false);
45
+ if (mandatory.length === 0)
46
+ return undefined;
47
+ const state = (typeof value === 'object' && value !== null && !Array.isArray(value))
48
+ ? value
49
+ : {};
50
+ const incomplete = mandatory.filter((i) => !state[i.id]).length;
51
+ if (incomplete === 0)
52
+ return undefined;
53
+ return `${incomplete} of ${mandatory.length} checks incomplete`;
54
+ }
55
+ /**
56
+ * Runtime type check against the field's declared JSON Schema `type`. Guards
57
+ * the payload contract for API-first callers (a form widget already produces
58
+ * the right primitive; a script or agent submitting `"1"` for a number field
59
+ * does not). Absent/empty values pass — presence is the required check's job.
60
+ */
61
+ function validateFieldType(value, fieldSchema) {
62
+ const declared = fieldSchema?.type;
63
+ if (typeof declared !== 'string')
64
+ return undefined;
65
+ if (value === undefined || value === null || value === '')
66
+ return undefined;
67
+ switch (declared) {
68
+ case 'string':
69
+ return typeof value === 'string' ? undefined : 'Expected text';
70
+ case 'number':
71
+ return typeof value === 'number' && Number.isFinite(value) ? undefined : 'Expected a number';
72
+ case 'integer':
73
+ return typeof value === 'number' && Number.isInteger(value) ? undefined : 'Expected a whole number';
74
+ case 'boolean':
75
+ return typeof value === 'boolean' ? undefined : 'Expected true or false';
76
+ case 'array':
77
+ return Array.isArray(value) ? undefined : 'Expected a list';
78
+ case 'object':
79
+ return typeof value === 'object' && !Array.isArray(value) ? undefined : 'Expected an object';
80
+ default:
81
+ return undefined;
82
+ }
83
+ }
84
+ /**
85
+ * Per-field JSON Schema validation — subset used by the resolver form.
86
+ *
87
+ * Returns a human-readable error string when the value fails a constraint,
88
+ * or undefined when the value is valid. Callers are responsible for the
89
+ * required check (empty-when-required) before calling this for constraint checks.
90
+ *
91
+ * `ctx` is optional context (ShowIfContext-shaped) used to resolve dynamic
92
+ * constraint paths like `x-lt-minimum: "envelope.min_score"`.
93
+ */
94
+ function validateFieldConstraints(value, fieldSchema, ctx) {
95
+ if (!fieldSchema)
96
+ return undefined;
97
+ // Enum membership — the form's select widget constrains choices; API-first
98
+ // callers are unconstrained, so the schema's enum is the contract.
99
+ const allowed = fieldSchema.enum;
100
+ if (Array.isArray(allowed) && allowed.length > 0
101
+ && value !== undefined && value !== null && value !== ''
102
+ && !allowed.includes(value)) {
103
+ return `Must be one of: ${allowed.map((v) => String(v)).join(', ')}`;
104
+ }
105
+ if (typeof value === 'string') {
106
+ const s = value.trim();
107
+ if (s === '')
108
+ return undefined; // empty string: required check is the caller's job
109
+ const minLength = resolveNumericConstraint(fieldSchema.minLength, fieldSchema['x-lt-min-length'], ctx);
110
+ if (minLength !== undefined && s.length < minLength) {
111
+ return `Minimum ${minLength} character${minLength === 1 ? '' : 's'}`;
112
+ }
113
+ const maxLength = resolveNumericConstraint(fieldSchema.maxLength, fieldSchema['x-lt-max-length'], ctx);
114
+ if (maxLength !== undefined && s.length > maxLength) {
115
+ return `Maximum ${maxLength} characters (${s.length} entered)`;
116
+ }
117
+ const pattern = fieldSchema.pattern;
118
+ if (pattern) {
119
+ try {
120
+ if (!new RegExp(pattern).test(s)) {
121
+ const patternError = fieldSchema['x-lt-pattern-error'];
122
+ return patternError ?? 'Invalid format';
123
+ }
124
+ }
125
+ catch {
126
+ // Malformed pattern in schema — silently skip
127
+ }
128
+ }
129
+ const fmt = fieldSchema.format;
130
+ if (fmt === 'email' && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(s)) {
131
+ return 'Enter a valid email address';
132
+ }
133
+ if (fmt === 'uri' && !/^https?:\/\/.+/.test(s)) {
134
+ return 'Enter a valid URL';
135
+ }
136
+ }
137
+ if (typeof value === 'number') {
138
+ const minimum = resolveNumericConstraint(fieldSchema.minimum, fieldSchema['x-lt-minimum'], ctx);
139
+ const exclusiveMinimum = resolveNumericConstraint(fieldSchema.exclusiveMinimum, undefined, ctx);
140
+ const maximum = resolveNumericConstraint(fieldSchema.maximum, fieldSchema['x-lt-maximum'], ctx);
141
+ const exclusiveMaximum = resolveNumericConstraint(fieldSchema.exclusiveMaximum, undefined, ctx);
142
+ if (minimum !== undefined && value < minimum) {
143
+ return `Minimum value is ${minimum}`;
144
+ }
145
+ if (exclusiveMinimum !== undefined && value <= exclusiveMinimum) {
146
+ return `Must be greater than ${exclusiveMinimum}`;
147
+ }
148
+ if (maximum !== undefined && value > maximum) {
149
+ return `Maximum value is ${maximum}`;
150
+ }
151
+ if (exclusiveMaximum !== undefined && value >= exclusiveMaximum) {
152
+ return `Must be less than ${exclusiveMaximum}`;
153
+ }
154
+ }
155
+ return undefined;
156
+ }
157
+ function resolveNumericConstraint(staticVal, dynamicPath, ctx) {
158
+ if (typeof staticVal === 'number')
159
+ return staticVal;
160
+ if (typeof dynamicPath === 'string' && ctx) {
161
+ const dot = dynamicPath.indexOf('.');
162
+ if (dot !== -1) {
163
+ const domain = dynamicPath.slice(0, dot);
164
+ const path = dynamicPath.slice(dot + 1);
165
+ const domainObj = ctx[domain];
166
+ if (domainObj && typeof domainObj === 'object') {
167
+ const parts = path.split('.');
168
+ let cur = domainObj;
169
+ for (const p of parts) {
170
+ cur = cur[p];
171
+ if (cur === undefined)
172
+ break;
173
+ }
174
+ if (typeof cur === 'number')
175
+ return cur;
176
+ if (typeof cur === 'string') {
177
+ const n = Number(cur);
178
+ if (!Number.isNaN(n))
179
+ return n;
180
+ }
181
+ }
182
+ }
183
+ }
184
+ return undefined;
185
+ }
186
+ /** Full field error including required check then constraints. */
187
+ function validateField(value, fieldSchema, isRequired, isTouched, ctx) {
188
+ if (!isTouched)
189
+ return undefined;
190
+ if (isRequired) {
191
+ if (value === undefined || value === null)
192
+ return 'Required';
193
+ if (typeof value === 'boolean' && !value)
194
+ return 'Required';
195
+ if (typeof value === 'string' && value.trim() === '')
196
+ return 'Required';
197
+ if (typeof value === 'object' && !Array.isArray(value) && value !== null) {
198
+ const vals = Object.values(value);
199
+ if (vals.length === 0 || vals.every((v) => !v))
200
+ return 'Required';
201
+ }
202
+ }
203
+ // Declared-type check runs before constraints: a mis-typed value would make
204
+ // the numeric/string constraint branches silently inapplicable.
205
+ const typeError = validateFieldType(value, fieldSchema);
206
+ if (typeError)
207
+ return typeError;
208
+ // Checklist completion — the stricter guard runs regardless of the
209
+ // required-array entry (which stays at-least-one when present).
210
+ const requireAll = validateRequireAll(value, fieldSchema, ctx);
211
+ if (requireAll)
212
+ return requireAll;
213
+ return validateFieldConstraints(value, fieldSchema, ctx);
214
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Isomorphic form-validation library for the x-lt-* enriched form_schema
3
+ * vocabulary. The dashboard renders and pre-validates resolver forms with it;
4
+ * the API layer enforces the same contract on every resolve surface. Pure
5
+ * functions only — no React, no DOM, no database.
6
+ */
7
+ export * from './x-lt-bind';
8
+ export * from './x-lt-help';
9
+ export * from './x-lt-show-if';
10
+ export * from './field-validator';
11
+ export * from './validate-resolver-payload';
@@ -0,0 +1,27 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ /**
18
+ * Isomorphic form-validation library for the x-lt-* enriched form_schema
19
+ * vocabulary. The dashboard renders and pre-validates resolver forms with it;
20
+ * the API layer enforces the same contract on every resolve surface. Pure
21
+ * functions only — no React, no DOM, no database.
22
+ */
23
+ __exportStar(require("./x-lt-bind"), exports);
24
+ __exportStar(require("./x-lt-help"), exports);
25
+ __exportStar(require("./x-lt-show-if"), exports);
26
+ __exportStar(require("./field-validator"), exports);
27
+ __exportStar(require("./validate-resolver-payload"), exports);
@@ -0,0 +1,41 @@
1
+ /**
2
+ * The full pre-submission validation pass over a resolver form schema — the
3
+ * same pass on both sides of the wire. The dashboard runs it on the flat form
4
+ * values before submitting; the API layer runs it on the submitted (bound,
5
+ * nested) payload by inverting x-lt-bind first. Because both entry points
6
+ * funnel into one loop, a payload that passes the client panel passes the
7
+ * server gate, and a 422's violation list is exactly what the panel shows.
8
+ *
9
+ * Semantics per field:
10
+ * - x-lt-showIf-hidden fields are skipped entirely (a field the submitter
11
+ * cannot see never blocks submission)
12
+ * - required (schema.required membership), with checklist/empty-object rules
13
+ * - declared-type check (string/number/integer/boolean/array/object)
14
+ * - enum membership
15
+ * - x-lt-require-all against the checklist items resolved from context
16
+ * - static + dynamic bounds (minimum/x-lt-minimum, lengths, patterns)
17
+ *
18
+ * The showIf/`resolver.*` domain is always the FLAT form representation, so a
19
+ * condition like `resolver.approved` reads the same on both sides.
20
+ */
21
+ import { type FieldError } from './field-validator';
22
+ import { type ShowIfContext } from './x-lt-show-if';
23
+ export type { FieldError } from './field-validator';
24
+ /**
25
+ * The escalation-surface context the pass evaluates showIf conditions and
26
+ * dynamic constraints against. `resolver` is supplied by the pass itself
27
+ * (the flat form values under validation) — callers provide the rest.
28
+ */
29
+ export type ResolverValidationContext = Omit<ShowIfContext, 'resolver'>;
30
+ /**
31
+ * Validate FLAT form values against the form schema. This is the dashboard's
32
+ * entry point (the values the user edits, keyed by field name).
33
+ */
34
+ export declare function validateResolverForm(schema: Record<string, unknown> | null | undefined, formValues: Record<string, unknown>, ctx?: ResolverValidationContext | null): FieldError[];
35
+ /**
36
+ * Validate a SUBMITTED resolver payload (the bound, nested shape the workflow
37
+ * consumes) against the form schema. This is the API layer's entry point: the
38
+ * payload is inverted through each field's x-lt-bind path back to the flat
39
+ * form representation, then run through the same pass the client uses.
40
+ */
41
+ export declare function validateResolverPayload(schema: Record<string, unknown> | null | undefined, payload: Record<string, unknown>, ctx?: ResolverValidationContext | null): FieldError[];
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateResolverForm = validateResolverForm;
4
+ exports.validateResolverPayload = validateResolverPayload;
5
+ /**
6
+ * The full pre-submission validation pass over a resolver form schema — the
7
+ * same pass on both sides of the wire. The dashboard runs it on the flat form
8
+ * values before submitting; the API layer runs it on the submitted (bound,
9
+ * nested) payload by inverting x-lt-bind first. Because both entry points
10
+ * funnel into one loop, a payload that passes the client panel passes the
11
+ * server gate, and a 422's violation list is exactly what the panel shows.
12
+ *
13
+ * Semantics per field:
14
+ * - x-lt-showIf-hidden fields are skipped entirely (a field the submitter
15
+ * cannot see never blocks submission)
16
+ * - required (schema.required membership), with checklist/empty-object rules
17
+ * - declared-type check (string/number/integer/boolean/array/object)
18
+ * - enum membership
19
+ * - x-lt-require-all against the checklist items resolved from context
20
+ * - static + dynamic bounds (minimum/x-lt-minimum, lengths, patterns)
21
+ *
22
+ * The showIf/`resolver.*` domain is always the FLAT form representation, so a
23
+ * condition like `resolver.approved` reads the same on both sides.
24
+ */
25
+ const field_validator_1 = require("./field-validator");
26
+ const x_lt_show_if_1 = require("./x-lt-show-if");
27
+ const x_lt_bind_1 = require("./x-lt-bind");
28
+ /**
29
+ * Validate FLAT form values against the form schema. This is the dashboard's
30
+ * entry point (the values the user edits, keyed by field name).
31
+ */
32
+ function validateResolverForm(schema, formValues, ctx) {
33
+ if (!schema)
34
+ return [];
35
+ const properties = (schema.properties ?? {});
36
+ const required = new Set(schema.required ?? []);
37
+ const liveCtx = {
38
+ ...(ctx ?? {}),
39
+ resolver: formValues,
40
+ };
41
+ const errors = [];
42
+ for (const [field, fieldSchema] of Object.entries(properties)) {
43
+ if (!(0, x_lt_show_if_1.evaluateShowIf)(fieldSchema['x-lt-showIf'], liveCtx))
44
+ continue;
45
+ const err = (0, field_validator_1.validateField)(formValues[field], fieldSchema, required.has(field), true, liveCtx);
46
+ if (err)
47
+ errors.push({ field, message: err });
48
+ }
49
+ return errors;
50
+ }
51
+ /**
52
+ * Validate a SUBMITTED resolver payload (the bound, nested shape the workflow
53
+ * consumes) against the form schema. This is the API layer's entry point: the
54
+ * payload is inverted through each field's x-lt-bind path back to the flat
55
+ * form representation, then run through the same pass the client uses.
56
+ */
57
+ function validateResolverPayload(schema, payload, ctx) {
58
+ if (!schema)
59
+ return [];
60
+ const formValues = (0, x_lt_bind_1.mapPayloadToForm)(payload, schema);
61
+ return validateResolverForm(schema, formValues, ctx);
62
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * x-lt-bind — maps the escalation FORM (flat field values the user edits) to and
3
+ * from the PAYLOAD (the nested JSON the workflow consumes). A form_schema property
4
+ * may declare `x-lt-bind: "a.b[0].c"`, the path its value occupies in the payload;
5
+ * a property with no bind sits at its own name at the root (1:1). This module is
6
+ * isomorphic — the dashboard renders forms with it, and the API layer inverts a
7
+ * submitted payload through it to validate against the form contract. One
8
+ * implementation, both sides.
9
+ *
10
+ * mapPayloadToForm — payload → flat form values, to PREFILL/display the form
11
+ * (server-side: to validate a submitted payload)
12
+ * mapFormToPayload — flat form values → payload, the shape submitted/stored
13
+ */
14
+ type PathSeg = {
15
+ key: string;
16
+ } | {
17
+ index: number;
18
+ };
19
+ /** Parse a bind path — dot keys with optional `[n]` indices. Rejects pollution keys. */
20
+ export declare function parsePath(path: string): PathSeg[];
21
+ /** Set `value` at `path` inside `root`, creating intermediate objects/arrays. */
22
+ export declare function setDeep(root: Record<string, any>, path: string, value: unknown): void;
23
+ /** Read the value at `path` inside `root` (undefined if any segment is missing). */
24
+ export declare function getDeep(root: unknown, path: string): unknown;
25
+ /** The bind path for a form property (its `x-lt-bind`, or the property name). */
26
+ export declare function bindPathFor(propName: string, propDef: Record<string, any> | undefined): string;
27
+ /**
28
+ * Assemble the payload from the form's flat values. A field absent from
29
+ * `formValues` is omitted (so clearing/deleting a field drops it from the
30
+ * payload). Unknown keys not declared in the schema are dropped. With no schema
31
+ * properties, values pass through unchanged.
32
+ */
33
+ export declare function mapFormToPayload(formValues: Record<string, any>, formSchema: Record<string, any> | null | undefined): Record<string, any>;
34
+ /**
35
+ * Reverse of {@link mapFormToPayload}: pull each form field's value out of the
36
+ * payload via its bind path, to prefill/display the form. A field whose bound
37
+ * path is missing from the payload is omitted (the caller falls back to the
38
+ * schema default).
39
+ */
40
+ export declare function mapPayloadToForm(payload: Record<string, any> | null | undefined, formSchema: Record<string, any> | null | undefined): Record<string, any>;
41
+ export {};