@hotmeshio/long-tail 0.10.13 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (373) hide show
  1. package/README.md +2 -4
  2. package/build/api/escalations/analytics.d.ts +6 -0
  3. package/build/api/escalations/analytics.js +123 -0
  4. package/build/api/escalations/index.d.ts +1 -0
  5. package/build/api/escalations/index.js +4 -1
  6. package/build/api/escalations/metadata.js +1 -1
  7. package/build/api/escalations/resolve.js +4 -4
  8. package/build/api/roles.d.ts +4 -0
  9. package/build/api/roles.js +8 -0
  10. package/build/api/scan-codes/choice.d.ts +11 -0
  11. package/build/api/scan-codes/choice.js +136 -0
  12. package/build/api/scan-codes/context.d.ts +24 -0
  13. package/build/api/scan-codes/context.js +86 -0
  14. package/build/api/scan-codes/execute.d.ts +1 -0
  15. package/build/api/scan-codes/execute.js +49 -244
  16. package/build/api/scan-codes/identity.d.ts +18 -0
  17. package/build/api/scan-codes/identity.js +116 -0
  18. package/build/api/scan-codes/index.d.ts +2 -0
  19. package/build/api/scan-codes/index.js +6 -1
  20. package/build/api/scan-codes/locate.d.ts +14 -0
  21. package/build/api/scan-codes/locate.js +127 -0
  22. package/build/api/scan-codes/present.d.ts +9 -0
  23. package/build/api/scan-codes/present.js +59 -0
  24. package/build/api/scan-codes/verbs.d.ts +15 -0
  25. package/build/api/scan-codes/verbs.js +205 -0
  26. package/build/bin/ltc.js +33 -0
  27. package/build/lib/cli/commands/escalations.d.ts +31 -0
  28. package/build/lib/cli/commands/escalations.js +88 -0
  29. package/build/lib/db/schemas/028_role_entity_facet.sql +18 -0
  30. package/build/lib/db/schemas/029_scan_scheme_kind.sql +31 -0
  31. package/build/modules/config.d.ts +5 -0
  32. package/build/modules/config.js +12 -0
  33. package/build/routes/escalations/acting.d.ts +12 -0
  34. package/build/routes/escalations/acting.js +25 -0
  35. package/build/routes/escalations/analytics.d.ts +8 -0
  36. package/build/routes/escalations/analytics.js +63 -0
  37. package/build/routes/escalations/index.js +3 -0
  38. package/build/routes/escalations/resolve.js +8 -1
  39. package/build/routes/escalations/single.js +13 -4
  40. package/build/routes/roles.js +1 -1
  41. package/build/routes/scan-codes.js +28 -2
  42. package/build/scripts/ortho-populate.js +14 -0
  43. package/build/scripts/printer-cycle.d.ts +25 -0
  44. package/build/scripts/printer-cycle.js +169 -0
  45. package/build/scripts/twin-farm.js +19 -5
  46. package/build/sdk/index.d.ts +2 -0
  47. package/build/sdk/index.js +3 -0
  48. package/build/services/escalation/aggregate-sql.d.ts +36 -0
  49. package/build/services/escalation/aggregate-sql.js +253 -0
  50. package/build/services/escalation/aggregate-validate.d.ts +57 -0
  51. package/build/services/escalation/aggregate-validate.js +218 -0
  52. package/build/services/escalation/aggregates.d.ts +26 -0
  53. package/build/services/escalation/aggregates.js +204 -0
  54. package/build/services/escalation/client.js +57 -21
  55. package/build/services/escalation/facet-sql.js +17 -0
  56. package/build/services/escalation/index.d.ts +2 -0
  57. package/build/services/escalation/index.js +8 -1
  58. package/build/services/escalation/metrics-cache.d.ts +18 -0
  59. package/build/services/escalation/metrics-cache.js +47 -1
  60. package/build/services/escalation/queries.js +2 -0
  61. package/build/services/escalation/resolver-validation.d.ts +1 -1
  62. package/build/services/escalation/resolver-validation.js +12 -5
  63. package/build/services/escalation/submit-guard.d.ts +29 -0
  64. package/build/services/escalation/submit-guard.js +57 -0
  65. package/build/services/iam/acting-identity.d.ts +16 -0
  66. package/build/services/iam/acting-identity.js +60 -0
  67. package/build/services/role/index.js +2 -0
  68. package/build/services/role/sql.d.ts +10 -2
  69. package/build/services/role/sql.js +14 -1
  70. package/build/services/role/types.d.ts +16 -0
  71. package/build/services/scan-code/read.js +4 -0
  72. package/build/services/scan-code/sql.d.ts +4 -4
  73. package/build/services/scan-code/sql.js +14 -8
  74. package/build/services/scan-code/validate.d.ts +2 -0
  75. package/build/services/scan-code/validate.js +86 -0
  76. package/build/services/scan-code/write.d.ts +4 -0
  77. package/build/services/scan-code/write.js +16 -2
  78. package/build/services/user/crud.d.ts +6 -0
  79. package/build/services/user/crud.js +16 -0
  80. package/build/services/user/index.d.ts +1 -1
  81. package/build/services/user/index.js +2 -1
  82. package/build/services/user/sql.d.ts +8 -0
  83. package/build/services/user/sql.js +9 -1
  84. package/build/shared/form-validation/index.d.ts +4 -0
  85. package/build/shared/form-validation/index.js +4 -0
  86. package/build/shared/form-validation/x-lt-labels.d.ts +28 -0
  87. package/build/shared/form-validation/x-lt-labels.js +42 -0
  88. package/build/shared/form-validation/x-lt-query.d.ts +56 -0
  89. package/build/shared/form-validation/x-lt-query.js +49 -0
  90. package/build/shared/form-validation/x-lt-submit-guard.d.ts +46 -0
  91. package/build/shared/form-validation/x-lt-submit-guard.js +25 -0
  92. package/build/shared/form-validation/x-lt-submit-on-claim.d.ts +22 -0
  93. package/build/shared/form-validation/x-lt-submit-on-claim.js +28 -0
  94. package/build/system/mcp-servers/admin/escalations.js +34 -0
  95. package/build/system/mcp-servers/admin/scan-codes.js +17 -1
  96. package/build/system/mcp-servers/admin/schemas.d.ts +643 -25
  97. package/build/system/mcp-servers/admin/schemas.js +127 -19
  98. package/build/system/mcp-servers/admin/users.js +3 -1
  99. package/build/system/mcp-servers/human-queue-schemas.d.ts +2 -2
  100. package/build/system/seed/tool-manifests-admin.d.ts +2283 -0
  101. package/build/system/seed/tool-manifests-admin.js +8 -5
  102. package/build/tsconfig.tsbuildinfo +1 -1
  103. package/build/types/analytics.d.ts +154 -0
  104. package/build/types/analytics.js +14 -0
  105. package/build/types/facets.d.ts +13 -0
  106. package/build/types/index.d.ts +5 -2
  107. package/build/types/index.js +5 -1
  108. package/build/types/scan-choice.d.ts +49 -0
  109. package/build/types/scan-choice.js +9 -0
  110. package/build/types/scan-code.d.ts +72 -1
  111. package/build/types/scan-code.js +30 -1
  112. package/dashboard/dist/assets/{AdminDashboard-Bv3pHBzn.js → AdminDashboard-DJ3LJQ09.js} +2 -2
  113. package/dashboard/dist/assets/{AdminDashboard-Bv3pHBzn.js.map → AdminDashboard-DJ3LJQ09.js.map} +1 -1
  114. package/dashboard/dist/assets/{AgentConfigPage-Dk2zlvDb.js → AgentConfigPage-BMMvaD0z.js} +2 -2
  115. package/dashboard/dist/assets/{AgentConfigPage-Dk2zlvDb.js.map → AgentConfigPage-BMMvaD0z.js.map} +1 -1
  116. package/dashboard/dist/assets/{AgentDetailPage-DUno6EGs.js → AgentDetailPage-C6wfsnRe.js} +2 -2
  117. package/dashboard/dist/assets/{AgentDetailPage-DUno6EGs.js.map → AgentDetailPage-C6wfsnRe.js.map} +1 -1
  118. package/dashboard/dist/assets/AgentsPage-Cwqka7nE.js +2 -0
  119. package/dashboard/dist/assets/{AgentsPage-CToVu1qj.js.map → AgentsPage-Cwqka7nE.js.map} +1 -1
  120. package/dashboard/dist/assets/AvailableEscalationsPage-CVlG_AVC.js +2 -0
  121. package/dashboard/dist/assets/AvailableEscalationsPage-CVlG_AVC.js.map +1 -0
  122. package/dashboard/dist/assets/{BotPicker-DQOpVB4M.js → BotPicker-BBkJBXZB.js} +2 -2
  123. package/dashboard/dist/assets/{BotPicker-DQOpVB4M.js.map → BotPicker-BBkJBXZB.js.map} +1 -1
  124. package/dashboard/dist/assets/{CapabilitiesPage-Dmf46PUJ.js → CapabilitiesPage-wxmE4917.js} +2 -2
  125. package/dashboard/dist/assets/{CapabilitiesPage-Dmf46PUJ.js.map → CapabilitiesPage-wxmE4917.js.map} +1 -1
  126. package/dashboard/dist/assets/{CollapsibleSection-CDADefUY.js → CollapsibleSection-B3FsrHwH.js} +2 -2
  127. package/dashboard/dist/assets/{CollapsibleSection-CDADefUY.js.map → CollapsibleSection-B3FsrHwH.js.map} +1 -1
  128. package/dashboard/dist/assets/CountdownTimer-B3nCqJdC.js +2 -0
  129. package/dashboard/dist/assets/CountdownTimer-B3nCqJdC.js.map +1 -0
  130. package/dashboard/dist/assets/{CredentialsPage-8LIEvomi.js → CredentialsPage-Bv875IHe.js} +2 -2
  131. package/dashboard/dist/assets/{CredentialsPage-8LIEvomi.js.map → CredentialsPage-Bv875IHe.js.map} +1 -1
  132. package/dashboard/dist/assets/{CronLabel-CK3WSsM5.js → CronLabel-CSzjWuwj.js} +2 -2
  133. package/dashboard/dist/assets/{CronLabel-CK3WSsM5.js.map → CronLabel-CSzjWuwj.js.map} +1 -1
  134. package/dashboard/dist/assets/{CustomDurationPicker-FPmlA6cE.js → CustomDurationPicker-CCpqf3e4.js} +2 -2
  135. package/dashboard/dist/assets/{CustomDurationPicker-FPmlA6cE.js.map → CustomDurationPicker-CCpqf3e4.js.map} +1 -1
  136. package/dashboard/dist/assets/{DropZone-CL9gA7pu.js → DropZone-CJkk-U3o.js} +2 -2
  137. package/dashboard/dist/assets/{DropZone-CL9gA7pu.js.map → DropZone-CJkk-U3o.js.map} +1 -1
  138. package/dashboard/dist/assets/{ElapsedCell-BZVkVxE0.js → ElapsedCell-WV6pUaKo.js} +2 -2
  139. package/dashboard/dist/assets/{ElapsedCell-BZVkVxE0.js.map → ElapsedCell-WV6pUaKo.js.map} +1 -1
  140. package/dashboard/dist/assets/EntityTimelinePanel-DrL86Yrf.js +2 -0
  141. package/dashboard/dist/assets/EntityTimelinePanel-DrL86Yrf.js.map +1 -0
  142. package/dashboard/dist/assets/{EscalationListSchemaPage-kYLdUtZX.js → EscalationListSchemaPage-CTQCALw4.js} +3 -3
  143. package/dashboard/dist/assets/{EscalationListSchemaPage-kYLdUtZX.js.map → EscalationListSchemaPage-CTQCALw4.js.map} +1 -1
  144. package/dashboard/dist/assets/{EscalationSchemaPage-kUmCDivo.js → EscalationSchemaPage-D_UgP0pv.js} +3 -3
  145. package/dashboard/dist/assets/{EscalationSchemaPage-kUmCDivo.js.map → EscalationSchemaPage-D_UgP0pv.js.map} +1 -1
  146. package/dashboard/dist/assets/{EscalationsOverview-D17auO-m.js → EscalationsOverview-DuIUyxr0.js} +2 -2
  147. package/dashboard/dist/assets/{EscalationsOverview-D17auO-m.js.map → EscalationsOverview-DuIUyxr0.js.map} +1 -1
  148. package/dashboard/dist/assets/EventTable-BV6unphX.js +2 -0
  149. package/dashboard/dist/assets/EventTable-BV6unphX.js.map +1 -0
  150. package/dashboard/dist/assets/FilterBar-DYFgzXNB.js +2 -0
  151. package/dashboard/dist/assets/FilterBar-DYFgzXNB.js.map +1 -0
  152. package/dashboard/dist/assets/{GraphInvokePage-D11uOnZi.js → GraphInvokePage-BGHVUipJ.js} +2 -2
  153. package/dashboard/dist/assets/{GraphInvokePage-D11uOnZi.js.map → GraphInvokePage-BGHVUipJ.js.map} +1 -1
  154. package/dashboard/dist/assets/HomePage-B-S2cK3E.js +2 -0
  155. package/dashboard/dist/assets/{HomePage-Bcq10Bxx.js.map → HomePage-B-S2cK3E.js.map} +1 -1
  156. package/dashboard/dist/assets/ListToolbar-Bl7F3A28.js +2 -0
  157. package/dashboard/dist/assets/{ListToolbar-IPXsTb3Q.js.map → ListToolbar-Bl7F3A28.js.map} +1 -1
  158. package/dashboard/dist/assets/{McpOverview-Dx2j0KkF.js → McpOverview-_T9IsCD_.js} +2 -2
  159. package/dashboard/dist/assets/{McpOverview-Dx2j0KkF.js.map → McpOverview-_T9IsCD_.js.map} +1 -1
  160. package/dashboard/dist/assets/{McpQueryDetailPage-CzF_bna8.js → McpQueryDetailPage-DtsVqKPw.js} +2 -2
  161. package/dashboard/dist/assets/{McpQueryDetailPage-CzF_bna8.js.map → McpQueryDetailPage-DtsVqKPw.js.map} +1 -1
  162. package/dashboard/dist/assets/McpQueryPage-DX5u-1bx.js +2 -0
  163. package/dashboard/dist/assets/{McpQueryPage-CNsuiw_q.js.map → McpQueryPage-DX5u-1bx.js.map} +1 -1
  164. package/dashboard/dist/assets/McpRunDetailPage-BhcqqtYS.js +2 -0
  165. package/dashboard/dist/assets/McpRunDetailPage-BhcqqtYS.js.map +1 -0
  166. package/dashboard/dist/assets/{McpRunsPage-CK96s3Nt.js → McpRunsPage-L-1y8wnX.js} +2 -2
  167. package/dashboard/dist/assets/{McpRunsPage-CK96s3Nt.js.map → McpRunsPage-L-1y8wnX.js.map} +1 -1
  168. package/dashboard/dist/assets/{NamespacePill-B9Vc_Pz2.js → NamespacePill-in1SLd0W.js} +2 -2
  169. package/dashboard/dist/assets/{NamespacePill-B9Vc_Pz2.js.map → NamespacePill-in1SLd0W.js.map} +1 -1
  170. package/dashboard/dist/assets/OperationsPage-i8KcDpKo.js +3 -0
  171. package/dashboard/dist/assets/OperationsPage-i8KcDpKo.js.map +1 -0
  172. package/dashboard/dist/assets/OperatorDashboard-CIbDzOlh.js +2 -0
  173. package/dashboard/dist/assets/{OperatorDashboard-C-jE0IRA.js.map → OperatorDashboard-CIbDzOlh.js.map} +1 -1
  174. package/dashboard/dist/assets/{PageHeader-Ce4GcIYo.js → PageHeader-BJgWMZtw.js} +2 -2
  175. package/dashboard/dist/assets/{PageHeader-Ce4GcIYo.js.map → PageHeader-BJgWMZtw.js.map} +1 -1
  176. package/dashboard/dist/assets/{PageHeaderWithStats-Ck0KZvXD.js → PageHeaderWithStats-Ccio4vyG.js} +2 -2
  177. package/dashboard/dist/assets/{PageHeaderWithStats-Ck0KZvXD.js.map → PageHeaderWithStats-Ccio4vyG.js.map} +1 -1
  178. package/dashboard/dist/assets/{PersonaDetailPage-CJ6jqo7h.js → PersonaDetailPage-BOaf0TW1.js} +2 -2
  179. package/dashboard/dist/assets/{PersonaDetailPage-CJ6jqo7h.js.map → PersonaDetailPage-BOaf0TW1.js.map} +1 -1
  180. package/dashboard/dist/assets/{PersonasPage-D8hL3kL5.js → PersonasPage-DSdRb90f.js} +2 -2
  181. package/dashboard/dist/assets/{PersonasPage-D8hL3kL5.js.map → PersonasPage-DSdRb90f.js.map} +1 -1
  182. package/dashboard/dist/assets/{ProcessDetailPage-Vnx8Z5_y.js → ProcessDetailPage-DN9NqfeP.js} +2 -2
  183. package/dashboard/dist/assets/{ProcessDetailPage-Vnx8Z5_y.js.map → ProcessDetailPage-DN9NqfeP.js.map} +1 -1
  184. package/dashboard/dist/assets/{ProcessesListPage-DRYtvS3N.js → ProcessesListPage-CfQEWaD4.js} +2 -2
  185. package/dashboard/dist/assets/{ProcessesListPage-DRYtvS3N.js.map → ProcessesListPage-CfQEWaD4.js.map} +1 -1
  186. package/dashboard/dist/assets/RoleDetailPage-BC5HL7ls.js +8 -0
  187. package/dashboard/dist/assets/RoleDetailPage-BC5HL7ls.js.map +1 -0
  188. package/dashboard/dist/assets/{RolePill-CnuBPhPw.js → RolePill-BNAP-uK6.js} +2 -2
  189. package/dashboard/dist/assets/{RolePill-CnuBPhPw.js.map → RolePill-BNAP-uK6.js.map} +1 -1
  190. package/dashboard/dist/assets/RolesPage-DCnW0VmD.js +2 -0
  191. package/dashboard/dist/assets/RolesPage-DCnW0VmD.js.map +1 -0
  192. package/dashboard/dist/assets/RunAsSelector-twbuX7fB.js +2 -0
  193. package/dashboard/dist/assets/{RunAsSelector-CS3KQ-BF.js.map → RunAsSelector-twbuX7fB.js.map} +1 -1
  194. package/dashboard/dist/assets/ScanCodesPage-CPNg6K--.js +2 -0
  195. package/dashboard/dist/assets/ScanCodesPage-CPNg6K--.js.map +1 -0
  196. package/dashboard/dist/assets/ScanSchemeDetailPage-DyLmCamO.js +2 -0
  197. package/dashboard/dist/assets/ScanSchemeDetailPage-DyLmCamO.js.map +1 -0
  198. package/dashboard/dist/assets/ScanStationPage-DoZccU5B.js +2 -0
  199. package/dashboard/dist/assets/ScanStationPage-DoZccU5B.js.map +1 -0
  200. package/dashboard/dist/assets/{ScopeBadge-BUpYpS3x.js → ScopeBadge-BG7KkZ8Q.js} +2 -2
  201. package/dashboard/dist/assets/{ScopeBadge-BUpYpS3x.js.map → ScopeBadge-BG7KkZ8Q.js.map} +1 -1
  202. package/dashboard/dist/assets/SegmentedTabs-DXNzY05q.js +2 -0
  203. package/dashboard/dist/assets/SegmentedTabs-DXNzY05q.js.map +1 -0
  204. package/dashboard/dist/assets/StickyPagination-DIeYMPPd.js +2 -0
  205. package/dashboard/dist/assets/StickyPagination-DIeYMPPd.js.map +1 -0
  206. package/dashboard/dist/assets/{StreamMessageDetail-DyJyZwBl.js → StreamMessageDetail-gU4CUeQI.js} +2 -2
  207. package/dashboard/dist/assets/{StreamMessageDetail-DyJyZwBl.js.map → StreamMessageDetail-gU4CUeQI.js.map} +1 -1
  208. package/dashboard/dist/assets/{SwimlaneTimeline-BlzV74V5.js → SwimlaneTimeline-Br-nBA4l.js} +2 -2
  209. package/dashboard/dist/assets/{SwimlaneTimeline-BlzV74V5.js.map → SwimlaneTimeline-Br-nBA4l.js.map} +1 -1
  210. package/dashboard/dist/assets/{TagInput-BbZ25nNe.js → TagInput-CvM5n6ww.js} +2 -2
  211. package/dashboard/dist/assets/{TagInput-BbZ25nNe.js.map → TagInput-CvM5n6ww.js.map} +1 -1
  212. package/dashboard/dist/assets/{TaskDetailPage-B0p_Z4J_.js → TaskDetailPage-_9cr_R0u.js} +2 -2
  213. package/dashboard/dist/assets/{TaskDetailPage-B0p_Z4J_.js.map → TaskDetailPage-_9cr_R0u.js.map} +1 -1
  214. package/dashboard/dist/assets/{TaskQueuePill-D0QKBrN3.js → TaskQueuePill-D4JPHXOq.js} +2 -2
  215. package/dashboard/dist/assets/{TaskQueuePill-D0QKBrN3.js.map → TaskQueuePill-D4JPHXOq.js.map} +1 -1
  216. package/dashboard/dist/assets/{TasksListPage-CiGR2QiQ.js → TasksListPage-DVENC9Jp.js} +2 -2
  217. package/dashboard/dist/assets/{TasksListPage-CiGR2QiQ.js.map → TasksListPage-DVENC9Jp.js.map} +1 -1
  218. package/dashboard/dist/assets/{TimeAgo-D_DA9ucC.js → TimeAgo-C9yYnOui.js} +2 -2
  219. package/dashboard/dist/assets/{TimeAgo-D_DA9ucC.js.map → TimeAgo-C9yYnOui.js.map} +1 -1
  220. package/dashboard/dist/assets/{TimestampCell-C7rkC9nh.js → TimestampCell-DoB8cYgw.js} +2 -2
  221. package/dashboard/dist/assets/{TimestampCell-C7rkC9nh.js.map → TimestampCell-DoB8cYgw.js.map} +1 -1
  222. package/dashboard/dist/assets/{ToolPill-8xY9rkoc.js → ToolPill-BUjbC-Tj.js} +2 -2
  223. package/dashboard/dist/assets/{ToolPill-8xY9rkoc.js.map → ToolPill-BUjbC-Tj.js.map} +1 -1
  224. package/dashboard/dist/assets/{ToolTestPanel-E8efYGYs.js → ToolTestPanel-CBtsIP8K.js} +2 -2
  225. package/dashboard/dist/assets/{ToolTestPanel-E8efYGYs.js.map → ToolTestPanel-CBtsIP8K.js.map} +1 -1
  226. package/dashboard/dist/assets/{TopicDetailPage-B455XrRc.js → TopicDetailPage-mR4Jaz83.js} +4 -4
  227. package/dashboard/dist/assets/{TopicDetailPage-B455XrRc.js.map → TopicDetailPage-mR4Jaz83.js.map} +1 -1
  228. package/dashboard/dist/assets/TopicsPage-CP7HFxIC.js +2 -0
  229. package/dashboard/dist/assets/{TopicsPage-1VAc29Qw.js.map → TopicsPage-CP7HFxIC.js.map} +1 -1
  230. package/dashboard/dist/assets/{UserName-DikzjQHJ.js → UserName-BnLF6yhz.js} +2 -2
  231. package/dashboard/dist/assets/{UserName-DikzjQHJ.js.map → UserName-BnLF6yhz.js.map} +1 -1
  232. package/dashboard/dist/assets/WorkflowExecutionPage-xL956RZi.js +2 -0
  233. package/dashboard/dist/assets/WorkflowExecutionPage-xL956RZi.js.map +1 -0
  234. package/dashboard/dist/assets/{WorkflowPill-Da406nEj.js → WorkflowPill-tXU0-eXu.js} +2 -2
  235. package/dashboard/dist/assets/{WorkflowPill-Da406nEj.js.map → WorkflowPill-tXU0-eXu.js.map} +1 -1
  236. package/dashboard/dist/assets/WorkflowsDashboard-B-u7zFKM.js +2 -0
  237. package/dashboard/dist/assets/{WorkflowsDashboard-BMQd_0tW.js.map → WorkflowsDashboard-B-u7zFKM.js.map} +1 -1
  238. package/dashboard/dist/assets/{WorkflowsOverview-CdxjVifp.js → WorkflowsOverview-CqZVarK-.js} +2 -2
  239. package/dashboard/dist/assets/{WorkflowsOverview-CdxjVifp.js.map → WorkflowsOverview-CqZVarK-.js.map} +1 -1
  240. package/dashboard/dist/assets/{YamlWorkflowDetailPage-DNVffIXa.js → YamlWorkflowDetailPage-DiFLavW0.js} +10 -10
  241. package/dashboard/dist/assets/{YamlWorkflowDetailPage-DNVffIXa.js.map → YamlWorkflowDetailPage-DiFLavW0.js.map} +1 -1
  242. package/dashboard/dist/assets/{YamlWorkflowsPage-BGP8wuos.js → YamlWorkflowsPage-BuQM6uZA.js} +2 -2
  243. package/dashboard/dist/assets/{YamlWorkflowsPage-BGP8wuos.js.map → YamlWorkflowsPage-BuQM6uZA.js.map} +1 -1
  244. package/dashboard/dist/assets/{agents-BZJLIJ4h.js → agents-DU9GPovp.js} +2 -2
  245. package/dashboard/dist/assets/{agents-BZJLIJ4h.js.map → agents-DU9GPovp.js.map} +1 -1
  246. package/dashboard/dist/assets/{bots-ClLcDGJb.js → bots-Cy-Hmg7w.js} +2 -2
  247. package/dashboard/dist/assets/{bots-ClLcDGJb.js.map → bots-Cy-Hmg7w.js.map} +1 -1
  248. package/dashboard/dist/assets/capabilities-sSJJqrp-.js +2 -0
  249. package/dashboard/dist/assets/{capabilities-IaCcS7ge.js.map → capabilities-sSJJqrp-.js.map} +1 -1
  250. package/dashboard/dist/assets/{controlplane-Zi4m_MSx.js → controlplane-TVCjDHQ-.js} +2 -2
  251. package/dashboard/dist/assets/{controlplane-Zi4m_MSx.js.map → controlplane-TVCjDHQ-.js.map} +1 -1
  252. package/dashboard/dist/assets/escalation-columns-BpkjKYGd.js +2 -0
  253. package/dashboard/dist/assets/escalation-columns-BpkjKYGd.js.map +1 -0
  254. package/dashboard/dist/assets/index-5TblaCXQ.css +1 -0
  255. package/dashboard/dist/assets/index-7BP6FaCZ.js +2 -0
  256. package/dashboard/dist/assets/{index-Dldi3Q3M.js.map → index-7BP6FaCZ.js.map} +1 -1
  257. package/dashboard/dist/assets/{index-BzkE48xJ.js → index-B7IaBPBg.js} +4 -4
  258. package/dashboard/dist/assets/{index-BzkE48xJ.js.map → index-B7IaBPBg.js.map} +1 -1
  259. package/dashboard/dist/assets/index-BE0phFw0.js +2 -0
  260. package/dashboard/dist/assets/{index-CLmZaNTK.js.map → index-BE0phFw0.js.map} +1 -1
  261. package/dashboard/dist/assets/{index-BqGnhkh0.js → index-BYNN9N1T.js} +2 -2
  262. package/dashboard/dist/assets/{index-BqGnhkh0.js.map → index-BYNN9N1T.js.map} +1 -1
  263. package/dashboard/dist/assets/{index-kiKZresb.js → index-CLPVqbVY.js} +2 -2
  264. package/dashboard/dist/assets/{index-kiKZresb.js.map → index-CLPVqbVY.js.map} +1 -1
  265. package/dashboard/dist/assets/{index-C3o4OisO.js → index-Cfv86_L9.js} +2 -2
  266. package/dashboard/dist/assets/{index-C3o4OisO.js.map → index-Cfv86_L9.js.map} +1 -1
  267. package/dashboard/dist/assets/{index-yGNt29V9.js → index-CtwbQ_-m.js} +2 -2
  268. package/dashboard/dist/assets/{index-yGNt29V9.js.map → index-CtwbQ_-m.js.map} +1 -1
  269. package/dashboard/dist/assets/index-DOai950R.js +3 -0
  270. package/dashboard/dist/assets/index-DOai950R.js.map +1 -0
  271. package/dashboard/dist/assets/index-DTtHNC-D.js +5 -0
  272. package/dashboard/dist/assets/{index-CvNBdkB1.js.map → index-DTtHNC-D.js.map} +1 -1
  273. package/dashboard/dist/assets/{index-CJu2PBNx.js → index-DsWnVyVN.js} +2 -2
  274. package/dashboard/dist/assets/{index-CJu2PBNx.js.map → index-DsWnVyVN.js.map} +1 -1
  275. package/dashboard/dist/assets/{index-D0zFReGL.js → index-Dy-MMYti.js} +2 -2
  276. package/dashboard/dist/assets/{index-D0zFReGL.js.map → index-Dy-MMYti.js.map} +1 -1
  277. package/dashboard/dist/assets/index-errgQT5x.js +65 -0
  278. package/dashboard/dist/assets/index-errgQT5x.js.map +1 -0
  279. package/dashboard/dist/assets/{index-CmnNqpWg.js → index-fgBDhnI6.js} +2 -2
  280. package/dashboard/dist/assets/{index-CmnNqpWg.js.map → index-fgBDhnI6.js.map} +1 -1
  281. package/dashboard/dist/assets/{knowledge-DWLxGTib.js → knowledge-arh4NfmL.js} +2 -2
  282. package/dashboard/dist/assets/{knowledge-DWLxGTib.js.map → knowledge-arh4NfmL.js.map} +1 -1
  283. package/dashboard/dist/assets/{mcp-B6AARZ2I.js → mcp-QGf5jHCo.js} +2 -2
  284. package/dashboard/dist/assets/{mcp-B6AARZ2I.js.map → mcp-QGf5jHCo.js.map} +1 -1
  285. package/dashboard/dist/assets/{mcp-query-DrkvBU3a.js → mcp-query-BEJN1nMZ.js} +2 -2
  286. package/dashboard/dist/assets/{mcp-query-DrkvBU3a.js.map → mcp-query-BEJN1nMZ.js.map} +1 -1
  287. package/dashboard/dist/assets/{personas-Cmz2SAEU.js → personas-DYtw1COf.js} +2 -2
  288. package/dashboard/dist/assets/{personas-Cmz2SAEU.js.map → personas-DYtw1COf.js.map} +1 -1
  289. package/dashboard/dist/assets/{pipelines-CSgfVCMy.js → pipelines-Byi6PnbE.js} +2 -2
  290. package/dashboard/dist/assets/{pipelines-CSgfVCMy.js.map → pipelines-Byi6PnbE.js.map} +1 -1
  291. package/dashboard/dist/assets/{tasks-UOtUkDk-.js → tasks-D0SQdENz.js} +2 -2
  292. package/dashboard/dist/assets/{tasks-UOtUkDk-.js.map → tasks-D0SQdENz.js.map} +1 -1
  293. package/dashboard/dist/assets/{topics-Df5hGh6o.js → topics-DgDv5ZXP.js} +2 -2
  294. package/dashboard/dist/assets/{topics-Df5hGh6o.js.map → topics-DgDv5ZXP.js.map} +1 -1
  295. package/dashboard/dist/assets/useEventHooks-DZaYzE7s.js +2 -0
  296. package/dashboard/dist/assets/{useEventHooks-PDbuSJ12.js.map → useEventHooks-DZaYzE7s.js.map} +1 -1
  297. package/dashboard/dist/assets/{useNamespace-tZSOlge3.js → useNamespace-C1OqiNXN.js} +2 -2
  298. package/dashboard/dist/assets/{useNamespace-tZSOlge3.js.map → useNamespace-C1OqiNXN.js.map} +1 -1
  299. package/dashboard/dist/assets/{useYamlActivityEvents-CINLzE32.js → useYamlActivityEvents-CkmXDm-Z.js} +2 -2
  300. package/dashboard/dist/assets/{useYamlActivityEvents-CINLzE32.js.map → useYamlActivityEvents-CkmXDm-Z.js.map} +1 -1
  301. package/dashboard/dist/assets/{users-G8qwyZKS.js → users-D4DCFPH1.js} +2 -2
  302. package/dashboard/dist/assets/{users-G8qwyZKS.js.map → users-D4DCFPH1.js.map} +1 -1
  303. package/dashboard/dist/assets/{vendor-icons-BpZiWH2f.js → vendor-icons-BxuyFxH2.js} +156 -136
  304. package/dashboard/dist/assets/vendor-icons-BxuyFxH2.js.map +1 -0
  305. package/dashboard/dist/assets/{workflows-DbPqi1TW.js → workflows-qyc0ku_5.js} +2 -2
  306. package/dashboard/dist/assets/{workflows-DbPqi1TW.js.map → workflows-qyc0ku_5.js.map} +1 -1
  307. package/dashboard/dist/assets/{yaml-workflows-DozD8hpR.js → yaml-workflows-DWFww9Xn.js} +2 -2
  308. package/dashboard/dist/assets/{yaml-workflows-DozD8hpR.js.map → yaml-workflows-DWFww9Xn.js.map} +1 -1
  309. package/dashboard/dist/index.html +3 -3
  310. package/docs/api/http/escalations.md +133 -0
  311. package/docs/api/http/roles.md +6 -0
  312. package/docs/api/mcp/admin.md +53 -0
  313. package/docs/api/sdk/escalations.md +58 -0
  314. package/docs/cli.md +11 -0
  315. package/docs/dashboard.md +22 -20
  316. package/docs/data.md +12 -4
  317. package/docs/design-principles.md +9 -7
  318. package/docs/escalation-analytics.md +251 -0
  319. package/docs/hitl/roles.md +1 -1
  320. package/docs/hitl/x-lt-embed.md +8 -4
  321. package/docs/hitl/x-lt-footer.md +67 -0
  322. package/docs/hitl/x-lt-list-schema.md +10 -3
  323. package/docs/hitl-guide.md +11 -2
  324. package/docs/iam.md +12 -0
  325. package/docs/operations.md +17 -0
  326. package/docs/scan-codes.md +112 -0
  327. package/docs/sdk.md +1 -1
  328. package/package.json +2 -1
  329. package/dashboard/dist/assets/AgentsPage-CToVu1qj.js +0 -2
  330. package/dashboard/dist/assets/AvailableEscalationsPage-DldboL4W.js +0 -2
  331. package/dashboard/dist/assets/AvailableEscalationsPage-DldboL4W.js.map +0 -1
  332. package/dashboard/dist/assets/CountdownTimer-DPjIkerB.js +0 -2
  333. package/dashboard/dist/assets/CountdownTimer-DPjIkerB.js.map +0 -1
  334. package/dashboard/dist/assets/EventTable-CwPWl163.js +0 -2
  335. package/dashboard/dist/assets/EventTable-CwPWl163.js.map +0 -1
  336. package/dashboard/dist/assets/FilterBar-D7GghUsU.js +0 -2
  337. package/dashboard/dist/assets/FilterBar-D7GghUsU.js.map +0 -1
  338. package/dashboard/dist/assets/HomePage-Bcq10Bxx.js +0 -2
  339. package/dashboard/dist/assets/ListToolbar-IPXsTb3Q.js +0 -2
  340. package/dashboard/dist/assets/McpQueryPage-CNsuiw_q.js +0 -2
  341. package/dashboard/dist/assets/McpRunDetailPage-BJguEMS0.js +0 -2
  342. package/dashboard/dist/assets/McpRunDetailPage-BJguEMS0.js.map +0 -1
  343. package/dashboard/dist/assets/OperationsPage-DvWrLuH6.js +0 -2
  344. package/dashboard/dist/assets/OperationsPage-DvWrLuH6.js.map +0 -1
  345. package/dashboard/dist/assets/OperatorDashboard-C-jE0IRA.js +0 -2
  346. package/dashboard/dist/assets/RoleDetailPage-BKkUvTO-.js +0 -8
  347. package/dashboard/dist/assets/RoleDetailPage-BKkUvTO-.js.map +0 -1
  348. package/dashboard/dist/assets/RolesPage-BHzWK9n6.js +0 -2
  349. package/dashboard/dist/assets/RolesPage-BHzWK9n6.js.map +0 -1
  350. package/dashboard/dist/assets/RunAsSelector-CS3KQ-BF.js +0 -2
  351. package/dashboard/dist/assets/ScanCodesPage-BW4P4zWf.js +0 -2
  352. package/dashboard/dist/assets/ScanCodesPage-BW4P4zWf.js.map +0 -1
  353. package/dashboard/dist/assets/ScanSchemeDetailPage-BLykA4j-.js +0 -2
  354. package/dashboard/dist/assets/ScanSchemeDetailPage-BLykA4j-.js.map +0 -1
  355. package/dashboard/dist/assets/StickyPagination-hMrnLXde.js +0 -2
  356. package/dashboard/dist/assets/StickyPagination-hMrnLXde.js.map +0 -1
  357. package/dashboard/dist/assets/TopicsPage-1VAc29Qw.js +0 -2
  358. package/dashboard/dist/assets/WorkflowExecutionPage-C15GSAoe.js +0 -2
  359. package/dashboard/dist/assets/WorkflowExecutionPage-C15GSAoe.js.map +0 -1
  360. package/dashboard/dist/assets/WorkflowsDashboard-BMQd_0tW.js +0 -2
  361. package/dashboard/dist/assets/capabilities-IaCcS7ge.js +0 -2
  362. package/dashboard/dist/assets/escalation-columns-BY2mg9DY.js +0 -2
  363. package/dashboard/dist/assets/escalation-columns-BY2mg9DY.js.map +0 -1
  364. package/dashboard/dist/assets/index-CLmZaNTK.js +0 -2
  365. package/dashboard/dist/assets/index-CfAi1OsI.js +0 -65
  366. package/dashboard/dist/assets/index-CfAi1OsI.js.map +0 -1
  367. package/dashboard/dist/assets/index-CvNBdkB1.js +0 -5
  368. package/dashboard/dist/assets/index-Dldi3Q3M.js +0 -2
  369. package/dashboard/dist/assets/index-mKcQGi2B.js +0 -3
  370. package/dashboard/dist/assets/index-mKcQGi2B.js.map +0 -1
  371. package/dashboard/dist/assets/index-zQiUPfxA.css +0 -1
  372. package/dashboard/dist/assets/useEventHooks-PDbuSJ12.js +0 -2
  373. package/dashboard/dist/assets/vendor-icons-BpZiWH2f.js.map +0 -1
@@ -7,6 +7,7 @@ const metadata_1 = require("./metadata");
7
7
  const single_1 = require("./single");
8
8
  const resolve_1 = require("./resolve");
9
9
  const facets_1 = require("./facets");
10
+ const analytics_1 = require("./analytics");
10
11
  const router = (0, express_1.Router)();
11
12
  // Registration order matters: literal paths before parameterized /:id routes.
12
13
  // GET /, /available, /types, /stats
@@ -18,6 +19,8 @@ const router = (0, express_1.Router)();
18
19
  (0, metadata_1.registerMetadataRoutes)(router);
19
20
  // POST /search-by-facets, /claim-groups, /claim-by-facets
20
21
  (0, facets_1.registerFacetRoutes)(router);
22
+ // POST /aggregate-by-facets, /timeline-by-facet
23
+ (0, analytics_1.registerAnalyticsRoutes)(router);
21
24
  // PATCH /:id/escalate, GET /by-workflow/:workflowId,
22
25
  // GET /:id, POST /:id/claim, POST /:id/release
23
26
  (0, single_1.registerSingleRoutes)(router);
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.registerResolveRoutes = registerResolveRoutes;
37
37
  const api = __importStar(require("../../api/escalations"));
38
+ const acting_1 = require("./acting");
38
39
  function registerResolveRoutes(router) {
39
40
  /**
40
41
  * POST /api/escalations/resolve-by-signal-key
@@ -92,7 +93,13 @@ function registerResolveRoutes(router) {
92
93
  * Body: { resolverPayload: Record<string, any>, metadata?: Record<string, any> }
93
94
  */
94
95
  router.post('/:id/resolve', async (req, res) => {
95
- const result = await api.resolveEscalation({ id: req.params.id, resolverPayload: req.body?.resolverPayload, metadata: req.body?.metadata }, req.auth);
96
+ // The actor is the token user or the badged person when an
97
+ // X-LT-Acting-Token grant rides the request (station continuity: the
98
+ // person who claimed by badge submits by badge).
99
+ const auth = await (0, acting_1.effectiveWorkAuth)(req, res);
100
+ if (!auth)
101
+ return;
102
+ const result = await api.resolveEscalation({ id: req.params.id, resolverPayload: req.body?.resolverPayload, metadata: req.body?.metadata }, auth);
96
103
  res.status(result.status).json(result.data ?? { error: result.error });
97
104
  });
98
105
  }
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.registerSingleRoutes = registerSingleRoutes;
37
37
  const api = __importStar(require("../../api/escalations"));
38
+ const acting_1 = require("./acting");
38
39
  function registerSingleRoutes(router) {
39
40
  /**
40
41
  * PATCH /api/escalations/:id/escalate
@@ -67,20 +68,28 @@ function registerSingleRoutes(router) {
67
68
  });
68
69
  /**
69
70
  * POST /api/escalations/:id/claim
70
- * Claim an escalation. userId comes from auth token.
71
+ * Claim an escalation. The actor is the auth token's user — or the badged
72
+ * person when an X-LT-Acting-Token grant rides the request.
71
73
  * Body: { durationMinutes?: number }
72
74
  */
73
75
  router.post('/:id/claim', async (req, res) => {
74
- const result = await api.claimEscalation({ id: req.params.id, durationMinutes: req.body?.durationMinutes, provisionIfAbsent: req.body?.provisionIfAbsent }, req.auth);
76
+ const auth = await (0, acting_1.effectiveWorkAuth)(req, res);
77
+ if (!auth)
78
+ return;
79
+ const result = await api.claimEscalation({ id: req.params.id, durationMinutes: req.body?.durationMinutes, provisionIfAbsent: req.body?.provisionIfAbsent }, auth);
75
80
  res.status(result.status).json(result.data ?? { error: result.error });
76
81
  });
77
82
  /**
78
83
  * POST /api/escalations/:id/release
79
84
  * Release a claimed escalation back to the available pool.
80
- * Only the assigned user may release their own claim.
85
+ * Only the assigned actor (token user, or the badged person when an
86
+ * X-LT-Acting-Token grant rides the request) may release their own claim.
81
87
  */
82
88
  router.post('/:id/release', async (req, res) => {
83
- const result = await api.releaseEscalation({ id: req.params.id }, req.auth);
89
+ const auth = await (0, acting_1.effectiveWorkAuth)(req, res);
90
+ if (!auth)
91
+ return;
92
+ const result = await api.releaseEscalation({ id: req.params.id }, auth);
84
93
  res.status(result.status).json(result.data ?? { error: result.error });
85
94
  });
86
95
  /**
@@ -95,7 +95,7 @@ router.delete('/escalation-chains', auth_1.requireRoleManager, async (req, res)
95
95
  /**
96
96
  * PATCH /api/roles/:role
97
97
  * Update role metadata. Requires admin.
98
- * Body: { title?, description?, form_schema?, metadata_schema?, properties?, ops_visible?, parent_role?, sla_minutes?, target_per_hour?, worker_count?, priority_threshold_minutes?, priority_facet? }
98
+ * Body: { title?, description?, form_schema?, metadata_schema?, properties?, ops_visible?, parent_role?, sla_minutes?, target_per_hour?, worker_count?, priority_threshold_minutes?, priority_facet?, entity_facet?, entity_state_source? }
99
99
  */
100
100
  router.patch('/:role', auth_1.requireRoleManager, async (req, res) => {
101
101
  // URL is the resource identity — a `role` key in the body must not redirect
@@ -40,11 +40,33 @@ const router = (0, express_1.Router)();
40
40
  // ── Execute ───────────────────────────────────────────────────────────────
41
41
  /**
42
42
  * POST /api/scan-codes/execute
43
- * Execute a raw scan code (from any input source) as the calling user.
43
+ * Execute a raw scan code (from any input source). Verbs run as the calling
44
+ * user, or as the badged person when an acting-identity grant rides along.
44
45
  * Every terminal state is a structured 200 outcome.
45
46
  */
46
47
  router.post('/execute', async (req, res) => {
47
- const result = await api.executeScanCode({ code: req.body.code }, req.auth);
48
+ const result = await api.executeScanCode({
49
+ code: req.body.code,
50
+ actingToken: req.body.actingToken,
51
+ previousActingToken: req.body.previousActingToken,
52
+ }, req.auth);
53
+ res.status(result.status).json(result.data ?? { error: result.error });
54
+ });
55
+ /**
56
+ * POST /api/scan-codes/execute-choice
57
+ * Execute one choice presented by a PRESENT step. The body is a pointer
58
+ * (scheme/category/step/choice + escalationId); the server re-validates
59
+ * config, row state, identity, and RBAC before the verb runs.
60
+ */
61
+ router.post('/execute-choice', async (req, res) => {
62
+ const result = await api.executeScanChoice({
63
+ schemeVersion: req.body.schemeVersion,
64
+ category: req.body.category,
65
+ stepIndex: req.body.stepIndex,
66
+ choiceIndex: req.body.choiceIndex,
67
+ escalationId: req.body.escalationId,
68
+ actingToken: req.body.actingToken,
69
+ }, req.auth);
48
70
  res.status(result.status).json(result.data ?? { error: result.error });
49
71
  });
50
72
  // ── Scheme CRUD (admin, engineer, superadmin) ─────────────────────────────
@@ -77,6 +99,9 @@ router.put('/schemes/:version', auth_1.requireRoleManager, async (req, res) => {
77
99
  encoding: req.body.encoding,
78
100
  delimiter: req.body.delimiter,
79
101
  target_length: req.body.target_length,
102
+ kind: req.body.kind,
103
+ grant_ttl_seconds: req.body.grant_ttl_seconds,
104
+ grant_max_uses: req.body.grant_max_uses,
80
105
  enabled: req.body.enabled,
81
106
  });
82
107
  res.status(result.status).json(result.data ?? { error: result.error });
@@ -120,6 +145,7 @@ router.put('/schemes/:version/actions/:category', auth_1.requireRoleManager, asy
120
145
  name: req.body.name,
121
146
  steps: req.body.steps,
122
147
  fallback: req.body.fallback,
148
+ notPrimed: req.body.notPrimed,
123
149
  enabled: req.body.enabled,
124
150
  });
125
151
  res.status(result.status).json(result.data ?? { error: result.error });
@@ -162,6 +162,20 @@ async function ensureSideQuestRoles() {
162
162
  await api('PATCH', '/api/roles/ship', { upstream_roles: [...upstreams, 'inserting'] });
163
163
  }
164
164
  console.log(`[${ts()}] Side-quest roles ready (ordering → inserting ⇒ ship)`);
165
+ // Declare each station's entity: the order is what moves through every one
166
+ // of these roles, so entity_facet = 'order_id' unlocks distinct-order
167
+ // counts, per-order dwell, and order timelines on the Pace Board. Set only
168
+ // where unset — an operator-configured entity is never overwritten.
169
+ let declared = 0;
170
+ for (const role of ALL_ROLES) {
171
+ const detail = (details?.roles ?? []).find((r) => r.role === role);
172
+ if (!detail || detail.entity_facet)
173
+ continue;
174
+ await api('PATCH', `/api/roles/${role}`, { entity_facet: 'order_id' }).catch(() => { });
175
+ declared++;
176
+ }
177
+ if (declared > 0)
178
+ console.log(`[${ts()}] Entity declared on ${declared} role(s): order_id`);
165
179
  }
166
180
  // ── Side-quest escalations (standalone rows — no workflow behind them) ────────
167
181
  async function createSideEscalation(role, workflowId, orderId, runId, description, authorizedAt) {
@@ -0,0 +1,25 @@
1
+ /**
2
+ * printer-cycle — drive the seeded printer fleet through its states live.
3
+ *
4
+ * The flagship entity-analytics demo (examples/seed-fleet-sim.ts) seeds six
5
+ * printers with backdated history and one open interval each. This driver
6
+ * keeps the fleet moving: each printer dwells in its current state, then the
7
+ * open escalation resolves and the next state's escalation is created after a
8
+ * short untracked settle gap — exactly the authoring contract a real workflow
9
+ * follows with condition(). Watch /operations: the state band, slice-by, and
10
+ * per-printer timelines move within seconds of every transition.
11
+ *
12
+ * State machine per printer: idle → printing → harvest → (service |) idle …
13
+ *
14
+ * Usage:
15
+ * npx ts-node scripts/printer-cycle.ts
16
+ * DWELL_SCALE=0.2 npx ts-node scripts/printer-cycle.ts (5× faster)
17
+ *
18
+ * Env vars:
19
+ * DWELL_SCALE — multiply every dwell/gap (default 1; smaller = faster demo)
20
+ * CYCLES — stop after each printer completes this many transitions
21
+ * (default: run until interrupted)
22
+ * POLL_MS — poll interval ms (default 1000)
23
+ * BASE_URL — server URL (default http://localhost:3000)
24
+ */
25
+ export {};
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ /**
3
+ * printer-cycle — drive the seeded printer fleet through its states live.
4
+ *
5
+ * The flagship entity-analytics demo (examples/seed-fleet-sim.ts) seeds six
6
+ * printers with backdated history and one open interval each. This driver
7
+ * keeps the fleet moving: each printer dwells in its current state, then the
8
+ * open escalation resolves and the next state's escalation is created after a
9
+ * short untracked settle gap — exactly the authoring contract a real workflow
10
+ * follows with condition(). Watch /operations: the state band, slice-by, and
11
+ * per-printer timelines move within seconds of every transition.
12
+ *
13
+ * State machine per printer: idle → printing → harvest → (service |) idle …
14
+ *
15
+ * Usage:
16
+ * npx ts-node scripts/printer-cycle.ts
17
+ * DWELL_SCALE=0.2 npx ts-node scripts/printer-cycle.ts (5× faster)
18
+ *
19
+ * Env vars:
20
+ * DWELL_SCALE — multiply every dwell/gap (default 1; smaller = faster demo)
21
+ * CYCLES — stop after each printer completes this many transitions
22
+ * (default: run until interrupted)
23
+ * POLL_MS — poll interval ms (default 1000)
24
+ * BASE_URL — server URL (default http://localhost:3000)
25
+ */
26
+ Object.defineProperty(exports, "__esModule", { value: true });
27
+ try {
28
+ require('dotenv/config');
29
+ }
30
+ catch { }
31
+ const BASE_URL = process.env.BASE_URL || 'http://localhost:3000';
32
+ const DWELL_SCALE = parseFloat(process.env.DWELL_SCALE || '1');
33
+ const CYCLES = parseInt(process.env.CYCLES || '0', 10);
34
+ const POLL_MS = parseInt(process.env.POLL_MS || '1000', 10);
35
+ const FLEET_ROLE = 'printer-fleet';
36
+ const HARVEST_ROLE = 'printer-harvest';
37
+ const SERVICE_ROLE = 'printer-service';
38
+ const ROLES = [FLEET_ROLE, HARVEST_ROLE, SERVICE_ROLE];
39
+ const ENTITY_FACET = 'serialNumber';
40
+ /** Seconds a printer dwells in each state (before DWELL_SCALE and jitter). */
41
+ const DWELL_S = { idle: 45, printing: 120, harvest: 20, service: 60 };
42
+ const GAP_S = 5; // untracked settle time between queues
43
+ const STATES = {
44
+ idle: { role: FLEET_ROLE, subtype: 'idle' },
45
+ printing: { role: FLEET_ROLE, subtype: 'printing' },
46
+ harvest: { role: HARVEST_ROLE, subtype: 'harvest' },
47
+ service: { role: SERVICE_ROLE, subtype: 'service' },
48
+ };
49
+ let token = '';
50
+ let transitions = 0;
51
+ function ts() { return new Date().toISOString().slice(11, 19); }
52
+ function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); }
53
+ function ageSeconds(iso) { return (Date.now() - new Date(iso).getTime()) / 1000; }
54
+ /** Deterministic per-row jitter in [0, 1) — FNV-1a of the escalation id. */
55
+ function jitter(id, salt) {
56
+ let h = 2166136261;
57
+ for (const c of salt + id) {
58
+ h ^= c.charCodeAt(0);
59
+ h = Math.imul(h, 16777619);
60
+ }
61
+ return ((h >>> 0) % 1000) / 1000;
62
+ }
63
+ async function api(method, path, body) {
64
+ const res = await fetch(`${BASE_URL}${path}`, {
65
+ method,
66
+ headers: {
67
+ 'Content-Type': 'application/json',
68
+ ...(token ? { Authorization: `Bearer ${token}` } : {}),
69
+ },
70
+ body: body !== undefined ? JSON.stringify(body) : undefined,
71
+ });
72
+ const data = await res.json().catch(() => ({}));
73
+ if (!res.ok)
74
+ throw new Error(`${method} ${path} → ${res.status}: ${JSON.stringify(data)}`);
75
+ return data;
76
+ }
77
+ async function login() {
78
+ const auth = await api('POST', '/api/auth/login', { username: 'superadmin', password: 'l0ngt@1l' });
79
+ token = auth.token;
80
+ if (!token) {
81
+ console.error('[auth] Login failed');
82
+ process.exit(1);
83
+ }
84
+ console.log(`[${ts()}] Logged in`);
85
+ }
86
+ /** Self-heal the entity dials: declare where unset, never overwrite (S2). */
87
+ async function ensureEntityDials() {
88
+ const details = await api('GET', '/api/roles/details').catch(() => ({ roles: [] }));
89
+ const byRole = new Map((details?.roles ?? []).map((r) => [r.role, r]));
90
+ for (const role of ROLES) {
91
+ const row = byRole.get(role);
92
+ if (!row) {
93
+ console.error(`[${ts()}] role ${role} is missing — run the seeded install first (docker compose up with examples)`);
94
+ process.exit(1);
95
+ }
96
+ if (row.entity_facet == null) {
97
+ await api('PATCH', `/api/roles/${role}`, {
98
+ entity_facet: ENTITY_FACET,
99
+ entity_state_source: role === FLEET_ROLE ? 'subtype' : 'role',
100
+ }).catch(() => { });
101
+ console.log(`[${ts()}] declared entity dials on ${role}`);
102
+ }
103
+ }
104
+ }
105
+ /** The state a printer enters after `current` — service follows ~⅓ of harvests. */
106
+ function nextState(current, rowId) {
107
+ if (current === 'idle')
108
+ return 'printing';
109
+ if (current === 'printing')
110
+ return 'harvest';
111
+ if (current === 'harvest')
112
+ return jitter(rowId, 'svc') < 0.33 ? 'service' : 'idle';
113
+ return 'idle'; // service → back to the floor
114
+ }
115
+ async function transition(row) {
116
+ const serial = row.metadata?.[ENTITY_FACET];
117
+ const current = row.role === FLEET_ROLE ? row.subtype : row.role === HARVEST_ROLE ? 'harvest' : 'service';
118
+ const next = nextState(current, row.id);
119
+ await api('POST', `/api/escalations/${row.id}/resolve`, {
120
+ resolverPayload: { outcome: current, driver: 'printer-cycle' },
121
+ });
122
+ await sleep(GAP_S * DWELL_SCALE * 1000 * (0.5 + jitter(row.id, 'gap')));
123
+ const def = STATES[next];
124
+ await api('POST', '/api/escalations', {
125
+ type: 'fleet',
126
+ subtype: def.subtype,
127
+ role: def.role,
128
+ description: `${serial} — ${next}`,
129
+ priority: 3,
130
+ envelope: JSON.stringify({ source: 'printer-cycle' }),
131
+ metadata: { ...row.metadata },
132
+ });
133
+ transitions++;
134
+ console.log(`[${ts()}] ${serial}: ${current} → ${next}`);
135
+ }
136
+ /** Every live printer interval across the three queues. */
137
+ async function liveRows() {
138
+ const params = new URLSearchParams({
139
+ status: 'pending',
140
+ roles: JSON.stringify(ROLES),
141
+ exists: JSON.stringify([ENTITY_FACET]),
142
+ limit: '200',
143
+ });
144
+ const data = await api('GET', `/api/escalations?${params}`);
145
+ return data.escalations ?? [];
146
+ }
147
+ async function main() {
148
+ console.log(`[${ts()}] printer-cycle starting (scale ${DWELL_SCALE}, ${CYCLES || '∞'} transitions/printer)`);
149
+ await login();
150
+ await ensureEntityDials();
151
+ const perPrinterCap = CYCLES > 0 ? CYCLES * 6 : Infinity; // 6 seeded printers
152
+ while (transitions < perPrinterCap) {
153
+ const rows = await liveRows();
154
+ if (rows.length === 0) {
155
+ console.log(`[${ts()}] no live printer intervals — seed the fleet first`);
156
+ break;
157
+ }
158
+ for (const row of rows) {
159
+ const state = row.role === FLEET_ROLE ? row.subtype : row.role === HARVEST_ROLE ? 'harvest' : 'service';
160
+ const dwell = (DWELL_S[state] ?? 30) * DWELL_SCALE * (0.6 + 0.8 * jitter(row.id, 'dwell'));
161
+ if (ageSeconds(row.created_at) >= dwell) {
162
+ await transition(row).catch((err) => console.error(`[${ts()}] transition failed: ${String(err.message).slice(0, 100)}`));
163
+ }
164
+ }
165
+ await sleep(POLL_MS);
166
+ }
167
+ console.log(`[${ts()}] done — ${transitions} transitions`);
168
+ }
169
+ main().catch((err) => { console.error(err); process.exit(1); });
@@ -111,12 +111,17 @@ async function login() {
111
111
  *
112
112
  * Topology: print-jobs ─▶ printer-fleet (production line), with print-servicer
113
113
  * a side-quest root merging into the fleet.
114
+ *
115
+ * The three printer roles share entity_facet 'serialNumber' (every twin row
116
+ * carries it) — together with the flagship printer roles they form the
117
+ * printer's SYSTEM, so onboarding and servicing intervals join the machine's
118
+ * timeline and state band.
114
119
  */
115
120
  const TWIN_ROLE_CONFIG = [
116
121
  { role: 'print-jobs', title: 'Print Jobs', parent_role: null, sla_minutes: 5, target_per_hour: 30, priority_threshold_minutes: 5, description: 'Order demand — one print-job escalation per unit, claimed as a set.' },
117
- { role: 'printer-fleet', title: 'Printer Fleet', parent_role: 'print-jobs', sla_minutes: 5, target_per_hour: 30, priority_threshold_minutes: 5, description: 'Twin availability adverts and in-flight print rows — the machines at work.', upstream_roles: ['print-onboarder', 'print-servicer'] },
118
- { role: 'print-onboarder', title: 'Print Onboarder', parent_role: null, sla_minutes: 15, target_per_hour: 5, priority_threshold_minutes: 15, description: 'Register + bind a newly unboxed machine.' },
119
- { role: 'print-servicer', title: 'Print Servicer', parent_role: null, sla_minutes: 10, target_per_hour: 10, priority_threshold_minutes: 10, description: 'Reload filament, inspect failures, restore offline machines.' },
122
+ { role: 'printer-fleet', title: 'Printer Fleet', parent_role: 'print-jobs', sla_minutes: 5, target_per_hour: 30, priority_threshold_minutes: 5, description: 'Twin availability adverts and in-flight print rows — the machines at work.', upstream_roles: ['print-onboarder', 'print-servicer'], entity_facet: 'serialNumber', entity_state_source: 'subtype' },
123
+ { role: 'print-onboarder', title: 'Print Onboarder', parent_role: null, sla_minutes: 15, target_per_hour: 5, priority_threshold_minutes: 15, description: 'Register + bind a newly unboxed machine.', entity_facet: 'serialNumber', entity_state_source: 'role' },
124
+ { role: 'print-servicer', title: 'Print Servicer', parent_role: null, sla_minutes: 10, target_per_hour: 10, priority_threshold_minutes: 10, description: 'Reload filament, inspect failures, restore offline machines.', entity_facet: 'serialNumber', entity_state_source: 'role' },
120
125
  ];
121
126
  async function ensureTwinRoles() {
122
127
  const details = await api('GET', '/api/roles/details').catch(() => ({ roles: [] }));
@@ -129,8 +134,17 @@ async function ensureTwinRoles() {
129
134
  let applied = 0;
130
135
  for (const cfg of TWIN_ROLE_CONFIG) {
131
136
  const row = configured.get(cfg.role);
132
- if (row?.title)
133
- continue; // already configured — respect admin tuning
137
+ if (row?.title) {
138
+ // Already configured — respect admin tuning, but self-heal the entity
139
+ // dials where the role predates them (set only when unset).
140
+ if ('entity_facet' in cfg && row.entity_facet == null) {
141
+ await api('PATCH', `/api/roles/${cfg.role}`, {
142
+ entity_facet: cfg.entity_facet,
143
+ entity_state_source: cfg.entity_state_source,
144
+ }).catch(() => { });
145
+ }
146
+ continue;
147
+ }
134
148
  const { role, ...body } = cfg;
135
149
  await api('PATCH', `/api/roles/${role}`, { ...body, ops_visible: true }).then(() => { applied++; }).catch((err) => {
136
150
  console.warn(`[${ts()}] ⚠ role ${role}: ${String(err.message).slice(0, 80)}`);
@@ -227,6 +227,8 @@ export declare function createClient(options?: LTClientOptions): {
227
227
  durationMinutes?: number;
228
228
  allOrNone?: boolean;
229
229
  }, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
230
+ aggregateByFacets: (input: import("..").AggregateByFacetsInput, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
231
+ timelineByFacet: (input: import("..").TimelineByFacetInput, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
230
232
  };
231
233
  workflows: {
232
234
  invoke: (input: {
@@ -145,6 +145,9 @@ function createClient(options = {}) {
145
145
  searchByFacets: bindAuth(escalationsApi.searchByFacets, auth),
146
146
  claimGroups: bindAuth(escalationsApi.claimGroups, auth),
147
147
  claimByFacets: bindAuth(escalationsApi.claimByFacets, auth),
148
+ // Analytics surface (grouped membership/dwell + per-entity timeline), read_all-gated.
149
+ aggregateByFacets: bindAuth(escalationsApi.aggregateByFacets, auth),
150
+ timelineByFacet: bindAuth(escalationsApi.timelineByFacet, auth),
148
151
  },
149
152
  // ── Workflows ──────────────────────────────────────────────────────────
150
153
  workflows: {
@@ -0,0 +1,36 @@
1
+ import type { AggregateByFacetsInput, GroupableColumn, TimelineByFacetInput } from '../../types';
2
+ export { AnalyticsInputError } from './aggregate-validate';
3
+ export interface BuiltAggregateQuery {
4
+ sql: string;
5
+ params: unknown[];
6
+ /** Groups per page; the SQL fetches pageLimit + 1 rows to detect overflow. */
7
+ pageLimit: number;
8
+ columns: GroupableColumn[];
9
+ facets: string[];
10
+ /** true when grouped by the derived state label (groupBy.state). */
11
+ stateGrouped: boolean;
12
+ measureKind: 'membership' | 'dwell';
13
+ /** true = the anchor touches now (short cache); false = fully past (immutable). */
14
+ nowAnchored: boolean;
15
+ }
16
+ /** Per-role state naming, from lt_roles.entity_state_source. */
17
+ export type StateSources = Record<string, 'role' | 'subtype'>;
18
+ export interface BuiltTimelineQuery {
19
+ sql: string;
20
+ params: unknown[];
21
+ pageLimit: number;
22
+ columns: GroupableColumn[];
23
+ facets: string[];
24
+ nowAnchored: boolean;
25
+ }
26
+ /**
27
+ * Build the grouped aggregate (membership or dwell) as one parameterized
28
+ * query. `query.entity` must be RESOLVED by the caller before building
29
+ * (aggregates.ts turns it into roles + opts.stateSources); the builder
30
+ * rejects an unresolved entity so it can never be silently ignored.
31
+ */
32
+ export declare function buildAggregateQuery(input: AggregateByFacetsInput, opts?: {
33
+ stateSources?: StateSources;
34
+ }): BuiltAggregateQuery;
35
+ /** Build the single-entity interval sequence, created_at-ordered, gaps preserved. */
36
+ export declare function buildTimelineQuery(input: TimelineByFacetInput): BuiltTimelineQuery;