@hotmeshio/long-tail 0.20.0 → 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) hide show
  1. package/README.md +4 -4
  2. package/build/api/escalations/accumulate.d.ts +104 -0
  3. package/build/api/escalations/accumulate.js +541 -0
  4. package/build/api/escalations/index.d.ts +1 -0
  5. package/build/api/escalations/index.js +11 -1
  6. package/build/api/roles.d.ts +4 -5
  7. package/build/api/roles.js +53 -4
  8. package/build/api/scan-codes/context.d.ts +14 -1
  9. package/build/api/scan-codes/context.js +30 -2
  10. package/build/api/scan-codes/execute.js +2 -0
  11. package/build/api/scan-codes/identity.js +1 -0
  12. package/build/api/scan-codes/verbs.d.ts +21 -0
  13. package/build/api/scan-codes/verbs.js +122 -3
  14. package/build/index.d.ts +2 -1
  15. package/build/index.js +63 -2
  16. package/build/lib/db/schemas/036_role_portals.sql +12 -0
  17. package/build/routes/escalations/accumulate.d.ts +7 -0
  18. package/build/routes/escalations/accumulate.js +158 -0
  19. package/build/routes/escalations/index.js +5 -0
  20. package/build/sdk/index.d.ts +28 -0
  21. package/build/sdk/index.js +9 -0
  22. package/build/services/escalation/accumulate.d.ts +81 -0
  23. package/build/services/escalation/accumulate.js +154 -0
  24. package/build/services/escalation/index.d.ts +1 -0
  25. package/build/services/escalation/index.js +1 -0
  26. package/build/services/mcp/playwright-server/schemas.d.ts +2 -2
  27. package/build/services/orchestrator/condition.d.ts +40 -3
  28. package/build/services/orchestrator/condition.js +42 -2
  29. package/build/services/role/index.js +1 -0
  30. package/build/services/role/seed.js +6 -1
  31. package/build/services/role/sql.d.ts +6 -3
  32. package/build/services/role/sql.js +7 -2
  33. package/build/services/role/types.d.ts +38 -10
  34. package/build/services/role/types.js +10 -1
  35. package/build/services/scan-code/index.d.ts +1 -1
  36. package/build/services/scan-code/index.js +3 -1
  37. package/build/services/scan-code/parse.d.ts +17 -3
  38. package/build/services/scan-code/parse.js +37 -4
  39. package/build/services/scan-code/validate.js +35 -0
  40. package/build/shared/form-validation/display-only-widgets.d.ts +16 -0
  41. package/build/shared/form-validation/display-only-widgets.js +25 -0
  42. package/build/shared/form-validation/index.d.ts +2 -0
  43. package/build/shared/form-validation/index.js +2 -0
  44. package/build/shared/form-validation/x-lt-bind.d.ts +2 -14
  45. package/build/shared/form-validation/x-lt-bind.js +12 -8
  46. package/build/shared/form-validation/x-lt-invoke.d.ts +38 -0
  47. package/build/shared/form-validation/x-lt-invoke.js +103 -0
  48. package/build/system/mcp-servers/admin/escalations.js +44 -0
  49. package/build/system/mcp-servers/admin/schemas.d.ts +195 -13
  50. package/build/system/mcp-servers/admin/schemas.js +40 -3
  51. package/build/system/mcp-servers/admin/users.js +1 -0
  52. package/build/system/mcp-servers/docs.js +4 -0
  53. package/build/system/mcp-servers/human-queue-schemas.d.ts +85 -0
  54. package/build/system/mcp-servers/human-queue-schemas.js +19 -1
  55. package/build/system/mcp-servers/human-queue.d.ts +2 -0
  56. package/build/system/mcp-servers/human-queue.js +77 -0
  57. package/build/system/seed/tool-manifests-admin.d.ts +1108 -100
  58. package/build/system/seed/tool-manifests-admin.js +4 -1
  59. package/build/system/seed/tool-manifests-escalation.d.ts +174 -0
  60. package/build/system/seed/tool-manifests-escalation.js +56 -0
  61. package/build/tsconfig.tsbuildinfo +1 -1
  62. package/build/types/escalation.d.ts +52 -0
  63. package/build/types/escalation.js +29 -1
  64. package/build/types/index.d.ts +4 -4
  65. package/build/types/index.js +4 -1
  66. package/build/types/scan-code.d.ts +55 -1
  67. package/build/types/scan-code.js +29 -2
  68. package/build/types/startup.d.ts +20 -0
  69. package/dashboard/dist/assets/{AdminDashboard-DplvDBti.js → AdminDashboard-Covdam48.js} +2 -2
  70. package/dashboard/dist/assets/{AdminDashboard-DplvDBti.js.map → AdminDashboard-Covdam48.js.map} +1 -1
  71. package/dashboard/dist/assets/{AgentConfigPage-D8Bf6YxO.js → AgentConfigPage-CE1k6J5r.js} +6 -6
  72. package/dashboard/dist/assets/{AgentConfigPage-D8Bf6YxO.js.map → AgentConfigPage-CE1k6J5r.js.map} +1 -1
  73. package/dashboard/dist/assets/{AgentDetailPage-BN8g0Y2G.js → AgentDetailPage-CWJZIZP1.js} +3 -3
  74. package/dashboard/dist/assets/{AgentDetailPage-BN8g0Y2G.js.map → AgentDetailPage-CWJZIZP1.js.map} +1 -1
  75. package/dashboard/dist/assets/AgentsPage---Dg5ufF.js +2 -0
  76. package/dashboard/dist/assets/{AgentsPage-7JJBHku8.js.map → AgentsPage---Dg5ufF.js.map} +1 -1
  77. package/dashboard/dist/assets/AvailableEscalationsPage-CpbC8oTN.js +2 -0
  78. package/dashboard/dist/assets/AvailableEscalationsPage-CpbC8oTN.js.map +1 -0
  79. package/dashboard/dist/assets/{BotPicker-CGCnIz8I.js → BotPicker-D3drO3-T.js} +2 -2
  80. package/dashboard/dist/assets/{BotPicker-CGCnIz8I.js.map → BotPicker-D3drO3-T.js.map} +1 -1
  81. package/dashboard/dist/assets/BulkAssignModal-BOAWsViq.js +2 -0
  82. package/dashboard/dist/assets/{BulkAssignModal-NJBcoj-f.js.map → BulkAssignModal-BOAWsViq.js.map} +1 -1
  83. package/dashboard/dist/assets/CapabilitiesPage-RGgD3YZO.js +2 -0
  84. package/dashboard/dist/assets/{CapabilitiesPage-F8dpNn9B.js.map → CapabilitiesPage-RGgD3YZO.js.map} +1 -1
  85. package/dashboard/dist/assets/{CollapsibleSection-BZW6VpCU.js → CollapsibleSection-DNkZn87n.js} +2 -2
  86. package/dashboard/dist/assets/{CollapsibleSection-BZW6VpCU.js.map → CollapsibleSection-DNkZn87n.js.map} +1 -1
  87. package/dashboard/dist/assets/{ConfirmDeleteModal-64adXLdq.js → ConfirmDeleteModal-BqzOwhPr.js} +2 -2
  88. package/dashboard/dist/assets/{ConfirmDeleteModal-64adXLdq.js.map → ConfirmDeleteModal-BqzOwhPr.js.map} +1 -1
  89. package/dashboard/dist/assets/{CountdownTimer-BxDub9d2.js → CountdownTimer-BaexQMK6.js} +2 -2
  90. package/dashboard/dist/assets/{CountdownTimer-BxDub9d2.js.map → CountdownTimer-BaexQMK6.js.map} +1 -1
  91. package/dashboard/dist/assets/{CredentialsPage-CnLzopLL.js → CredentialsPage-D7abp0aS.js} +2 -2
  92. package/dashboard/dist/assets/{CredentialsPage-CnLzopLL.js.map → CredentialsPage-D7abp0aS.js.map} +1 -1
  93. package/dashboard/dist/assets/{CronLabel-CAD5UYDT.js → CronLabel-DZiWmTwJ.js} +2 -2
  94. package/dashboard/dist/assets/{CronLabel-CAD5UYDT.js.map → CronLabel-DZiWmTwJ.js.map} +1 -1
  95. package/dashboard/dist/assets/DataTable-spX1dFyb.js +2 -0
  96. package/dashboard/dist/assets/DataTable-spX1dFyb.js.map +1 -0
  97. package/dashboard/dist/assets/{DropZone-XlcY8hEH.js → DropZone-f1o-GLM8.js} +2 -2
  98. package/dashboard/dist/assets/{DropZone-XlcY8hEH.js.map → DropZone-f1o-GLM8.js.map} +1 -1
  99. package/dashboard/dist/assets/{ElapsedCell-CwO4ufd0.js → ElapsedCell-BdGO_w4v.js} +2 -2
  100. package/dashboard/dist/assets/{ElapsedCell-CwO4ufd0.js.map → ElapsedCell-BdGO_w4v.js.map} +1 -1
  101. package/dashboard/dist/assets/EntityTimelinePanel-DIDcF5Yu.js +2 -0
  102. package/dashboard/dist/assets/{EntityTimelinePanel-CkF-oW-m.js.map → EntityTimelinePanel-DIDcF5Yu.js.map} +1 -1
  103. package/dashboard/dist/assets/{EscalationListSchemaPage-h9JO_q5f.js → EscalationListSchemaPage-C28rn9XC.js} +3 -3
  104. package/dashboard/dist/assets/{EscalationListSchemaPage-h9JO_q5f.js.map → EscalationListSchemaPage-C28rn9XC.js.map} +1 -1
  105. package/dashboard/dist/assets/EscalationListView-CkBnkpDJ.js +2 -0
  106. package/dashboard/dist/assets/EscalationListView-CkBnkpDJ.js.map +1 -0
  107. package/dashboard/dist/assets/{EscalationSchemaPage-mJFL5_Se.js → EscalationSchemaPage-W5r0A1kj.js} +3 -3
  108. package/dashboard/dist/assets/{EscalationSchemaPage-mJFL5_Se.js.map → EscalationSchemaPage-W5r0A1kj.js.map} +1 -1
  109. package/dashboard/dist/assets/EscalationTimeline-DKyTz6sM.js +2 -0
  110. package/dashboard/dist/assets/EscalationTimeline-DKyTz6sM.js.map +1 -0
  111. package/dashboard/dist/assets/EscalationTitleSelect-CzKfavri.js +2 -0
  112. package/dashboard/dist/assets/EscalationTitleSelect-CzKfavri.js.map +1 -0
  113. package/dashboard/dist/assets/{EscalationsOverview-DlXUFqWJ.js → EscalationsOverview-Tdu3Yx2c.js} +2 -2
  114. package/dashboard/dist/assets/{EscalationsOverview-DlXUFqWJ.js.map → EscalationsOverview-Tdu3Yx2c.js.map} +1 -1
  115. package/dashboard/dist/assets/{EventTable-Ike2xchn.js → EventTable-DiIxOJwO.js} +2 -2
  116. package/dashboard/dist/assets/{EventTable-Ike2xchn.js.map → EventTable-DiIxOJwO.js.map} +1 -1
  117. package/dashboard/dist/assets/{FilterBar-DMOR-O1c.js → FilterBar-CvMBCVIo.js} +2 -2
  118. package/dashboard/dist/assets/{FilterBar-DMOR-O1c.js.map → FilterBar-CvMBCVIo.js.map} +1 -1
  119. package/dashboard/dist/assets/GraphInvokePage-DO-yyhi6.js +2 -0
  120. package/dashboard/dist/assets/{GraphInvokePage-CKtvWowP.js.map → GraphInvokePage-DO-yyhi6.js.map} +1 -1
  121. package/dashboard/dist/assets/HomePage-DSS3eHR2.js +2 -0
  122. package/dashboard/dist/assets/{HomePage-BQ3Q791Q.js.map → HomePage-DSS3eHR2.js.map} +1 -1
  123. package/dashboard/dist/assets/ListToolbar-C3-Tqqub.js +2 -0
  124. package/dashboard/dist/assets/{ListToolbar-DdJzj472.js.map → ListToolbar-C3-Tqqub.js.map} +1 -1
  125. package/dashboard/dist/assets/{McpOverview-BbtrduWn.js → McpOverview-DEJmsdVi.js} +2 -2
  126. package/dashboard/dist/assets/{McpOverview-BbtrduWn.js.map → McpOverview-DEJmsdVi.js.map} +1 -1
  127. package/dashboard/dist/assets/{McpQueryDetailPage-C1L4T-Wt.js → McpQueryDetailPage-DYJr16l7.js} +2 -2
  128. package/dashboard/dist/assets/{McpQueryDetailPage-C1L4T-Wt.js.map → McpQueryDetailPage-DYJr16l7.js.map} +1 -1
  129. package/dashboard/dist/assets/McpQueryPage-BBcG_UuU.js +2 -0
  130. package/dashboard/dist/assets/{McpQueryPage-CfJy7HZ7.js.map → McpQueryPage-BBcG_UuU.js.map} +1 -1
  131. package/dashboard/dist/assets/{McpRunDetailPage-CA9yv7he.js → McpRunDetailPage-C6xw0kBg.js} +2 -2
  132. package/dashboard/dist/assets/{McpRunDetailPage-CA9yv7he.js.map → McpRunDetailPage-C6xw0kBg.js.map} +1 -1
  133. package/dashboard/dist/assets/McpRunsPage-CRQqrF4Q.js +2 -0
  134. package/dashboard/dist/assets/{McpRunsPage-D7QXjW9z.js.map → McpRunsPage-CRQqrF4Q.js.map} +1 -1
  135. package/dashboard/dist/assets/{NamespacePill-Bb3revqD.js → NamespacePill-DADRJOUl.js} +2 -2
  136. package/dashboard/dist/assets/{NamespacePill-Bb3revqD.js.map → NamespacePill-DADRJOUl.js.map} +1 -1
  137. package/dashboard/dist/assets/OperationsPage-Dlfwzf-0.js +3 -0
  138. package/dashboard/dist/assets/OperationsPage-Dlfwzf-0.js.map +1 -0
  139. package/dashboard/dist/assets/OperatorDashboard-DoiDGZ9R.js +2 -0
  140. package/dashboard/dist/assets/{OperatorDashboard-sXNDh1Ph.js.map → OperatorDashboard-DoiDGZ9R.js.map} +1 -1
  141. package/dashboard/dist/assets/{PageHeader-Di5Sz3an.js → PageHeader-Csq434-v.js} +2 -2
  142. package/dashboard/dist/assets/{PageHeader-Di5Sz3an.js.map → PageHeader-Csq434-v.js.map} +1 -1
  143. package/dashboard/dist/assets/{PageHeaderWithStats-DutKJ-h2.js → PageHeaderWithStats-CSnk1p5A.js} +2 -2
  144. package/dashboard/dist/assets/{PageHeaderWithStats-DutKJ-h2.js.map → PageHeaderWithStats-CSnk1p5A.js.map} +1 -1
  145. package/dashboard/dist/assets/{PersonaDetailPage-NeHD-Gra.js → PersonaDetailPage-BzbA4Prr.js} +2 -2
  146. package/dashboard/dist/assets/{PersonaDetailPage-NeHD-Gra.js.map → PersonaDetailPage-BzbA4Prr.js.map} +1 -1
  147. package/dashboard/dist/assets/{PersonasPage-DavKXRWX.js → PersonasPage-B36yn4hU.js} +2 -2
  148. package/dashboard/dist/assets/{PersonasPage-DavKXRWX.js.map → PersonasPage-B36yn4hU.js.map} +1 -1
  149. package/dashboard/dist/assets/PortalPage-BkD4YfDf.js +2 -0
  150. package/dashboard/dist/assets/PortalPage-BkD4YfDf.js.map +1 -0
  151. package/dashboard/dist/assets/{ProcessDetailPage-DkdKJGe6.js → ProcessDetailPage-BT0eiBWY.js} +2 -2
  152. package/dashboard/dist/assets/{ProcessDetailPage-DkdKJGe6.js.map → ProcessDetailPage-BT0eiBWY.js.map} +1 -1
  153. package/dashboard/dist/assets/ProcessesListPage-BEqeeNae.js +2 -0
  154. package/dashboard/dist/assets/{ProcessesListPage-CjwVKe32.js.map → ProcessesListPage-BEqeeNae.js.map} +1 -1
  155. package/dashboard/dist/assets/ResolverForm-BwgjIX97.js +7 -0
  156. package/dashboard/dist/assets/ResolverForm-BwgjIX97.js.map +1 -0
  157. package/dashboard/dist/assets/RoleDetailPage-BFuLNJXa.js +8 -0
  158. package/dashboard/dist/assets/RoleDetailPage-BFuLNJXa.js.map +1 -0
  159. package/dashboard/dist/assets/{RolePill-DhnVPK4q.js → RolePill-BafrASDX.js} +2 -2
  160. package/dashboard/dist/assets/{RolePill-DhnVPK4q.js.map → RolePill-BafrASDX.js.map} +1 -1
  161. package/dashboard/dist/assets/{RolesPage-OM9KM8Pg.js → RolesPage-80quJU5-.js} +2 -2
  162. package/dashboard/dist/assets/{RolesPage-OM9KM8Pg.js.map → RolesPage-80quJU5-.js.map} +1 -1
  163. package/dashboard/dist/assets/RunAsSelector-BoePhWVD.js +2 -0
  164. package/dashboard/dist/assets/{RunAsSelector-fFMt1bGe.js.map → RunAsSelector-BoePhWVD.js.map} +1 -1
  165. package/dashboard/dist/assets/{ScanCodesPage-AujH-pPQ.js → ScanCodesPage-Cu1bKEix.js} +2 -2
  166. package/dashboard/dist/assets/{ScanCodesPage-AujH-pPQ.js.map → ScanCodesPage-Cu1bKEix.js.map} +1 -1
  167. package/dashboard/dist/assets/ScanSchemeDetailPage-D9AbS6UY.js +2 -0
  168. package/dashboard/dist/assets/ScanSchemeDetailPage-D9AbS6UY.js.map +1 -0
  169. package/dashboard/dist/assets/ScanStationPage-gcZGefvT.js +2 -0
  170. package/dashboard/dist/assets/{ScanStationPage-C1_ppDoZ.js.map → ScanStationPage-gcZGefvT.js.map} +1 -1
  171. package/dashboard/dist/assets/{ScopeBadge-CXUg0FHo.js → ScopeBadge-b6MIBiYD.js} +2 -2
  172. package/dashboard/dist/assets/{ScopeBadge-CXUg0FHo.js.map → ScopeBadge-b6MIBiYD.js.map} +1 -1
  173. package/dashboard/dist/assets/{StickyPagination-B91Pk9xh.js → StickyPagination-9ITrei_d.js} +2 -2
  174. package/dashboard/dist/assets/{StickyPagination-B91Pk9xh.js.map → StickyPagination-9ITrei_d.js.map} +1 -1
  175. package/dashboard/dist/assets/{StreamMessageDetail-C7SPqaJt.js → StreamMessageDetail-BkYvEHFY.js} +2 -2
  176. package/dashboard/dist/assets/{StreamMessageDetail-C7SPqaJt.js.map → StreamMessageDetail-BkYvEHFY.js.map} +1 -1
  177. package/dashboard/dist/assets/{SwimlaneTimeline-BcHR8ylf.js → SwimlaneTimeline-B1rotFix.js} +2 -2
  178. package/dashboard/dist/assets/{SwimlaneTimeline-BcHR8ylf.js.map → SwimlaneTimeline-B1rotFix.js.map} +1 -1
  179. package/dashboard/dist/assets/{TagInput-BZ8vb2oW.js → TagInput-ZrIIrEUP.js} +2 -2
  180. package/dashboard/dist/assets/{TagInput-BZ8vb2oW.js.map → TagInput-ZrIIrEUP.js.map} +1 -1
  181. package/dashboard/dist/assets/{TaskDetailPage-Bqj0I_I0.js → TaskDetailPage-zhn_U_eC.js} +2 -2
  182. package/dashboard/dist/assets/{TaskDetailPage-Bqj0I_I0.js.map → TaskDetailPage-zhn_U_eC.js.map} +1 -1
  183. package/dashboard/dist/assets/{TaskQueuePill-Bxir8WRl.js → TaskQueuePill-DkQ1uc6y.js} +2 -2
  184. package/dashboard/dist/assets/{TaskQueuePill-Bxir8WRl.js.map → TaskQueuePill-DkQ1uc6y.js.map} +1 -1
  185. package/dashboard/dist/assets/TasksListPage-CNbNeagx.js +2 -0
  186. package/dashboard/dist/assets/{TasksListPage-BB1f79lL.js.map → TasksListPage-CNbNeagx.js.map} +1 -1
  187. package/dashboard/dist/assets/{TimeAgo-BFnODmNe.js → TimeAgo-0YVMBwls.js} +2 -2
  188. package/dashboard/dist/assets/{TimeAgo-BFnODmNe.js.map → TimeAgo-0YVMBwls.js.map} +1 -1
  189. package/dashboard/dist/assets/{TimestampCell-BXgLOBsr.js → TimestampCell-DB7r3np8.js} +2 -2
  190. package/dashboard/dist/assets/{TimestampCell-BXgLOBsr.js.map → TimestampCell-DB7r3np8.js.map} +1 -1
  191. package/dashboard/dist/assets/{ToolPill-FkgTXIhq.js → ToolPill-Baxm02L6.js} +2 -2
  192. package/dashboard/dist/assets/{ToolPill-FkgTXIhq.js.map → ToolPill-Baxm02L6.js.map} +1 -1
  193. package/dashboard/dist/assets/ToolTestPanel-BLfA02wv.js +2 -0
  194. package/dashboard/dist/assets/{ToolTestPanel-Bwe3J5lj.js.map → ToolTestPanel-BLfA02wv.js.map} +1 -1
  195. package/dashboard/dist/assets/{TopicDetailPage-DAF07vZ9.js → TopicDetailPage-eAqPKShq.js} +3 -3
  196. package/dashboard/dist/assets/{TopicDetailPage-DAF07vZ9.js.map → TopicDetailPage-eAqPKShq.js.map} +1 -1
  197. package/dashboard/dist/assets/TopicsPage-BNNWD-zl.js +2 -0
  198. package/dashboard/dist/assets/{TopicsPage-C1gxBUap.js.map → TopicsPage-BNNWD-zl.js.map} +1 -1
  199. package/dashboard/dist/assets/{UserName-BzXJUE6q.js → UserName-Pw46tO_k.js} +2 -2
  200. package/dashboard/dist/assets/{UserName-BzXJUE6q.js.map → UserName-Pw46tO_k.js.map} +1 -1
  201. package/dashboard/dist/assets/{WorkflowExecutionPage-SkRU5cRX.js → WorkflowExecutionPage-DvA51lT3.js} +2 -2
  202. package/dashboard/dist/assets/{WorkflowExecutionPage-SkRU5cRX.js.map → WorkflowExecutionPage-DvA51lT3.js.map} +1 -1
  203. package/dashboard/dist/assets/{WorkflowPill--AYMW7u_.js → WorkflowPill-ZepbO_ny.js} +2 -2
  204. package/dashboard/dist/assets/{WorkflowPill--AYMW7u_.js.map → WorkflowPill-ZepbO_ny.js.map} +1 -1
  205. package/dashboard/dist/assets/WorkflowsDashboard-DFDTwnhn.js +2 -0
  206. package/dashboard/dist/assets/{WorkflowsDashboard-CZAqRk1N.js.map → WorkflowsDashboard-DFDTwnhn.js.map} +1 -1
  207. package/dashboard/dist/assets/{WorkflowsOverview-BoN44VTE.js → WorkflowsOverview-5i2Tcy-p.js} +2 -2
  208. package/dashboard/dist/assets/{WorkflowsOverview-BoN44VTE.js.map → WorkflowsOverview-5i2Tcy-p.js.map} +1 -1
  209. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CqjhtdJf.js → YamlWorkflowDetailPage-p4VEYZS0.js} +11 -11
  210. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CqjhtdJf.js.map → YamlWorkflowDetailPage-p4VEYZS0.js.map} +1 -1
  211. package/dashboard/dist/assets/{YamlWorkflowsPage-CwnJkzyb.js → YamlWorkflowsPage-Cq-hMVxl.js} +2 -2
  212. package/dashboard/dist/assets/{YamlWorkflowsPage-CwnJkzyb.js.map → YamlWorkflowsPage-Cq-hMVxl.js.map} +1 -1
  213. package/dashboard/dist/assets/{agents-gV0Ys-sY.js → agents-EyBPJMYa.js} +2 -2
  214. package/dashboard/dist/assets/{agents-gV0Ys-sY.js.map → agents-EyBPJMYa.js.map} +1 -1
  215. package/dashboard/dist/assets/{bots-B97itB3I.js → bots-DX6jjqtF.js} +2 -2
  216. package/dashboard/dist/assets/{bots-B97itB3I.js.map → bots-DX6jjqtF.js.map} +1 -1
  217. package/dashboard/dist/assets/{capabilities-CR9xZgGd.js → capabilities-ZdLv9xBQ.js} +2 -2
  218. package/dashboard/dist/assets/{capabilities-CR9xZgGd.js.map → capabilities-ZdLv9xBQ.js.map} +1 -1
  219. package/dashboard/dist/assets/{constants-BHkpVaqx.js → constants-CeBBTzf5.js} +2 -2
  220. package/dashboard/dist/assets/{constants-BHkpVaqx.js.map → constants-CeBBTzf5.js.map} +1 -1
  221. package/dashboard/dist/assets/{controlplane-YxvP1KCa.js → controlplane-CpvZaJuw.js} +2 -2
  222. package/dashboard/dist/assets/{controlplane-YxvP1KCa.js.map → controlplane-CpvZaJuw.js.map} +1 -1
  223. package/dashboard/dist/assets/escalation-columns-Mvsze5eV.js +2 -0
  224. package/dashboard/dist/assets/escalation-columns-Mvsze5eV.js.map +1 -0
  225. package/dashboard/dist/assets/index-B_GT23TE.js +3 -0
  226. package/dashboard/dist/assets/index-B_GT23TE.js.map +1 -0
  227. package/dashboard/dist/assets/index-BbCjGO3M.js +2 -0
  228. package/dashboard/dist/assets/{index-CFbo9FU9.js.map → index-BbCjGO3M.js.map} +1 -1
  229. package/dashboard/dist/assets/{index-DMeaiKgf.js → index-Bhb89oHH.js} +2 -2
  230. package/dashboard/dist/assets/{index-DMeaiKgf.js.map → index-Bhb89oHH.js.map} +1 -1
  231. package/dashboard/dist/assets/index-CgUcYveM.js +67 -0
  232. package/dashboard/dist/assets/index-CgUcYveM.js.map +1 -0
  233. package/dashboard/dist/assets/index-Cn8uJsd7.js +2 -0
  234. package/dashboard/dist/assets/{index-BQpV-DTG.js.map → index-Cn8uJsd7.js.map} +1 -1
  235. package/dashboard/dist/assets/index-D-Xs4rAW.js +2 -0
  236. package/dashboard/dist/assets/{index-Bp9KBLT5.js.map → index-D-Xs4rAW.js.map} +1 -1
  237. package/dashboard/dist/assets/{index-DwOnWeu8.js → index-DGmzBY9D.js} +2 -2
  238. package/dashboard/dist/assets/{index-DwOnWeu8.js.map → index-DGmzBY9D.js.map} +1 -1
  239. package/dashboard/dist/assets/{index-CIpHj4di.js → index-DZhtP2Ok.js} +2 -2
  240. package/dashboard/dist/assets/{index-CIpHj4di.js.map → index-DZhtP2Ok.js.map} +1 -1
  241. package/dashboard/dist/assets/index-Dh8MJl3L.css +1 -0
  242. package/dashboard/dist/assets/index-DkrBFFSO.js +13 -0
  243. package/dashboard/dist/assets/{index-Cfvkl2J0.js.map → index-DkrBFFSO.js.map} +1 -1
  244. package/dashboard/dist/assets/{index-B9BBCqLI.js → index-Eo-l3Lqo.js} +2 -2
  245. package/dashboard/dist/assets/{index-B9BBCqLI.js.map → index-Eo-l3Lqo.js.map} +1 -1
  246. package/dashboard/dist/assets/index-PfSRKerc.js +2 -0
  247. package/dashboard/dist/assets/{index-CUZ6LYye.js.map → index-PfSRKerc.js.map} +1 -1
  248. package/dashboard/dist/assets/{index-ipqwPavs.js → index-oFKUFGQL.js} +2 -2
  249. package/dashboard/dist/assets/{index-ipqwPavs.js.map → index-oFKUFGQL.js.map} +1 -1
  250. package/dashboard/dist/assets/index-z5Hpeidu.js +2 -0
  251. package/dashboard/dist/assets/index-z5Hpeidu.js.map +1 -0
  252. package/dashboard/dist/assets/{knowledge-XX6cW4Ob.js → knowledge-CgloEkaf.js} +2 -2
  253. package/dashboard/dist/assets/{knowledge-XX6cW4Ob.js.map → knowledge-CgloEkaf.js.map} +1 -1
  254. package/dashboard/dist/assets/{mcp-CH13hNH2.js → mcp-Bix7QYO7.js} +2 -2
  255. package/dashboard/dist/assets/{mcp-CH13hNH2.js.map → mcp-Bix7QYO7.js.map} +1 -1
  256. package/dashboard/dist/assets/{mcp-query-Duydd3JA.js → mcp-query-o-sGX2ST.js} +2 -2
  257. package/dashboard/dist/assets/{mcp-query-Duydd3JA.js.map → mcp-query-o-sGX2ST.js.map} +1 -1
  258. package/dashboard/dist/assets/metadata-display-COo3mMCr.js +2 -0
  259. package/dashboard/dist/assets/metadata-display-COo3mMCr.js.map +1 -0
  260. package/dashboard/dist/assets/{personas-mDk4lLQS.js → personas-30azkJ_s.js} +2 -2
  261. package/dashboard/dist/assets/{personas-mDk4lLQS.js.map → personas-30azkJ_s.js.map} +1 -1
  262. package/dashboard/dist/assets/{pipelines-B5GcgCeF.js → pipelines-Bfk2GFK7.js} +2 -2
  263. package/dashboard/dist/assets/{pipelines-B5GcgCeF.js.map → pipelines-Bfk2GFK7.js.map} +1 -1
  264. package/dashboard/dist/assets/{tasks-CItmNsRp.js → tasks-CpdopewW.js} +2 -2
  265. package/dashboard/dist/assets/{tasks-CItmNsRp.js.map → tasks-CpdopewW.js.map} +1 -1
  266. package/dashboard/dist/assets/{topics-CJYG7BX5.js → topics--bvCV9Yp.js} +2 -2
  267. package/dashboard/dist/assets/{topics-CJYG7BX5.js.map → topics--bvCV9Yp.js.map} +1 -1
  268. package/dashboard/dist/assets/useContainerWidth-DSLp1gEm.js +2 -0
  269. package/dashboard/dist/assets/useContainerWidth-DSLp1gEm.js.map +1 -0
  270. package/dashboard/dist/assets/{useDebouncedValue-BrwgXcp8.js → useDebouncedValue-Da0lPmj3.js} +2 -2
  271. package/dashboard/dist/assets/{useDebouncedValue-BrwgXcp8.js.map → useDebouncedValue-Da0lPmj3.js.map} +1 -1
  272. package/dashboard/dist/assets/{useNamespace-CHty0HAS.js → useNamespace-DD_Esl6n.js} +2 -2
  273. package/dashboard/dist/assets/{useNamespace-CHty0HAS.js.map → useNamespace-DD_Esl6n.js.map} +1 -1
  274. package/dashboard/dist/assets/{useYamlActivityEvents-CoTsia7t.js → useYamlActivityEvents-AeAhZJJk.js} +2 -2
  275. package/dashboard/dist/assets/{useYamlActivityEvents-CoTsia7t.js.map → useYamlActivityEvents-AeAhZJJk.js.map} +1 -1
  276. package/dashboard/dist/assets/{vendor-icons-DeBdvyKJ.js → vendor-icons-B7OcUM6b.js} +2 -2
  277. package/dashboard/dist/assets/{vendor-icons-DeBdvyKJ.js.map → vendor-icons-B7OcUM6b.js.map} +1 -1
  278. package/dashboard/dist/assets/{yaml-workflows-CiWwx5rM.js → yaml-workflows-BHAOOGvn.js} +2 -2
  279. package/dashboard/dist/assets/{yaml-workflows-CiWwx5rM.js.map → yaml-workflows-BHAOOGvn.js.map} +1 -1
  280. package/dashboard/dist/index.html +3 -3
  281. package/docs/accumulator.md +113 -0
  282. package/docs/api/http/escalations.md +90 -0
  283. package/docs/api/http/roles.md +1 -0
  284. package/docs/api/sdk/escalations.md +92 -0
  285. package/docs/api/sdk/roles.md +2 -0
  286. package/docs/architecture.md +1 -1
  287. package/docs/code-owned-configuration.md +2 -1
  288. package/docs/dashboard.md +10 -4
  289. package/docs/hitl/design.md +1 -1
  290. package/docs/hitl/escalation.md +37 -1
  291. package/docs/hitl/invoke-form.md +4 -0
  292. package/docs/hitl/pinned-views.md +4 -0
  293. package/docs/hitl/portal.md +97 -0
  294. package/docs/hitl/resolution.md +41 -0
  295. package/docs/hitl/x-lt-embed.md +1 -1
  296. package/docs/hitl/x-lt-invoke.md +95 -0
  297. package/docs/hitl/x-lt-list-schema.md +3 -1
  298. package/docs/hitl/x-lt-widget.md +1 -0
  299. package/docs/hitl-guide.md +8 -1
  300. package/docs/scan-codes.md +33 -9
  301. package/docs/sdk.md +1 -1
  302. package/docs/workflows.md +2 -2
  303. package/package.json +4 -2
  304. package/dashboard/dist/assets/AgentsPage-7JJBHku8.js +0 -2
  305. package/dashboard/dist/assets/AvailableEscalationsPage-lz5qwSjg.js +0 -2
  306. package/dashboard/dist/assets/AvailableEscalationsPage-lz5qwSjg.js.map +0 -1
  307. package/dashboard/dist/assets/BulkAssignModal-NJBcoj-f.js +0 -2
  308. package/dashboard/dist/assets/CapabilitiesPage-F8dpNn9B.js +0 -2
  309. package/dashboard/dist/assets/DataTable-7C7riavf.js +0 -2
  310. package/dashboard/dist/assets/DataTable-7C7riavf.js.map +0 -1
  311. package/dashboard/dist/assets/EntityTimelinePanel-CkF-oW-m.js +0 -2
  312. package/dashboard/dist/assets/EscalationListView-AHW2xtlr.js +0 -2
  313. package/dashboard/dist/assets/EscalationListView-AHW2xtlr.js.map +0 -1
  314. package/dashboard/dist/assets/GraphInvokePage-CKtvWowP.js +0 -2
  315. package/dashboard/dist/assets/HomePage-BQ3Q791Q.js +0 -2
  316. package/dashboard/dist/assets/ListToolbar-DdJzj472.js +0 -2
  317. package/dashboard/dist/assets/McpQueryPage-CfJy7HZ7.js +0 -2
  318. package/dashboard/dist/assets/McpRunsPage-D7QXjW9z.js +0 -2
  319. package/dashboard/dist/assets/OperationsPage-aLHHAP2X.js +0 -3
  320. package/dashboard/dist/assets/OperationsPage-aLHHAP2X.js.map +0 -1
  321. package/dashboard/dist/assets/OperatorDashboard-sXNDh1Ph.js +0 -2
  322. package/dashboard/dist/assets/ProcessesListPage-CjwVKe32.js +0 -2
  323. package/dashboard/dist/assets/ResolverForm-Bk-wDkN-.js +0 -3
  324. package/dashboard/dist/assets/ResolverForm-Bk-wDkN-.js.map +0 -1
  325. package/dashboard/dist/assets/RoleDetailPage-WQt0y5l7.js +0 -8
  326. package/dashboard/dist/assets/RoleDetailPage-WQt0y5l7.js.map +0 -1
  327. package/dashboard/dist/assets/RunAsSelector-fFMt1bGe.js +0 -2
  328. package/dashboard/dist/assets/ScanSchemeDetailPage-eKQpmsC_.js +0 -2
  329. package/dashboard/dist/assets/ScanSchemeDetailPage-eKQpmsC_.js.map +0 -1
  330. package/dashboard/dist/assets/ScanStationPage-C1_ppDoZ.js +0 -2
  331. package/dashboard/dist/assets/TasksListPage-BB1f79lL.js +0 -2
  332. package/dashboard/dist/assets/ToolTestPanel-Bwe3J5lj.js +0 -2
  333. package/dashboard/dist/assets/TopicsPage-C1gxBUap.js +0 -2
  334. package/dashboard/dist/assets/WorkflowsDashboard-CZAqRk1N.js +0 -2
  335. package/dashboard/dist/assets/escalation-columns-uq-IV2aj.js +0 -2
  336. package/dashboard/dist/assets/escalation-columns-uq-IV2aj.js.map +0 -1
  337. package/dashboard/dist/assets/index-3ezfWLkE.js +0 -6
  338. package/dashboard/dist/assets/index-3ezfWLkE.js.map +0 -1
  339. package/dashboard/dist/assets/index-BQpV-DTG.js +0 -2
  340. package/dashboard/dist/assets/index-Bp9KBLT5.js +0 -2
  341. package/dashboard/dist/assets/index-Bpvfr4OW.css +0 -1
  342. package/dashboard/dist/assets/index-CFbo9FU9.js +0 -2
  343. package/dashboard/dist/assets/index-CIwlVfvV.js +0 -67
  344. package/dashboard/dist/assets/index-CIwlVfvV.js.map +0 -1
  345. package/dashboard/dist/assets/index-CUZ6LYye.js +0 -2
  346. package/dashboard/dist/assets/index-Cfvkl2J0.js +0 -13
  347. package/dashboard/dist/assets/index-SGyrXGp8.js +0 -3
  348. package/dashboard/dist/assets/index-SGyrXGp8.js.map +0 -1
  349. package/dashboard/dist/assets/invoke-context-DrVyUEfs.js +0 -2
  350. package/dashboard/dist/assets/invoke-context-DrVyUEfs.js.map +0 -1
  351. package/dashboard/dist/assets/metadata-display--TzK0REC.js +0 -2
  352. package/dashboard/dist/assets/metadata-display--TzK0REC.js.map +0 -1
  353. package/dashboard/dist/assets/resolver-payload-m9AGKZ3a.js +0 -2
  354. package/dashboard/dist/assets/resolver-payload-m9AGKZ3a.js.map +0 -1
  355. package/docs/compilation.md +0 -152
  356. package/docs/compiler.md +0 -311
  357. package/docs/contributing.md +0 -56
  358. package/docs/design-principles.md +0 -245
  359. package/docs/schema-exchange.md +0 -173
  360. package/docs/self-test.md +0 -106
  361. package/docs/story.md +0 -184
@@ -21,7 +21,7 @@ export declare const LIST_ROLES = "\n SELECT role FROM lt_roles ORDER BY role";
21
21
  */
22
22
  export declare const LIST_CONFIGURED_ROLES = "\n SELECT role FROM lt_roles\n WHERE title IS NOT NULL OR form_schema IS NOT NULL\n ORDER BY role";
23
23
  /** One role's full metadata row (plus upstream inputs) for startup diffing. */
24
- export declare const GET_ROLE_ROW = "\n SELECT\n r.role, r.title, r.description, r.form_schema, r.metadata_schema,\n r.properties, r.ops_visible, r.ops_home_default, r.parent_role,\n r.sla_minutes, r.target_per_hour, r.worker_count,\n r.priority_threshold_minutes, r.priority_facet,\n r.entity_facet, r.entity_state_source,\n r.list_schema, r.default_pins, r.enforce_schema,\n r.current_schema_version, r.current_list_schema_version,\n COALESCE((SELECT array_agg(u.upstream_role ORDER BY u.upstream_role)\n FROM lt_role_upstreams u WHERE u.role = r.role), '{}') AS upstream_roles\n FROM lt_roles r\n WHERE r.role = $1";
24
+ export declare const GET_ROLE_ROW = "\n SELECT\n r.role, r.title, r.description, r.form_schema, r.metadata_schema,\n r.properties, r.ops_visible, r.ops_home_default, r.parent_role,\n r.sla_minutes, r.target_per_hour, r.worker_count,\n r.priority_threshold_minutes, r.priority_facet,\n r.entity_facet, r.entity_state_source,\n r.list_schema, r.default_pins, r.portals, r.enforce_schema,\n r.current_schema_version, r.current_list_schema_version,\n COALESCE((SELECT array_agg(u.upstream_role ORDER BY u.upstream_role)\n FROM lt_role_upstreams u WHERE u.role = r.role), '{}') AS upstream_roles\n FROM lt_roles r\n WHERE r.role = $1";
25
25
  export declare const DELETE_ROLE = "\n DELETE FROM lt_roles WHERE role = $1";
26
26
  /**
27
27
  * PATCH semantics in ONE atomic statement: each column has a boolean
@@ -66,8 +66,11 @@ export declare const DELETE_ROLE = "\n DELETE FROM lt_roles WHERE role = $1";
66
66
  * entity_state_source ($39 = provided sentinel, $40 = value) is unversioned
67
67
  * config: 'role' | 'subtype' — how this role names its contribution to the
68
68
  * entity's state space (the station itself, or its subtypes).
69
+ *
70
+ * portals ($41 = provided sentinel, $42 = value) is unversioned config: the
71
+ * role's named portal views, each a matrix of pin cells rendered as one page.
69
72
  */
70
- export declare const UPDATE_ROLE_METADATA = "\n WITH home_clear AS (\n UPDATE lt_roles SET ops_home_default = false\n WHERE $35::boolean AND COALESCE($36::boolean, false) AND role <> $1 AND ops_home_default\n ), 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 entity_facet = CASE WHEN $37::boolean THEN $38 ELSE entity_facet END,\n entity_state_source\n = CASE WHEN $39::boolean THEN COALESCE($40, 'role') ELSE entity_state_source 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 enforce_schema = CASE WHEN $33::boolean THEN COALESCE($34::boolean, false) ELSE enforce_schema END,\n ops_home_default = CASE WHEN $35::boolean THEN COALESCE($36::boolean, false) ELSE ops_home_default 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, ops_home_default, parent_role, sla_minutes, target_per_hour, worker_count,\n priority_threshold_minutes, priority_facet, entity_facet, entity_state_source,\n current_schema_version, list_schema, current_list_schema_version,\n default_pins, enforce_schema\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";
73
+ export declare const UPDATE_ROLE_METADATA = "\n WITH home_clear AS (\n UPDATE lt_roles SET ops_home_default = false\n WHERE $35::boolean AND COALESCE($36::boolean, false) AND role <> $1 AND ops_home_default\n ), 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 entity_facet = CASE WHEN $37::boolean THEN $38 ELSE entity_facet END,\n entity_state_source\n = CASE WHEN $39::boolean THEN COALESCE($40, 'role') ELSE entity_state_source 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 portals = CASE WHEN $41::boolean THEN $42::jsonb ELSE portals END,\n enforce_schema = CASE WHEN $33::boolean THEN COALESCE($34::boolean, false) ELSE enforce_schema END,\n ops_home_default = CASE WHEN $35::boolean THEN COALESCE($36::boolean, false) ELSE ops_home_default 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, ops_home_default, parent_role, sla_minutes, target_per_hour, worker_count,\n priority_threshold_minutes, priority_facet, entity_facet, entity_state_source,\n current_schema_version, list_schema, current_list_schema_version,\n default_pins, portals, enforce_schema\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";
71
74
  export declare const GET_ROLE_FORM_SCHEMA = "\n SELECT form_schema FROM lt_roles WHERE role = $1";
72
75
  /**
73
76
  * The set of roles with server-side resolver validation turned on. Small and
@@ -92,7 +95,7 @@ export declare const GET_ROLE_LIST_SCHEMA_VERSION = "\n SELECT s.role, s.versio
92
95
  * never versioned its list schema still answers, with version NULL).
93
96
  */
94
97
  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";
95
- 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.ops_home_default,\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.entity_facet,\n r.entity_state_source,\n r.current_schema_version,\n r.list_schema,\n r.current_list_schema_version,\n r.default_pins,\n r.enforce_schema,\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";
98
+ 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.ops_home_default,\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.entity_facet,\n r.entity_state_source,\n r.current_schema_version,\n r.list_schema,\n r.current_list_schema_version,\n r.default_pins,\n r.portals,\n r.enforce_schema,\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";
96
99
  export declare const COUNT_USER_ROLE_REFS = "\n SELECT COUNT(*)::int AS cnt FROM lt_user_roles WHERE role = $1";
97
100
  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";
98
101
  export declare const COUNT_WORKFLOW_REFS = "\n SELECT COUNT(*)::int AS cnt FROM lt_config_roles WHERE role = $1";
@@ -64,7 +64,7 @@ exports.GET_ROLE_ROW = `
64
64
  r.sla_minutes, r.target_per_hour, r.worker_count,
65
65
  r.priority_threshold_minutes, r.priority_facet,
66
66
  r.entity_facet, r.entity_state_source,
67
- r.list_schema, r.default_pins, r.enforce_schema,
67
+ r.list_schema, r.default_pins, r.portals, r.enforce_schema,
68
68
  r.current_schema_version, r.current_list_schema_version,
69
69
  COALESCE((SELECT array_agg(u.upstream_role ORDER BY u.upstream_role)
70
70
  FROM lt_role_upstreams u WHERE u.role = r.role), '{}') AS upstream_roles
@@ -115,6 +115,9 @@ exports.DELETE_ROLE = `
115
115
  * entity_state_source ($39 = provided sentinel, $40 = value) is unversioned
116
116
  * config: 'role' | 'subtype' — how this role names its contribution to the
117
117
  * entity's state space (the station itself, or its subtypes).
118
+ *
119
+ * portals ($41 = provided sentinel, $42 = value) is unversioned config: the
120
+ * role's named portal views, each a matrix of pin cells rendered as one page.
118
121
  */
119
122
  exports.UPDATE_ROLE_METADATA = `
120
123
  WITH home_clear AS (
@@ -140,6 +143,7 @@ exports.UPDATE_ROLE_METADATA = `
140
143
  = CASE WHEN $39::boolean THEN COALESCE($40, 'role') ELSE entity_state_source END,
141
144
  list_schema = CASE WHEN $29::boolean THEN $30::jsonb ELSE list_schema END,
142
145
  default_pins = CASE WHEN $31::boolean THEN $32::jsonb ELSE default_pins END,
146
+ portals = CASE WHEN $41::boolean THEN $42::jsonb ELSE portals END,
143
147
  enforce_schema = CASE WHEN $33::boolean THEN COALESCE($34::boolean, false) ELSE enforce_schema END,
144
148
  ops_home_default = CASE WHEN $35::boolean THEN COALESCE($36::boolean, false) ELSE ops_home_default END,
145
149
  current_schema_version = CASE
@@ -157,7 +161,7 @@ exports.UPDATE_ROLE_METADATA = `
157
161
  ops_visible, ops_home_default, parent_role, sla_minutes, target_per_hour, worker_count,
158
162
  priority_threshold_minutes, priority_facet, entity_facet, entity_state_source,
159
163
  current_schema_version, list_schema, current_list_schema_version,
160
- default_pins, enforce_schema
164
+ default_pins, portals, enforce_schema
161
165
  ), snapshot AS (
162
166
  INSERT INTO lt_role_schemas (role, version, form_schema, metadata_schema, change_summary)
163
167
  SELECT role, current_schema_version, form_schema, metadata_schema, $26
@@ -304,6 +308,7 @@ exports.LIST_ROLES_WITH_DETAILS = `
304
308
  r.list_schema,
305
309
  r.current_list_schema_version,
306
310
  r.default_pins,
311
+ r.portals,
307
312
  r.enforce_schema,
308
313
  COALESCE(up.ups, '{}') AS upstream_roles,
309
314
  COALESCE(uc.cnt, 0) AS user_count,
@@ -35,6 +35,35 @@ export declare const ROLE_PROPERTY_KEYS: {
35
35
  * binding. Values are strings — jsonb containment is type-sensitive, so
36
36
  * numeric facets are not templatable.
37
37
  */
38
+ /** One pinned view: a label over a dashboard-relative URL, optionally badged with its live count. */
39
+ export interface RolePin {
40
+ label: string;
41
+ url: string;
42
+ badge?: boolean;
43
+ }
44
+ /** Bounds for a role's portals: how many, and the matrix of each (rows of cells, each cell a pin). */
45
+ export declare const PORTAL_LIMITS: {
46
+ readonly MAX_PORTALS: 12;
47
+ readonly MAX_ROWS: 4;
48
+ readonly MAX_COLS: 6;
49
+ readonly MAX_COUNTS: 8;
50
+ };
51
+ /** One count tile above a portal: a label, a blurb, and the live total of an escalations-list URL. */
52
+ export interface PortalCount {
53
+ label: string;
54
+ url: string;
55
+ blurb?: string;
56
+ }
57
+ /** A portal key: a short url-safe slug, unique within the role. */
58
+ export declare const PORTAL_KEY: RegExp;
59
+ /** One named portal view: a matrix of pins rendered as one page. */
60
+ export interface RolePortal {
61
+ key: string;
62
+ label: string;
63
+ rows: RolePin[][];
64
+ /** Count tiles shown above the panels, each the live total of a list URL. */
65
+ counts?: PortalCount[];
66
+ }
38
67
  export interface RoleLinkVariable {
39
68
  name: string;
40
69
  label?: string;
@@ -125,11 +154,12 @@ export interface RoleDetail {
125
154
  * in their Pinned nav section (marked role-provided); users promote, hide,
126
155
  * or reorder them through their own preferences. URLs only — never data.
127
156
  */
128
- default_pins: {
129
- label: string;
130
- url: string;
131
- badge?: boolean;
132
- }[] | null;
157
+ default_pins: RolePin[] | null;
158
+ /**
159
+ * The role's portals: named matrices of pins, each rendered as one page of
160
+ * live list panels at /portal/:role/:portal. Null when the role declares none.
161
+ */
162
+ portals: RolePortal[] | null;
133
163
  /**
134
164
  * Roles this station draws input from that live in OTHER sequences.
135
165
  * parent_role is the single "prior step" placing the role in one sequence;
@@ -185,11 +215,9 @@ export interface UpdateRoleInput {
185
215
  metadata_schema?: Record<string, any> | null;
186
216
  /** JSON contract that richly formats this role's escalation list page. */
187
217
  list_schema?: Record<string, any> | null;
188
- default_pins?: {
189
- label: string;
190
- url: string;
191
- badge?: boolean;
192
- }[] | null;
218
+ default_pins?: RolePin[] | null;
219
+ /** The role's named portals; null clears. */
220
+ portals?: RolePortal[] | null;
193
221
  properties?: Record<string, any> | null;
194
222
  ops_visible?: boolean;
195
223
  /** Make this role's sequence the home Pace Board's default segment (single-holder). */
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  /** Type definitions for the role and escalation chain service. */
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.ROLE_PROPERTY_KEYS = void 0;
4
+ exports.PORTAL_KEY = exports.PORTAL_LIMITS = exports.ROLE_PROPERTY_KEYS = void 0;
5
5
  /**
6
6
  * Reserved keys inside `lt_roles.properties`. Everything else in the bag is
7
7
  * user-owned. Readers type-guard (the bag is open, PATCH can write anything).
@@ -27,3 +27,12 @@ exports.ROLE_PROPERTY_KEYS = {
27
27
  KIOSK: 'kiosk',
28
28
  LINK_VARIABLES: 'link_variables',
29
29
  };
30
+ /** Bounds for a role's portals: how many, and the matrix of each (rows of cells, each cell a pin). */
31
+ exports.PORTAL_LIMITS = {
32
+ MAX_PORTALS: 12,
33
+ MAX_ROWS: 4,
34
+ MAX_COLS: 6,
35
+ MAX_COUNTS: 8,
36
+ };
37
+ /** A portal key: a short url-safe slug, unique within the role. */
38
+ exports.PORTAL_KEY = /^[a-z0-9][a-z0-9-]{0,63}$/;
@@ -1,4 +1,4 @@
1
1
  export { listScanSchemes, getScanScheme, listScanRules, getScanRule, } from './read';
2
2
  export { upsertScanScheme, deleteScanScheme, upsertScanRule, deleteScanRule, seedScanScheme, seedScanRule, applyScanScheme, applyScanRule, type ScanSchemeInput, type ScanRuleInput, } from './write';
3
- export { parseScanCode, interpolateScanTemplate, type ScanParseResult, type ScanParseFailure, type ScanTemplateContext, } from './parse';
3
+ export { parseScanCode, interpolateScanTemplate, mentionsClaimToken, ScanTemplateError, type ScanParseResult, type ScanParseFailure, type ScanTemplateContext, } from './parse';
4
4
  export { assertValidScheme, assertValidSteps } from './validate';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.assertValidSteps = exports.assertValidScheme = exports.interpolateScanTemplate = exports.parseScanCode = exports.applyScanRule = exports.applyScanScheme = exports.seedScanRule = exports.seedScanScheme = exports.deleteScanRule = exports.upsertScanRule = exports.deleteScanScheme = exports.upsertScanScheme = exports.getScanRule = exports.listScanRules = exports.getScanScheme = exports.listScanSchemes = void 0;
3
+ exports.assertValidSteps = exports.assertValidScheme = exports.ScanTemplateError = exports.mentionsClaimToken = exports.interpolateScanTemplate = exports.parseScanCode = exports.applyScanRule = exports.applyScanScheme = exports.seedScanRule = exports.seedScanScheme = exports.deleteScanRule = exports.upsertScanRule = exports.deleteScanScheme = exports.upsertScanScheme = exports.getScanRule = exports.listScanRules = exports.getScanScheme = exports.listScanSchemes = void 0;
4
4
  var read_1 = require("./read");
5
5
  Object.defineProperty(exports, "listScanSchemes", { enumerable: true, get: function () { return read_1.listScanSchemes; } });
6
6
  Object.defineProperty(exports, "getScanScheme", { enumerable: true, get: function () { return read_1.getScanScheme; } });
@@ -18,6 +18,8 @@ Object.defineProperty(exports, "applyScanRule", { enumerable: true, get: functio
18
18
  var parse_1 = require("./parse");
19
19
  Object.defineProperty(exports, "parseScanCode", { enumerable: true, get: function () { return parse_1.parseScanCode; } });
20
20
  Object.defineProperty(exports, "interpolateScanTemplate", { enumerable: true, get: function () { return parse_1.interpolateScanTemplate; } });
21
+ Object.defineProperty(exports, "mentionsClaimToken", { enumerable: true, get: function () { return parse_1.mentionsClaimToken; } });
22
+ Object.defineProperty(exports, "ScanTemplateError", { enumerable: true, get: function () { return parse_1.ScanTemplateError; } });
21
23
  var validate_1 = require("./validate");
22
24
  Object.defineProperty(exports, "assertValidScheme", { enumerable: true, get: function () { return validate_1.assertValidScheme; } });
23
25
  Object.defineProperty(exports, "assertValidSteps", { enumerable: true, get: function () { return validate_1.assertValidSteps; } });
@@ -26,10 +26,24 @@ export interface ScanTemplateContext {
26
26
  target: string;
27
27
  category: string;
28
28
  scannedAt: string;
29
+ /** The acting user's single live claim, its metadata; absent when none or ambiguous. */
30
+ claim?: Record<string, unknown>;
31
+ /** The row an item-mode accumulate step located, its metadata. */
32
+ item?: Record<string, unknown>;
29
33
  }
34
+ /** A `{claim.x}` or `{item.x}` token the context cannot resolve. */
35
+ export declare class ScanTemplateError extends Error {
36
+ readonly token: string;
37
+ readonly reason: string;
38
+ constructor(token: string, reason: string);
39
+ }
40
+ /** True when any string in the params mentions a `{claim.…}` token. */
41
+ export declare function mentionsClaimToken(value: unknown): boolean;
30
42
  /**
31
- * Replace SCAN_TEMPLATE_TOKENS inside string values of a params object.
32
- * Deep, pure, non-mutating. Only exact-token and in-string replacement of
33
- * the three known tokens no expression language.
43
+ * Replace the template tokens inside string values of a params object.
44
+ * Deep, pure, non-mutating. The three scan tokens are plain text
45
+ * replacement; `{claim.<facet>}` and `{item.<facet>}` read the context's
46
+ * facet bags and throw {@link ScanTemplateError} when they cannot resolve,
47
+ * so a literal token never reaches a row. No expression language.
34
48
  */
35
49
  export declare function interpolateScanTemplate<T>(value: T, ctx: ScanTemplateContext): T;
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ScanTemplateError = void 0;
3
4
  exports.parseScanCode = parseScanCode;
5
+ exports.mentionsClaimToken = mentionsClaimToken;
4
6
  exports.interpolateScanTemplate = interpolateScanTemplate;
5
7
  const types_1 = require("../../types");
6
8
  /**
@@ -82,17 +84,48 @@ function malformed(scheme, detail) {
82
84
  failure: { reason: 'malformed', detail: `scheme ${scheme.version} ("${scheme.name}"): ${detail}` },
83
85
  };
84
86
  }
87
+ /** A `{claim.x}` or `{item.x}` token the context cannot resolve. */
88
+ class ScanTemplateError extends Error {
89
+ constructor(token, reason) {
90
+ super(`scan template ${token}: ${reason}`);
91
+ this.token = token;
92
+ this.reason = reason;
93
+ this.name = 'ScanTemplateError';
94
+ }
95
+ }
96
+ exports.ScanTemplateError = ScanTemplateError;
97
+ const BAG_TOKEN = /\{(claim|item)\.([a-zA-Z0-9_]+)\}/g;
98
+ /** True when any string in the params mentions a `{claim.…}` token. */
99
+ function mentionsClaimToken(value) {
100
+ return JSON.stringify(value ?? null).includes(`{${types_1.SCAN_TEMPLATE_BAGS.CLAIM}.`);
101
+ }
102
+ function resolveBagToken(ctx, bag, facet, token) {
103
+ const source = bag === types_1.SCAN_TEMPLATE_BAGS.CLAIM ? ctx.claim : ctx.item;
104
+ if (!source) {
105
+ throw new ScanTemplateError(token, bag === types_1.SCAN_TEMPLATE_BAGS.CLAIM
106
+ ? 'the actor holds no single live claim'
107
+ : 'no located item row on this step');
108
+ }
109
+ const v = source[facet];
110
+ if (v === undefined || v === null || v === '') {
111
+ throw new ScanTemplateError(token, `facet ${facet} is absent`);
112
+ }
113
+ return typeof v === 'object' ? JSON.stringify(v) : String(v);
114
+ }
85
115
  /**
86
- * Replace SCAN_TEMPLATE_TOKENS inside string values of a params object.
87
- * Deep, pure, non-mutating. Only exact-token and in-string replacement of
88
- * the three known tokens no expression language.
116
+ * Replace the template tokens inside string values of a params object.
117
+ * Deep, pure, non-mutating. The three scan tokens are plain text
118
+ * replacement; `{claim.<facet>}` and `{item.<facet>}` read the context's
119
+ * facet bags and throw {@link ScanTemplateError} when they cannot resolve,
120
+ * so a literal token never reaches a row. No expression language.
89
121
  */
90
122
  function interpolateScanTemplate(value, ctx) {
91
123
  if (typeof value === 'string') {
92
- return value
124
+ const scanned = value
93
125
  .split(types_1.SCAN_TEMPLATE_TOKENS.TARGET).join(ctx.target)
94
126
  .split(types_1.SCAN_TEMPLATE_TOKENS.CATEGORY).join(ctx.category)
95
127
  .split(types_1.SCAN_TEMPLATE_TOKENS.SCANNED_AT).join(ctx.scannedAt);
128
+ return scanned.replace(BAG_TOKEN, (token, bag, facet) => resolveBagToken(ctx, bag, facet, token));
96
129
  }
97
130
  if (Array.isArray(value)) {
98
131
  return value.map((v) => interpolateScanTemplate(v, ctx));
@@ -4,6 +4,7 @@ exports.assertValidScheme = assertValidScheme;
4
4
  exports.assertValidIdentityRule = assertValidIdentityRule;
5
5
  exports.assertValidSteps = assertValidSteps;
6
6
  const types_1 = require("../../types");
7
+ const facet_sql_1 = require("../escalation/facet-sql");
7
8
  const VALID_VERBS = new Set(Object.values(types_1.SCAN_VERBS));
8
9
  /** Double-scan selection tokens — short, label-printable, never scheme-shaped. */
9
10
  const CHOICE_CODE = /^[A-Za-z0-9_-]{1,32}$/;
@@ -145,6 +146,22 @@ function assertValidSteps(steps) {
145
146
  if (step.verb === types_1.SCAN_VERBS.RESOLVE && !step.params?.resolverPayload) {
146
147
  throw new Error(`${at}: resolve requires params.resolverPayload`);
147
148
  }
149
+ if (step.verb === types_1.SCAN_VERBS.ACCUMULATE) {
150
+ const options = step.params?.accumulate;
151
+ if (options !== undefined && (!options || typeof options !== 'object' || Array.isArray(options))) {
152
+ throw new Error(`${at}: params.accumulate must be an object`);
153
+ }
154
+ if (options?.containerFacet !== undefined && !facet_sql_1.FACET_KEY.test(String(options.containerFacet))) {
155
+ throw new Error(`${at}: params.accumulate.containerFacet must be a facet key`);
156
+ }
157
+ if (options?.containerRoles !== undefined && !Array.isArray(options.containerRoles)) {
158
+ throw new Error(`${at}: params.accumulate.containerRoles must be an array`);
159
+ }
160
+ if (!options?.containerFacet && !step.params?.itemKey) {
161
+ throw new Error(`${at}: accumulate requires params.itemKey or params.accumulate.containerFacet`);
162
+ }
163
+ }
164
+ assertValidTemplateTokens(step, at);
148
165
  if (step.query && step.query.roles && !Array.isArray(step.query.roles)) {
149
166
  throw new Error(`${at}: query.roles must be an array`);
150
167
  }
@@ -162,3 +179,21 @@ function assertValidSteps(steps) {
162
179
  }
163
180
  });
164
181
  }
182
+ const BAG_TOKEN = /\{(claim|item)\.([^}]*)\}/g;
183
+ /**
184
+ * `{claim.<facet>}` and `{item.<facet>}` name facet keys; `{item.…}` reads
185
+ * the located row, which only an item-mode accumulate step has.
186
+ */
187
+ function assertValidTemplateTokens(step, at) {
188
+ const text = JSON.stringify(step.params ?? {});
189
+ const itemMode = step.verb === types_1.SCAN_VERBS.ACCUMULATE && !!step.params?.accumulate?.containerFacet;
190
+ for (const match of text.matchAll(BAG_TOKEN)) {
191
+ const [token, bag, facet] = match;
192
+ if (!facet_sql_1.FACET_KEY.test(facet)) {
193
+ throw new Error(`${at}: template token ${token} must name a facet key`);
194
+ }
195
+ if (bag === 'item' && !itemMode) {
196
+ throw new Error(`${at}: ${token} reads the located item row, which only an item-mode accumulate step has`);
197
+ }
198
+ }
199
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Widgets that render from the escalation context and produce no answer of
3
+ * their own: navigation links, embedded records and lists, and invoke
4
+ * controls. Their form slot exists only to place them in the layout, so
5
+ * the payload mapper drops them and the server never sees a value.
6
+ */
7
+ export declare const DISPLAY_ONLY_WIDGET_NAMES: {
8
+ readonly LINK: "link";
9
+ readonly ESCALATION: "escalation";
10
+ readonly ESCALATION_LIST: "escalation-list";
11
+ readonly INVOKE: "invoke";
12
+ };
13
+ export declare const DISPLAY_ONLY_WIDGETS: ReadonlySet<string>;
14
+ export declare function isDisplayOnlyWidget(name: unknown): boolean;
15
+ /** Whether a property definition renders a display-only widget. */
16
+ export declare function isDisplayOnlyField(def: Record<string, unknown> | null | undefined): boolean;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DISPLAY_ONLY_WIDGETS = exports.DISPLAY_ONLY_WIDGET_NAMES = void 0;
4
+ exports.isDisplayOnlyWidget = isDisplayOnlyWidget;
5
+ exports.isDisplayOnlyField = isDisplayOnlyField;
6
+ /**
7
+ * Widgets that render from the escalation context and produce no answer of
8
+ * their own: navigation links, embedded records and lists, and invoke
9
+ * controls. Their form slot exists only to place them in the layout, so
10
+ * the payload mapper drops them and the server never sees a value.
11
+ */
12
+ exports.DISPLAY_ONLY_WIDGET_NAMES = {
13
+ LINK: 'link',
14
+ ESCALATION: 'escalation',
15
+ ESCALATION_LIST: 'escalation-list',
16
+ INVOKE: 'invoke',
17
+ };
18
+ exports.DISPLAY_ONLY_WIDGETS = new Set(Object.values(exports.DISPLAY_ONLY_WIDGET_NAMES));
19
+ function isDisplayOnlyWidget(name) {
20
+ return typeof name === 'string' && exports.DISPLAY_ONLY_WIDGETS.has(name);
21
+ }
22
+ /** Whether a property definition renders a display-only widget. */
23
+ function isDisplayOnlyField(def) {
24
+ return isDisplayOnlyWidget(def?.['x-lt-widget']);
25
+ }
@@ -20,3 +20,5 @@ export * from './ctx-path';
20
20
  export * from './field-validator';
21
21
  export * from './validate-resolver-payload';
22
22
  export * from './invoke-context';
23
+ export * from './display-only-widgets';
24
+ export * from './x-lt-invoke';
@@ -36,3 +36,5 @@ __exportStar(require("./ctx-path"), exports);
36
36
  __exportStar(require("./field-validator"), exports);
37
37
  __exportStar(require("./validate-resolver-payload"), exports);
38
38
  __exportStar(require("./invoke-context"), exports);
39
+ __exportStar(require("./display-only-widgets"), exports);
40
+ __exportStar(require("./x-lt-invoke"), exports);
@@ -1,16 +1,3 @@
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
1
  type PathSeg = {
15
2
  key: string;
16
3
  } | {
@@ -27,7 +14,8 @@ export declare function bindPathFor(propName: string, propDef: Record<string, an
27
14
  /**
28
15
  * Assemble the payload from the form's flat values. A field absent from
29
16
  * `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
17
+ * payload). Unknown keys not declared in the schema are dropped, and so are
18
+ * display-only widget fields, which carry no answer. With no schema
31
19
  * properties, values pass through unchanged.
32
20
  */
33
21
  export declare function mapFormToPayload(formValues: Record<string, any>, formSchema: Record<string, any> | null | undefined): Record<string, any>;
@@ -1,4 +1,11 @@
1
1
  "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parsePath = parsePath;
4
+ exports.setDeep = setDeep;
5
+ exports.getDeep = getDeep;
6
+ exports.bindPathFor = bindPathFor;
7
+ exports.mapFormToPayload = mapFormToPayload;
8
+ exports.mapPayloadToForm = mapPayloadToForm;
2
9
  /**
3
10
  * x-lt-bind — maps the escalation FORM (flat field values the user edits) to and
4
11
  * from the PAYLOAD (the nested JSON the workflow consumes). A form_schema property
@@ -12,13 +19,7 @@
12
19
  * (server-side: to validate a submitted payload)
13
20
  * mapFormToPayload — flat form values → payload, the shape submitted/stored
14
21
  */
15
- Object.defineProperty(exports, "__esModule", { value: true });
16
- exports.parsePath = parsePath;
17
- exports.setDeep = setDeep;
18
- exports.getDeep = getDeep;
19
- exports.bindPathFor = bindPathFor;
20
- exports.mapFormToPayload = mapFormToPayload;
21
- exports.mapPayloadToForm = mapPayloadToForm;
22
+ const display_only_widgets_1 = require("./display-only-widgets");
22
23
  const BLOCKED_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
23
24
  /** Parse a bind path — dot keys with optional `[n]` indices. Rejects pollution keys. */
24
25
  function parsePath(path) {
@@ -75,7 +76,8 @@ function bindPathFor(propName, propDef) {
75
76
  /**
76
77
  * Assemble the payload from the form's flat values. A field absent from
77
78
  * `formValues` is omitted (so clearing/deleting a field drops it from the
78
- * payload). Unknown keys not declared in the schema are dropped. With no schema
79
+ * payload). Unknown keys not declared in the schema are dropped, and so are
80
+ * display-only widget fields, which carry no answer. With no schema
79
81
  * properties, values pass through unchanged.
80
82
  */
81
83
  function mapFormToPayload(formValues, formSchema) {
@@ -86,6 +88,8 @@ function mapFormToPayload(formValues, formSchema) {
86
88
  for (const [name, def] of Object.entries(props)) {
87
89
  if (!(name in formValues))
88
90
  continue;
91
+ if ((0, display_only_widgets_1.isDisplayOnlyField)(def))
92
+ continue;
89
93
  setDeep(payload, bindPathFor(name, def), formValues[name]);
90
94
  }
91
95
  return payload;
@@ -0,0 +1,38 @@
1
+ export declare const X_LT_INVOKE = "x-lt-invoke";
2
+ export declare const INVOKE_WIDGET: "invoke";
3
+ export declare const INVOKE_VARIANTS: {
4
+ readonly LINK: "link";
5
+ readonly BUTTON: "button";
6
+ };
7
+ export type InvokeVariant = (typeof INVOKE_VARIANTS)[keyof typeof INVOKE_VARIANTS];
8
+ export interface InvokeConfig {
9
+ /** The workflow_type to start. */
10
+ workflow: string;
11
+ /** Nested invoke `data` template; leaves interpolate against the context. */
12
+ data: Record<string, unknown>;
13
+ /** Extra run metadata template, merged over the workflow's declared metadata. */
14
+ metadata: Record<string, unknown>;
15
+ /** Open the workflow's input form prefilled instead of posting directly. */
16
+ modal: boolean;
17
+ /** Direct mode only: a prompt to confirm before posting; tokens interpolate. */
18
+ confirm: string | null;
19
+ variant: InvokeVariant;
20
+ /** Lead the label with the workflow's registered icon. */
21
+ icon: boolean;
22
+ }
23
+ export interface InvokePayload {
24
+ data: Record<string, unknown>;
25
+ metadata: Record<string, unknown>;
26
+ }
27
+ type Ctx = Record<string, unknown> | null | undefined;
28
+ /** The field's invoke declaration, or null when it names no workflow. */
29
+ export declare function readInvokeConfig(fieldSchema: Record<string, unknown> | null | undefined): InvokeConfig | null;
30
+ /**
31
+ * Resolve one template value against the context, keeping the type of a
32
+ * whole-token leaf. Returns undefined for a token with no value so the
33
+ * caller omits the key.
34
+ */
35
+ export declare function interpolateInvokeValue(value: unknown, ctx: Ctx): unknown;
36
+ /** The invoke payload for one context: `data` and `metadata` fully resolved. */
37
+ export declare function resolveInvokePayload(config: InvokeConfig, ctx: Ctx): InvokePayload;
38
+ export {};
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.INVOKE_VARIANTS = exports.INVOKE_WIDGET = exports.X_LT_INVOKE = void 0;
4
+ exports.readInvokeConfig = readInvokeConfig;
5
+ exports.interpolateInvokeValue = interpolateInvokeValue;
6
+ exports.resolveInvokePayload = resolveInvokePayload;
7
+ /**
8
+ * x-lt-invoke: start a workflow from inside a form. A display-only field
9
+ * declares the target workflow and how the form's context maps into the
10
+ * invoke payload:
11
+ *
12
+ * "x-lt-widget": "invoke",
13
+ * "x-lt-invoke": {
14
+ * "workflow": "printPamphlet",
15
+ * "data": { "order": { "id": "{{metadata.orderId}}" }, "copies": 1 },
16
+ * "metadata": { "escalationId": "{{escalation.id}}" },
17
+ * "modal": true,
18
+ * "confirm": "Print a pamphlet for {{metadata.orderId}}?",
19
+ * "variant": "link",
20
+ * "icon": true
21
+ * }
22
+ *
23
+ * `data` is the nested payload the invoke API receives. In direct mode it is
24
+ * posted as resolved; in modal mode it prefills the workflow's own input form
25
+ * through the x-lt-bind inversion. One declaration serves both.
26
+ *
27
+ * Interpolation keeps types: a leaf that is exactly one `{{domain.path}}`
28
+ * token becomes the raw context value (a number stays a number); a leaf that
29
+ * mixes text and tokens becomes a string; a token with no value drops its key
30
+ * so the target's own defaults apply. Objects and arrays recurse; every other
31
+ * leaf passes through unchanged.
32
+ */
33
+ const display_only_widgets_1 = require("./display-only-widgets");
34
+ const ctx_path_1 = require("./ctx-path");
35
+ exports.X_LT_INVOKE = 'x-lt-invoke';
36
+ exports.INVOKE_WIDGET = display_only_widgets_1.DISPLAY_ONLY_WIDGET_NAMES.INVOKE;
37
+ exports.INVOKE_VARIANTS = {
38
+ LINK: 'link',
39
+ BUTTON: 'button',
40
+ };
41
+ const WHOLE_TOKEN_PATTERN = /^\{\{\s*([^{}]+?)\s*\}\}$/;
42
+ function isPlainObject(value) {
43
+ return !!value && typeof value === 'object' && !Array.isArray(value);
44
+ }
45
+ function isVariant(value) {
46
+ return value === exports.INVOKE_VARIANTS.LINK || value === exports.INVOKE_VARIANTS.BUTTON;
47
+ }
48
+ /** The field's invoke declaration, or null when it names no workflow. */
49
+ function readInvokeConfig(fieldSchema) {
50
+ const raw = fieldSchema?.[exports.X_LT_INVOKE];
51
+ if (!isPlainObject(raw))
52
+ return null;
53
+ const workflow = raw.workflow;
54
+ if (typeof workflow !== 'string' || workflow.trim().length === 0)
55
+ return null;
56
+ const confirm = raw.confirm;
57
+ return {
58
+ workflow: workflow.trim(),
59
+ data: isPlainObject(raw.data) ? raw.data : {},
60
+ metadata: isPlainObject(raw.metadata) ? raw.metadata : {},
61
+ modal: raw.modal === true,
62
+ confirm: typeof confirm === 'string' && confirm.trim().length > 0 ? confirm : null,
63
+ variant: isVariant(raw.variant) ? raw.variant : exports.INVOKE_VARIANTS.LINK,
64
+ icon: raw.icon !== false,
65
+ };
66
+ }
67
+ /**
68
+ * Resolve one template value against the context, keeping the type of a
69
+ * whole-token leaf. Returns undefined for a token with no value so the
70
+ * caller omits the key.
71
+ */
72
+ function interpolateInvokeValue(value, ctx) {
73
+ if (typeof value === 'string') {
74
+ const whole = WHOLE_TOKEN_PATTERN.exec(value);
75
+ if (whole) {
76
+ const resolved = (0, ctx_path_1.resolveCtxPath)(whole[1], ctx ?? undefined);
77
+ return resolved === null ? undefined : resolved;
78
+ }
79
+ if ((0, ctx_path_1.hasInterpolation)(value))
80
+ return (0, ctx_path_1.interpolatePath)(value, ctx ?? undefined) ?? undefined;
81
+ return value;
82
+ }
83
+ if (Array.isArray(value)) {
84
+ return value.map((v) => interpolateInvokeValue(v, ctx)).filter((v) => v !== undefined);
85
+ }
86
+ if (isPlainObject(value)) {
87
+ const out = {};
88
+ for (const [key, v] of Object.entries(value)) {
89
+ const resolved = interpolateInvokeValue(v, ctx);
90
+ if (resolved !== undefined)
91
+ out[key] = resolved;
92
+ }
93
+ return out;
94
+ }
95
+ return value;
96
+ }
97
+ /** The invoke payload for one context: `data` and `metadata` fully resolved. */
98
+ function resolveInvokePayload(config, ctx) {
99
+ return {
100
+ data: interpolateInvokeValue(config.data, ctx),
101
+ metadata: interpolateInvokeValue(config.metadata, ctx),
102
+ };
103
+ }