@hotmeshio/long-tail 0.30.4 → 0.31.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 (413) hide show
  1. package/build/api/escalations/index.d.ts +1 -0
  2. package/build/api/escalations/index.js +5 -2
  3. package/build/api/escalations/roster-action.d.ts +11 -0
  4. package/build/api/escalations/roster-action.js +47 -30
  5. package/build/api/escalations/roster-scan.d.ts +26 -0
  6. package/build/api/escalations/roster-scan.js +114 -0
  7. package/build/api/labels/errors.d.ts +3 -0
  8. package/build/api/labels/errors.js +15 -0
  9. package/build/api/labels/index.d.ts +2 -0
  10. package/build/api/labels/index.js +17 -0
  11. package/build/api/labels/issue.d.ts +54 -0
  12. package/build/api/labels/issue.js +144 -0
  13. package/build/api/labels/templates.d.ts +29 -0
  14. package/build/api/labels/templates.js +98 -0
  15. package/build/api/scan-codes/context.d.ts +9 -1
  16. package/build/api/scan-codes/context.js +16 -1
  17. package/build/api/scan-codes/execute.js +6 -1
  18. package/build/api/scan-codes/fill-labels.d.ts +8 -0
  19. package/build/api/scan-codes/fill-labels.js +23 -2
  20. package/build/api/scan-codes/hold.js +2 -0
  21. package/build/api/scan-codes/located.d.ts +10 -0
  22. package/build/api/scan-codes/located.js +74 -0
  23. package/build/api/scan-codes/open.d.ts +9 -0
  24. package/build/api/scan-codes/open.js +99 -0
  25. package/build/api/scan-codes/present.js +1 -0
  26. package/build/api/scan-codes/verb-fill.js +1 -1
  27. package/build/api/users.d.ts +8 -4
  28. package/build/api/users.js +51 -13
  29. package/build/index.d.ts +1 -0
  30. package/build/index.js +4 -2
  31. package/build/lib/db/schemas/044_label_sheets.sql +65 -0
  32. package/build/lib/db/schemas/045_label_job_delivery.sql +14 -0
  33. package/build/lib/labels/transports.d.ts +23 -0
  34. package/build/lib/labels/transports.js +39 -0
  35. package/build/modules/auth.d.ts +2 -0
  36. package/build/modules/auth.js +3 -1
  37. package/build/modules/capabilities.d.ts +5 -1
  38. package/build/modules/capabilities.js +38 -8
  39. package/build/modules/config.d.ts +10 -0
  40. package/build/modules/config.js +10 -0
  41. package/build/routes/escalations/resolve.js +18 -0
  42. package/build/routes/index.js +2 -0
  43. package/build/routes/labels.d.ts +2 -0
  44. package/build/routes/labels.js +135 -0
  45. package/build/routes/users.js +1 -1
  46. package/build/services/labels/content.d.ts +13 -0
  47. package/build/services/labels/content.js +81 -0
  48. package/build/services/labels/errors.d.ts +5 -0
  49. package/build/services/labels/errors.js +12 -0
  50. package/build/services/labels/index.d.ts +11 -0
  51. package/build/services/labels/index.js +52 -0
  52. package/build/services/labels/issue.d.ts +38 -0
  53. package/build/services/labels/issue.js +181 -0
  54. package/build/services/labels/jobs.d.ts +37 -0
  55. package/build/services/labels/jobs.js +75 -0
  56. package/build/services/labels/media.d.ts +11 -0
  57. package/build/services/labels/media.js +44 -0
  58. package/build/services/labels/reissue.d.ts +13 -0
  59. package/build/services/labels/reissue.js +65 -0
  60. package/build/services/labels/render-pdf.d.ts +11 -0
  61. package/build/services/labels/render-pdf.js +138 -0
  62. package/build/services/labels/targets.d.ts +18 -0
  63. package/build/services/labels/targets.js +216 -0
  64. package/build/services/labels/templates/index.d.ts +3 -0
  65. package/build/services/labels/templates/index.js +18 -0
  66. package/build/services/labels/templates/read.d.ts +4 -0
  67. package/build/services/labels/templates/read.js +36 -0
  68. package/build/services/labels/templates/sql.d.ts +8 -0
  69. package/build/services/labels/templates/sql.js +50 -0
  70. package/build/services/labels/templates/validate.d.ts +19 -0
  71. package/build/services/labels/templates/validate.js +93 -0
  72. package/build/services/labels/templates/write.d.ts +16 -0
  73. package/build/services/labels/templates/write.js +75 -0
  74. package/build/services/labels/token.d.ts +9 -0
  75. package/build/services/labels/token.js +28 -0
  76. package/build/services/labels/verify.d.ts +4 -0
  77. package/build/services/labels/verify.js +38 -0
  78. package/build/services/role/index.d.ts +2 -0
  79. package/build/services/role/index.js +7 -0
  80. package/build/services/role/scan-done.js +4 -1
  81. package/build/services/role/sql.d.ts +1 -0
  82. package/build/services/role/sql.js +3 -1
  83. package/build/services/role/types.d.ts +2 -0
  84. package/build/services/scan-code/index.d.ts +1 -1
  85. package/build/services/scan-code/index.js +2 -1
  86. package/build/services/scan-code/parse.d.ts +5 -1
  87. package/build/services/scan-code/parse.js +8 -2
  88. package/build/services/scan-code/validate-station.d.ts +13 -0
  89. package/build/services/scan-code/validate-station.js +81 -0
  90. package/build/services/scan-code/validate-subject.js +33 -6
  91. package/build/services/scan-code/validate.d.ts +3 -0
  92. package/build/services/scan-code/validate.js +22 -18
  93. package/build/services/user/crud.d.ts +13 -1
  94. package/build/services/user/crud.js +42 -11
  95. package/build/services/user/index.d.ts +3 -2
  96. package/build/services/user/index.js +7 -1
  97. package/build/services/user/redact.d.ts +17 -0
  98. package/build/services/user/redact.js +32 -0
  99. package/build/services/user/sql.d.ts +8 -15
  100. package/build/services/user/sql.js +27 -3
  101. package/build/services/user/types.d.ts +21 -1
  102. package/build/shared/labels/compose.d.ts +12 -0
  103. package/build/shared/labels/compose.js +43 -0
  104. package/build/shared/labels/index.d.ts +9 -0
  105. package/build/shared/labels/index.js +54 -0
  106. package/build/shared/labels/label-content.d.ts +17 -0
  107. package/build/shared/labels/label-content.js +137 -0
  108. package/build/shared/labels/layout.d.ts +23 -0
  109. package/build/shared/labels/layout.js +81 -0
  110. package/build/shared/labels/media.d.ts +22 -0
  111. package/build/shared/labels/media.js +116 -0
  112. package/build/shared/labels/render-svg.d.ts +10 -0
  113. package/build/shared/labels/render-svg.js +58 -0
  114. package/build/shared/labels/render-zpl.d.ts +9 -0
  115. package/build/shared/labels/render-zpl.js +63 -0
  116. package/build/shared/labels/symbol.d.ts +18 -0
  117. package/build/shared/labels/symbol.js +74 -0
  118. package/build/shared/labels/tokens.d.ts +18 -0
  119. package/build/shared/labels/tokens.js +43 -0
  120. package/build/shared/labels/types.d.ts +105 -0
  121. package/build/shared/labels/types.js +11 -0
  122. package/build/start/adapters.js +16 -0
  123. package/build/start/workers.js +18 -2
  124. package/build/system/mcp-servers/admin/index.js +2 -0
  125. package/build/system/mcp-servers/admin/labels-schemas.d.ts +192 -0
  126. package/build/system/mcp-servers/admin/labels-schemas.js +46 -0
  127. package/build/system/mcp-servers/admin/labels.d.ts +9 -0
  128. package/build/system/mcp-servers/admin/labels.js +101 -0
  129. package/build/system/mcp-servers/admin/schemas.d.ts +491 -24
  130. package/build/system/mcp-servers/admin/schemas.js +32 -4
  131. package/build/system/mcp-servers/admin/users.js +1 -1
  132. package/build/system/seed/tool-manifests-admin.js +5 -0
  133. package/build/tsconfig.tsbuildinfo +1 -1
  134. package/build/types/capability.d.ts +2 -1
  135. package/build/types/index.d.ts +3 -2
  136. package/build/types/labels/index.d.ts +4 -0
  137. package/build/types/labels/index.js +2 -0
  138. package/build/types/labels/job.d.ts +51 -0
  139. package/build/types/labels/job.js +2 -0
  140. package/build/types/labels/source.d.ts +44 -0
  141. package/build/types/labels/source.js +2 -0
  142. package/build/types/labels/template.d.ts +46 -0
  143. package/build/types/labels/template.js +2 -0
  144. package/build/types/labels/transport.d.ts +24 -0
  145. package/build/types/labels/transport.js +2 -0
  146. package/build/types/scan-choice.d.ts +2 -4
  147. package/build/types/scan-code/constants.d.ts +1 -0
  148. package/build/types/scan-code/constants.js +1 -0
  149. package/build/types/scan-code/response.d.ts +22 -4
  150. package/build/types/scan-code/rule.d.ts +66 -3
  151. package/build/types/startup.d.ts +37 -0
  152. package/build/types/user.d.ts +2 -0
  153. package/dashboard/dist/assets/{AdminDashboard-VQ1fhhJP.js → AdminDashboard-BafKaq50.js} +2 -2
  154. package/dashboard/dist/assets/{AdminDashboard-VQ1fhhJP.js.map → AdminDashboard-BafKaq50.js.map} +1 -1
  155. package/dashboard/dist/assets/{AgentConfigPage-BOe_W2Ij.js → AgentConfigPage-CFHf31DT.js} +6 -6
  156. package/dashboard/dist/assets/{AgentConfigPage-BOe_W2Ij.js.map → AgentConfigPage-CFHf31DT.js.map} +1 -1
  157. package/dashboard/dist/assets/{AgentDetailPage-5ov5D9V2.js → AgentDetailPage-CEvz5rJr.js} +3 -3
  158. package/dashboard/dist/assets/{AgentDetailPage-5ov5D9V2.js.map → AgentDetailPage-CEvz5rJr.js.map} +1 -1
  159. package/dashboard/dist/assets/{AgentsPage-DDFMKHhI.js → AgentsPage-DjQaio0O.js} +2 -2
  160. package/dashboard/dist/assets/{AgentsPage-DDFMKHhI.js.map → AgentsPage-DjQaio0O.js.map} +1 -1
  161. package/dashboard/dist/assets/AvailableEscalationsPage-UB03VTJx.js +2 -0
  162. package/dashboard/dist/assets/AvailableEscalationsPage-UB03VTJx.js.map +1 -0
  163. package/dashboard/dist/assets/{BotPicker-Dqpo36dM.js → BotPicker-C7MNWOF7.js} +2 -2
  164. package/dashboard/dist/assets/{BotPicker-Dqpo36dM.js.map → BotPicker-C7MNWOF7.js.map} +1 -1
  165. package/dashboard/dist/assets/BulkAssignModal-h5fX-_cV.js +2 -0
  166. package/dashboard/dist/assets/{BulkAssignModal-CmLVxkz-.js.map → BulkAssignModal-h5fX-_cV.js.map} +1 -1
  167. package/dashboard/dist/assets/{CapabilitiesPage-Dfkip6_b.js → CapabilitiesPage-BIzDl-ZT.js} +2 -2
  168. package/dashboard/dist/assets/{CapabilitiesPage-Dfkip6_b.js.map → CapabilitiesPage-BIzDl-ZT.js.map} +1 -1
  169. package/dashboard/dist/assets/{CollapsibleSection-CYNYMYSa.js → CollapsibleSection-B5TivtEg.js} +2 -2
  170. package/dashboard/dist/assets/{CollapsibleSection-CYNYMYSa.js.map → CollapsibleSection-B5TivtEg.js.map} +1 -1
  171. package/dashboard/dist/assets/{ConfirmDeleteModal-CpJNP-8w.js → ConfirmDeleteModal-CB4nKePb.js} +2 -2
  172. package/dashboard/dist/assets/{ConfirmDeleteModal-CpJNP-8w.js.map → ConfirmDeleteModal-CB4nKePb.js.map} +1 -1
  173. package/dashboard/dist/assets/{ConnectedAppsPage-DXIp2Dpl.js → ConnectedAppsPage-B3S5gVWw.js} +2 -2
  174. package/dashboard/dist/assets/{ConnectedAppsPage-DXIp2Dpl.js.map → ConnectedAppsPage-B3S5gVWw.js.map} +1 -1
  175. package/dashboard/dist/assets/{CountdownTimer-CuPY7zkb.js → CountdownTimer-BHVIq3kA.js} +2 -2
  176. package/dashboard/dist/assets/{CountdownTimer-CuPY7zkb.js.map → CountdownTimer-BHVIq3kA.js.map} +1 -1
  177. package/dashboard/dist/assets/CredentialConfirmModal-w0AGmCIe.js +2 -0
  178. package/dashboard/dist/assets/CredentialConfirmModal-w0AGmCIe.js.map +1 -0
  179. package/dashboard/dist/assets/{CredentialsPage-CtrnkHcj.js → CredentialsPage-BtCGBJrT.js} +2 -2
  180. package/dashboard/dist/assets/{CredentialsPage-CtrnkHcj.js.map → CredentialsPage-BtCGBJrT.js.map} +1 -1
  181. package/dashboard/dist/assets/{CronLabel-DVjTw5Ri.js → CronLabel-BG1rZK-5.js} +2 -2
  182. package/dashboard/dist/assets/{CronLabel-DVjTw5Ri.js.map → CronLabel-BG1rZK-5.js.map} +1 -1
  183. package/dashboard/dist/assets/{DropZone-DefYTYQy.js → DropZone-D8ZVdEb5.js} +2 -2
  184. package/dashboard/dist/assets/{DropZone-DefYTYQy.js.map → DropZone-D8ZVdEb5.js.map} +1 -1
  185. package/dashboard/dist/assets/{ElapsedCell-gY_mGMTF.js → ElapsedCell-l4m8Yvfv.js} +2 -2
  186. package/dashboard/dist/assets/{ElapsedCell-gY_mGMTF.js.map → ElapsedCell-l4m8Yvfv.js.map} +1 -1
  187. package/dashboard/dist/assets/{EntityTimelinePanel-DJN_ZEQa.js → EntityTimelinePanel-BOHlIaxF.js} +2 -2
  188. package/dashboard/dist/assets/{EntityTimelinePanel-DJN_ZEQa.js.map → EntityTimelinePanel-BOHlIaxF.js.map} +1 -1
  189. package/dashboard/dist/assets/{EscalationListSchemaPage-A4KpTdJA.js → EscalationListSchemaPage-BotlwlX3.js} +3 -3
  190. package/dashboard/dist/assets/{EscalationListSchemaPage-A4KpTdJA.js.map → EscalationListSchemaPage-BotlwlX3.js.map} +1 -1
  191. package/dashboard/dist/assets/{EscalationSchemaPage-nfCn42hT.js → EscalationSchemaPage-CfZSVOSD.js} +3 -3
  192. package/dashboard/dist/assets/{EscalationSchemaPage-nfCn42hT.js.map → EscalationSchemaPage-CfZSVOSD.js.map} +1 -1
  193. package/dashboard/dist/assets/{EscalationTimeline-CLvSr1SD.js → EscalationTimeline-CCKpuRBU.js} +2 -2
  194. package/dashboard/dist/assets/{EscalationTimeline-CLvSr1SD.js.map → EscalationTimeline-CCKpuRBU.js.map} +1 -1
  195. package/dashboard/dist/assets/{EscalationTitleSelect-CT7mYHkb.js → EscalationTitleSelect-cpTzPHiW.js} +2 -2
  196. package/dashboard/dist/assets/{EscalationTitleSelect-CT7mYHkb.js.map → EscalationTitleSelect-cpTzPHiW.js.map} +1 -1
  197. package/dashboard/dist/assets/{EscalationsOverview-CKaGRh-E.js → EscalationsOverview-DS-nK0qV.js} +2 -2
  198. package/dashboard/dist/assets/{EscalationsOverview-CKaGRh-E.js.map → EscalationsOverview-DS-nK0qV.js.map} +1 -1
  199. package/dashboard/dist/assets/{EventTable-2ywJsOLy.js → EventTable-UfebhJf0.js} +2 -2
  200. package/dashboard/dist/assets/{EventTable-2ywJsOLy.js.map → EventTable-UfebhJf0.js.map} +1 -1
  201. package/dashboard/dist/assets/{FilterBar-Dy0b7wwf.js → FilterBar-newA5l-X.js} +2 -2
  202. package/dashboard/dist/assets/{FilterBar-Dy0b7wwf.js.map → FilterBar-newA5l-X.js.map} +1 -1
  203. package/dashboard/dist/assets/{GraphInvokePage-yOVpraAy.js → GraphInvokePage-6SCDyQcK.js} +2 -2
  204. package/dashboard/dist/assets/{GraphInvokePage-yOVpraAy.js.map → GraphInvokePage-6SCDyQcK.js.map} +1 -1
  205. package/dashboard/dist/assets/HomePage-BEc-XdKj.js +2 -0
  206. package/dashboard/dist/assets/{HomePage-67xXjKjN.js.map → HomePage-BEc-XdKj.js.map} +1 -1
  207. package/dashboard/dist/assets/LabelJobsPage-BO50zXT5.js +2 -0
  208. package/dashboard/dist/assets/LabelJobsPage-BO50zXT5.js.map +1 -0
  209. package/dashboard/dist/assets/{LinePage-CMsYtukW.js → LinePage-NYxJQ-ex.js} +3 -3
  210. package/dashboard/dist/assets/{LinePage-CMsYtukW.js.map → LinePage-NYxJQ-ex.js.map} +1 -1
  211. package/dashboard/dist/assets/{LinesPage-pwL46mOS.js → LinesPage-RbWTaQRh.js} +3 -3
  212. package/dashboard/dist/assets/{LinesPage-pwL46mOS.js.map → LinesPage-RbWTaQRh.js.map} +1 -1
  213. package/dashboard/dist/assets/{ListToolbar-CJmvGy2B.js → ListToolbar-B-E9-toh.js} +2 -2
  214. package/dashboard/dist/assets/{ListToolbar-CJmvGy2B.js.map → ListToolbar-B-E9-toh.js.map} +1 -1
  215. package/dashboard/dist/assets/{McpOverview-DA9LLvNG.js → McpOverview-Shcf9QhZ.js} +2 -2
  216. package/dashboard/dist/assets/{McpOverview-DA9LLvNG.js.map → McpOverview-Shcf9QhZ.js.map} +1 -1
  217. package/dashboard/dist/assets/{McpQueryDetailPage-N7qLmfE8.js → McpQueryDetailPage-D8kmjy2v.js} +3 -3
  218. package/dashboard/dist/assets/{McpQueryDetailPage-N7qLmfE8.js.map → McpQueryDetailPage-D8kmjy2v.js.map} +1 -1
  219. package/dashboard/dist/assets/{McpQueryPage-CpsP3w7x.js → McpQueryPage-ck-o5m8A.js} +2 -2
  220. package/dashboard/dist/assets/{McpQueryPage-CpsP3w7x.js.map → McpQueryPage-ck-o5m8A.js.map} +1 -1
  221. package/dashboard/dist/assets/McpRunDetailPage-BJKkM9-3.js +2 -0
  222. package/dashboard/dist/assets/{McpRunDetailPage-qHRQ1pEY.js.map → McpRunDetailPage-BJKkM9-3.js.map} +1 -1
  223. package/dashboard/dist/assets/{McpRunsPage-BRDDYpTM.js → McpRunsPage-DqhHfD5G.js} +2 -2
  224. package/dashboard/dist/assets/{McpRunsPage-BRDDYpTM.js.map → McpRunsPage-DqhHfD5G.js.map} +1 -1
  225. package/dashboard/dist/assets/{NamespacePill-CeSfHH-j.js → NamespacePill--uIaGtrN.js} +2 -2
  226. package/dashboard/dist/assets/{NamespacePill-CeSfHH-j.js.map → NamespacePill--uIaGtrN.js.map} +1 -1
  227. package/dashboard/dist/assets/{OperationsPage-zUaab-CL.js → OperationsPage-D6B9Vv__.js} +3 -3
  228. package/dashboard/dist/assets/{OperationsPage-zUaab-CL.js.map → OperationsPage-D6B9Vv__.js.map} +1 -1
  229. package/dashboard/dist/assets/OperatorDashboard-CIH1cxjQ.js +2 -0
  230. package/dashboard/dist/assets/{OperatorDashboard-el5BquXN.js.map → OperatorDashboard-CIH1cxjQ.js.map} +1 -1
  231. package/dashboard/dist/assets/{PageHeader-DiGWAQlR.js → PageHeader-DClJ33fV.js} +2 -2
  232. package/dashboard/dist/assets/{PageHeader-DiGWAQlR.js.map → PageHeader-DClJ33fV.js.map} +1 -1
  233. package/dashboard/dist/assets/{PageHeaderWithStats-DwnKQ06j.js → PageHeaderWithStats-C-TrbKQL.js} +2 -2
  234. package/dashboard/dist/assets/{PageHeaderWithStats-DwnKQ06j.js.map → PageHeaderWithStats-C-TrbKQL.js.map} +1 -1
  235. package/dashboard/dist/assets/PersonaDetailPage-DjvfyIph.js +2 -0
  236. package/dashboard/dist/assets/{PersonaDetailPage-B_tb8gfl.js.map → PersonaDetailPage-DjvfyIph.js.map} +1 -1
  237. package/dashboard/dist/assets/{PersonasPage-BPI7mqM8.js → PersonasPage-D7ryA8Vc.js} +2 -2
  238. package/dashboard/dist/assets/{PersonasPage-BPI7mqM8.js.map → PersonasPage-D7ryA8Vc.js.map} +1 -1
  239. package/dashboard/dist/assets/{PortalPage-e_rBb1do.js → PortalPage-D3ybr0mo.js} +2 -2
  240. package/dashboard/dist/assets/{PortalPage-e_rBb1do.js.map → PortalPage-D3ybr0mo.js.map} +1 -1
  241. package/dashboard/dist/assets/PrintLabelsPanel-D0HF5x8b.js +2 -0
  242. package/dashboard/dist/assets/PrintLabelsPanel-D0HF5x8b.js.map +1 -0
  243. package/dashboard/dist/assets/{ProcessDetailPage-D35RX1bB.js → ProcessDetailPage-0xS9EdHe.js} +2 -2
  244. package/dashboard/dist/assets/{ProcessDetailPage-D35RX1bB.js.map → ProcessDetailPage-0xS9EdHe.js.map} +1 -1
  245. package/dashboard/dist/assets/{ProcessesListPage-CT81miI5.js → ProcessesListPage-93SMj1Fd.js} +2 -2
  246. package/dashboard/dist/assets/{ProcessesListPage-CT81miI5.js.map → ProcessesListPage-93SMj1Fd.js.map} +1 -1
  247. package/dashboard/dist/assets/{ResolverForm-BxJkoKAO.js → ResolverForm-DfogHDzl.js} +5 -5
  248. package/dashboard/dist/assets/{ResolverForm-BxJkoKAO.js.map → ResolverForm-DfogHDzl.js.map} +1 -1
  249. package/dashboard/dist/assets/RoleDetailPage-DlUOJWSB.js +8 -0
  250. package/dashboard/dist/assets/{RoleDetailPage-DtU7vsJm.js.map → RoleDetailPage-DlUOJWSB.js.map} +1 -1
  251. package/dashboard/dist/assets/{RolePill-D3hkAdKf.js → RolePill-BjD1Qw5y.js} +2 -2
  252. package/dashboard/dist/assets/{RolePill-D3hkAdKf.js.map → RolePill-BjD1Qw5y.js.map} +1 -1
  253. package/dashboard/dist/assets/RolesPage-DqhHSvaw.js +2 -0
  254. package/dashboard/dist/assets/{RolesPage-BE7RWt9q.js.map → RolesPage-DqhHSvaw.js.map} +1 -1
  255. package/dashboard/dist/assets/{RosterWidget-BJMx0a8Z.js → RosterWidget-BrIq61HR.js} +2 -2
  256. package/dashboard/dist/assets/RosterWidget-BrIq61HR.js.map +1 -0
  257. package/dashboard/dist/assets/RunAsSelector-D6zQrCNr.js +2 -0
  258. package/dashboard/dist/assets/{RunAsSelector-Co6s9bqA.js.map → RunAsSelector-D6zQrCNr.js.map} +1 -1
  259. package/dashboard/dist/assets/ScanCodesPage-B2S9DR2f.js +2 -0
  260. package/dashboard/dist/assets/{ScanCodesPage-C2TETaj5.js.map → ScanCodesPage-B2S9DR2f.js.map} +1 -1
  261. package/dashboard/dist/assets/ScanSchemeDetailPage-gpxKN-pL.js +5 -0
  262. package/dashboard/dist/assets/ScanSchemeDetailPage-gpxKN-pL.js.map +1 -0
  263. package/dashboard/dist/assets/ScanStationPage-B-UTgXsG.js +2 -0
  264. package/dashboard/dist/assets/ScanStationPage-B-UTgXsG.js.map +1 -0
  265. package/dashboard/dist/assets/{SchemeMatchFields-9H7SmbED.js → SchemeMatchFields-BK24aa7K.js} +2 -2
  266. package/dashboard/dist/assets/{SchemeMatchFields-9H7SmbED.js.map → SchemeMatchFields-BK24aa7K.js.map} +1 -1
  267. package/dashboard/dist/assets/{ScopeBadge-DGz79rmG.js → ScopeBadge-ofLQ6HW-.js} +2 -2
  268. package/dashboard/dist/assets/{ScopeBadge-DGz79rmG.js.map → ScopeBadge-ofLQ6HW-.js.map} +1 -1
  269. package/dashboard/dist/assets/{StickyPagination-miUdVAKw.js → StickyPagination-CgVv7vc_.js} +2 -2
  270. package/dashboard/dist/assets/{StickyPagination-miUdVAKw.js.map → StickyPagination-CgVv7vc_.js.map} +1 -1
  271. package/dashboard/dist/assets/{StreamMessageDetail-D5Rk7pn7.js → StreamMessageDetail-B9sxDVw4.js} +2 -2
  272. package/dashboard/dist/assets/{StreamMessageDetail-D5Rk7pn7.js.map → StreamMessageDetail-B9sxDVw4.js.map} +1 -1
  273. package/dashboard/dist/assets/{SwimlaneTimeline-B1QY1ZzH.js → SwimlaneTimeline-DQc0CYSL.js} +2 -2
  274. package/dashboard/dist/assets/{SwimlaneTimeline-B1QY1ZzH.js.map → SwimlaneTimeline-DQc0CYSL.js.map} +1 -1
  275. package/dashboard/dist/assets/{TagInput-DaIdhv3h.js → TagInput-47qVYzke.js} +2 -2
  276. package/dashboard/dist/assets/{TagInput-DaIdhv3h.js.map → TagInput-47qVYzke.js.map} +1 -1
  277. package/dashboard/dist/assets/{TaskDetailPage-DKUM37o8.js → TaskDetailPage-D6VOsA1f.js} +2 -2
  278. package/dashboard/dist/assets/{TaskDetailPage-DKUM37o8.js.map → TaskDetailPage-D6VOsA1f.js.map} +1 -1
  279. package/dashboard/dist/assets/{TaskQueuePill-sUA1nZe-.js → TaskQueuePill-C5KmdXAl.js} +2 -2
  280. package/dashboard/dist/assets/{TaskQueuePill-sUA1nZe-.js.map → TaskQueuePill-C5KmdXAl.js.map} +1 -1
  281. package/dashboard/dist/assets/{TasksListPage-CUulwvm-.js → TasksListPage-DG8hvO8G.js} +2 -2
  282. package/dashboard/dist/assets/{TasksListPage-CUulwvm-.js.map → TasksListPage-DG8hvO8G.js.map} +1 -1
  283. package/dashboard/dist/assets/{TimeAgo-CHTelacB.js → TimeAgo-CL02EhFi.js} +2 -2
  284. package/dashboard/dist/assets/{TimeAgo-CHTelacB.js.map → TimeAgo-CL02EhFi.js.map} +1 -1
  285. package/dashboard/dist/assets/{TimestampCell-NanLWLKo.js → TimestampCell-BE7oKVJg.js} +2 -2
  286. package/dashboard/dist/assets/{TimestampCell-NanLWLKo.js.map → TimestampCell-BE7oKVJg.js.map} +1 -1
  287. package/dashboard/dist/assets/{ToolPill-CpBAFdEX.js → ToolPill-Cp9Drk1s.js} +2 -2
  288. package/dashboard/dist/assets/{ToolPill-CpBAFdEX.js.map → ToolPill-Cp9Drk1s.js.map} +1 -1
  289. package/dashboard/dist/assets/{ToolTestPanel-CF1CHzgz.js → ToolTestPanel-CRecLh6S.js} +2 -2
  290. package/dashboard/dist/assets/{ToolTestPanel-CF1CHzgz.js.map → ToolTestPanel-CRecLh6S.js.map} +1 -1
  291. package/dashboard/dist/assets/{TopicDetailPage-CGO8XV_a.js → TopicDetailPage-QzkinTfN.js} +3 -3
  292. package/dashboard/dist/assets/{TopicDetailPage-CGO8XV_a.js.map → TopicDetailPage-QzkinTfN.js.map} +1 -1
  293. package/dashboard/dist/assets/{TopicsPage-Bt8gOKYr.js → TopicsPage-D8dW6J65.js} +2 -2
  294. package/dashboard/dist/assets/{TopicsPage-Bt8gOKYr.js.map → TopicsPage-D8dW6J65.js.map} +1 -1
  295. package/dashboard/dist/assets/{UserName-DKXnK7DD.js → UserName-Dw3R_zrl.js} +2 -2
  296. package/dashboard/dist/assets/{UserName-DKXnK7DD.js.map → UserName-Dw3R_zrl.js.map} +1 -1
  297. package/dashboard/dist/assets/WorkflowExecutionPage-BTocv8or.js +2 -0
  298. package/dashboard/dist/assets/{WorkflowExecutionPage-Crf7AIFc.js.map → WorkflowExecutionPage-BTocv8or.js.map} +1 -1
  299. package/dashboard/dist/assets/{WorkflowPill-CKHip3hH.js → WorkflowPill-BiLYq__w.js} +2 -2
  300. package/dashboard/dist/assets/{WorkflowPill-CKHip3hH.js.map → WorkflowPill-BiLYq__w.js.map} +1 -1
  301. package/dashboard/dist/assets/WorkflowsDashboard-CIPEt3et.js +2 -0
  302. package/dashboard/dist/assets/{WorkflowsDashboard--isjt06C.js.map → WorkflowsDashboard-CIPEt3et.js.map} +1 -1
  303. package/dashboard/dist/assets/{WorkflowsOverview-D7Oqf4-V.js → WorkflowsOverview-Bj4MJIE-.js} +2 -2
  304. package/dashboard/dist/assets/{WorkflowsOverview-D7Oqf4-V.js.map → WorkflowsOverview-Bj4MJIE-.js.map} +1 -1
  305. package/dashboard/dist/assets/{YamlWorkflowDetailPage-B0wxgrGP.js → YamlWorkflowDetailPage-DMEk5k9-.js} +2 -2
  306. package/dashboard/dist/assets/{YamlWorkflowDetailPage-B0wxgrGP.js.map → YamlWorkflowDetailPage-DMEk5k9-.js.map} +1 -1
  307. package/dashboard/dist/assets/{YamlWorkflowsPage-BVdLnm6K.js → YamlWorkflowsPage-F2yyyoiB.js} +2 -2
  308. package/dashboard/dist/assets/{YamlWorkflowsPage-BVdLnm6K.js.map → YamlWorkflowsPage-F2yyyoiB.js.map} +1 -1
  309. package/dashboard/dist/assets/{agents-CHjbjHXA.js → agents-mSgxEPpI.js} +2 -2
  310. package/dashboard/dist/assets/{agents-CHjbjHXA.js.map → agents-mSgxEPpI.js.map} +1 -1
  311. package/dashboard/dist/assets/{bots-WrUhEPWs.js → bots-p4Hp0CV6.js} +2 -2
  312. package/dashboard/dist/assets/{bots-WrUhEPWs.js.map → bots-p4Hp0CV6.js.map} +1 -1
  313. package/dashboard/dist/assets/{capabilities-CunMmkj8.js → capabilities-D_-I_SXR.js} +2 -2
  314. package/dashboard/dist/assets/{capabilities-CunMmkj8.js.map → capabilities-D_-I_SXR.js.map} +1 -1
  315. package/dashboard/dist/assets/{controlplane-D6IZIZoh.js → controlplane-DjdoQnRU.js} +2 -2
  316. package/dashboard/dist/assets/{controlplane-D6IZIZoh.js.map → controlplane-DjdoQnRU.js.map} +1 -1
  317. package/dashboard/dist/assets/{escalation-columns-Bvo6JI4Z.js → escalation-columns-R_IEVQjQ.js} +2 -2
  318. package/dashboard/dist/assets/{escalation-columns-Bvo6JI4Z.js.map → escalation-columns-R_IEVQjQ.js.map} +1 -1
  319. package/dashboard/dist/assets/{escalation-items-DFGRwo49.js → escalation-items-BGZlJMpk.js} +2 -2
  320. package/dashboard/dist/assets/{escalation-items-DFGRwo49.js.map → escalation-items-BGZlJMpk.js.map} +1 -1
  321. package/dashboard/dist/assets/{index-OuKQ_0eB.js → index-BEMdD58x.js} +2 -2
  322. package/dashboard/dist/assets/{index-OuKQ_0eB.js.map → index-BEMdD58x.js.map} +1 -1
  323. package/dashboard/dist/assets/index-BUmz0NMg.css +1 -0
  324. package/dashboard/dist/assets/{index-C7EIu1mG.js → index-BuCEhhnl.js} +2 -2
  325. package/dashboard/dist/assets/{index-C7EIu1mG.js.map → index-BuCEhhnl.js.map} +1 -1
  326. package/dashboard/dist/assets/{index-Bo8QU31k.js → index-BxbQmeqh.js} +2 -2
  327. package/dashboard/dist/assets/{index-Bo8QU31k.js.map → index-BxbQmeqh.js.map} +1 -1
  328. package/dashboard/dist/assets/index-C5osluV3.js +2 -0
  329. package/dashboard/dist/assets/{index-DRK7M1_9.js.map → index-C5osluV3.js.map} +1 -1
  330. package/dashboard/dist/assets/{index-ygxyAKcc.js → index-C_dAJUzh.js} +27 -27
  331. package/dashboard/dist/assets/index-C_dAJUzh.js.map +1 -0
  332. package/dashboard/dist/assets/{index-DRw0FXdX.js → index-D-FYj9jT.js} +2 -2
  333. package/dashboard/dist/assets/{index-DRw0FXdX.js.map → index-D-FYj9jT.js.map} +1 -1
  334. package/dashboard/dist/assets/{index-B8qrHwp9.js → index-D6K_IgCz.js} +2 -2
  335. package/dashboard/dist/assets/{index-B8qrHwp9.js.map → index-D6K_IgCz.js.map} +1 -1
  336. package/dashboard/dist/assets/index-D7L_VoBD.js +2 -0
  337. package/dashboard/dist/assets/index-D7L_VoBD.js.map +1 -0
  338. package/dashboard/dist/assets/{index-BZFSXEkr.js → index-D9RAN9sA.js} +2 -2
  339. package/dashboard/dist/assets/{index-BZFSXEkr.js.map → index-D9RAN9sA.js.map} +1 -1
  340. package/dashboard/dist/assets/{index-DCJ483vt.js → index-DUYAGxwc.js} +2 -2
  341. package/dashboard/dist/assets/{index-DCJ483vt.js.map → index-DUYAGxwc.js.map} +1 -1
  342. package/dashboard/dist/assets/{index-boT612Jo.js → index-Dk2KKo0z.js} +2 -2
  343. package/dashboard/dist/assets/{index-boT612Jo.js.map → index-Dk2KKo0z.js.map} +1 -1
  344. package/dashboard/dist/assets/{index-CpCchhQv.js → index-DlJkZ12b.js} +2 -2
  345. package/dashboard/dist/assets/{index-CpCchhQv.js.map → index-DlJkZ12b.js.map} +1 -1
  346. package/dashboard/dist/assets/index-FiNThtNU.js +3 -0
  347. package/dashboard/dist/assets/index-FiNThtNU.js.map +1 -0
  348. package/dashboard/dist/assets/{knowledge-BubJBTwg.js → knowledge-DSsPTqkK.js} +2 -2
  349. package/dashboard/dist/assets/{knowledge-BubJBTwg.js.map → knowledge-DSsPTqkK.js.map} +1 -1
  350. package/dashboard/dist/assets/{machines-DSm5NFgs.js → machines-DSgGtqqr.js} +2 -2
  351. package/dashboard/dist/assets/{machines-DSm5NFgs.js.map → machines-DSgGtqqr.js.map} +1 -1
  352. package/dashboard/dist/assets/{mcp-D6MckqOV.js → mcp-Cg-_uLw8.js} +2 -2
  353. package/dashboard/dist/assets/{mcp-D6MckqOV.js.map → mcp-Cg-_uLw8.js.map} +1 -1
  354. package/dashboard/dist/assets/{mcp-query-VyCdOag6.js → mcp-query-DQombEK_.js} +2 -2
  355. package/dashboard/dist/assets/{mcp-query-VyCdOag6.js.map → mcp-query-DQombEK_.js.map} +1 -1
  356. package/dashboard/dist/assets/{personas-CyJc10xe.js → personas-DYrcoVBu.js} +2 -2
  357. package/dashboard/dist/assets/{personas-CyJc10xe.js.map → personas-DYrcoVBu.js.map} +1 -1
  358. package/dashboard/dist/assets/{pipelines-B2inDtx3.js → pipelines-wdb4xsey.js} +2 -2
  359. package/dashboard/dist/assets/{pipelines-B2inDtx3.js.map → pipelines-wdb4xsey.js.map} +1 -1
  360. package/dashboard/dist/assets/{tasks-DOP4d3M6.js → tasks-Bil7gvm9.js} +2 -2
  361. package/dashboard/dist/assets/{tasks-DOP4d3M6.js.map → tasks-Bil7gvm9.js.map} +1 -1
  362. package/dashboard/dist/assets/{topics-CNOjSWpX.js → topics-wBqaVhRR.js} +2 -2
  363. package/dashboard/dist/assets/{topics-CNOjSWpX.js.map → topics-wBqaVhRR.js.map} +1 -1
  364. package/dashboard/dist/assets/{useDebouncedValue-CgO0TGMd.js → useDebouncedValue-CwrY8TpV.js} +2 -2
  365. package/dashboard/dist/assets/{useDebouncedValue-CgO0TGMd.js.map → useDebouncedValue-CwrY8TpV.js.map} +1 -1
  366. package/dashboard/dist/assets/{useNamespace-BWHvUKtK.js → useNamespace-Sod_xApz.js} +2 -2
  367. package/dashboard/dist/assets/{useNamespace-BWHvUKtK.js.map → useNamespace-Sod_xApz.js.map} +1 -1
  368. package/dashboard/dist/assets/{useYamlActivityEvents-BZQ__ZGD.js → useYamlActivityEvents-CKLInV3C.js} +2 -2
  369. package/dashboard/dist/assets/{useYamlActivityEvents-BZQ__ZGD.js.map → useYamlActivityEvents-CKLInV3C.js.map} +1 -1
  370. package/dashboard/dist/assets/{validate-CAin6WM_.js → validate-CYhW1xMJ.js} +2 -2
  371. package/dashboard/dist/assets/{validate-CAin6WM_.js.map → validate-CYhW1xMJ.js.map} +1 -1
  372. package/dashboard/dist/assets/{vendor-icons-en0_uSRD.js → vendor-icons-ed7mYQw4.js} +2 -2
  373. package/dashboard/dist/assets/{vendor-icons-en0_uSRD.js.map → vendor-icons-ed7mYQw4.js.map} +1 -1
  374. package/dashboard/dist/assets/{yaml-workflows-Dyln3od-.js → yaml-workflows-C20qHo3L.js} +2 -2
  375. package/dashboard/dist/assets/{yaml-workflows-Dyln3od-.js.map → yaml-workflows-C20qHo3L.js.map} +1 -1
  376. package/dashboard/dist/index.html +3 -3
  377. package/docs/api/http/escalations.md +15 -0
  378. package/docs/api/http/labels.md +115 -0
  379. package/docs/api/http/users.md +2 -0
  380. package/docs/api/mcp/admin.md +76 -1
  381. package/docs/code-owned-configuration.md +1 -1
  382. package/docs/dashboard.md +2 -2
  383. package/docs/hitl/x-lt-roster.md +2 -0
  384. package/docs/hitl/x-lt-scan.md +12 -0
  385. package/docs/iam.md +12 -0
  386. package/docs/label-sheets.md +267 -0
  387. package/docs/scan-codes.md +93 -9
  388. package/package.json +4 -1
  389. package/dashboard/dist/assets/AvailableEscalationsPage-GFn8Sgg1.js +0 -2
  390. package/dashboard/dist/assets/AvailableEscalationsPage-GFn8Sgg1.js.map +0 -1
  391. package/dashboard/dist/assets/BulkAssignModal-CmLVxkz-.js +0 -2
  392. package/dashboard/dist/assets/HomePage-67xXjKjN.js +0 -2
  393. package/dashboard/dist/assets/McpRunDetailPage-qHRQ1pEY.js +0 -2
  394. package/dashboard/dist/assets/OperatorDashboard-el5BquXN.js +0 -2
  395. package/dashboard/dist/assets/PersonaDetailPage-B_tb8gfl.js +0 -2
  396. package/dashboard/dist/assets/RoleDetailPage-DtU7vsJm.js +0 -8
  397. package/dashboard/dist/assets/RolesPage-BE7RWt9q.js +0 -2
  398. package/dashboard/dist/assets/RosterWidget-BJMx0a8Z.js.map +0 -1
  399. package/dashboard/dist/assets/RunAsSelector-Co6s9bqA.js +0 -2
  400. package/dashboard/dist/assets/ScanCodesPage-C2TETaj5.js +0 -2
  401. package/dashboard/dist/assets/ScanSchemeDetailPage-C2UgU8l-.js +0 -5
  402. package/dashboard/dist/assets/ScanSchemeDetailPage-C2UgU8l-.js.map +0 -1
  403. package/dashboard/dist/assets/ScanStationPage-nWYz-OD3.js +0 -2
  404. package/dashboard/dist/assets/ScanStationPage-nWYz-OD3.js.map +0 -1
  405. package/dashboard/dist/assets/WorkflowExecutionPage-Crf7AIFc.js +0 -2
  406. package/dashboard/dist/assets/WorkflowsDashboard--isjt06C.js +0 -2
  407. package/dashboard/dist/assets/index-B95LbYhW.js +0 -2
  408. package/dashboard/dist/assets/index-B95LbYhW.js.map +0 -1
  409. package/dashboard/dist/assets/index-BmzscsXK.css +0 -1
  410. package/dashboard/dist/assets/index-DRK7M1_9.js +0 -2
  411. package/dashboard/dist/assets/index-P-DlgAWj.js +0 -3
  412. package/dashboard/dist/assets/index-P-DlgAWj.js.map +0 -1
  413. package/dashboard/dist/assets/index-ygxyAKcc.js.map +0 -1
@@ -0,0 +1,267 @@
1
+ # Label Sheets
2
+
3
+ Every physical thing a floor acts on carries a printed scan code: locations,
4
+ containers, stations, machines, and the badges people scan to act. Label sheets print
5
+ those codes from the scan schemes that read them, on office printers (A4 and
6
+ Letter label stock, ID card stock) and thermal printers (ZPL).
7
+
8
+ A label is a heading, up to two lines of text, and one to four codes for one
9
+ target, each printed beside the act it names. A container label can print
10
+ **Check in** and **Check out** side by side; the person scanning chooses the
11
+ act by choosing which code to scan. The text is whatever the target's facts
12
+ say: the platform has no notion of what a target is.
13
+
14
+ ## Contents
15
+
16
+ - [Templates](#templates)
17
+ - [Targets](#targets)
18
+ - [Media and layout](#media-and-layout)
19
+ - [Output](#output)
20
+ - [Checking codes before printing](#checking-codes-before-printing)
21
+ - [Badges are credentials](#badges-are-credentials)
22
+ - [Who may print](#who-may-print)
23
+ - [The label ledger](#the-label-ledger)
24
+ - [Printer transports](#printer-transports)
25
+ - [Declaring templates in code](#declaring-templates-in-code)
26
+ - [Agents](#agents)
27
+
28
+ ## Templates
29
+
30
+ A template says what one label shows, for one scan scheme. Templates print
31
+ codes the platform mints: schemes with `fixed` or `delimited` encoding.
32
+
33
+ | Field | Meaning |
34
+ |---|---|
35
+ | `codes` | 1 to 4 of the scheme's rules, in print order. Each has a `caption` (default: the rule's name) and a `tone`: `solid` (white text on a black band), `outline`, or `plain`. Tones tell neighbouring codes apart on black-only stock. |
36
+ | `text.title`, `text.lines` | A heading and up to two lines, written in label tokens. |
37
+ | `symbology` | `code128` (default; shelves scanned from a distance), `qrcode`, or `datamatrix` (small labels). |
38
+ | `human_readable` | Print the code as text under its symbol. |
39
+ | `media` | The default media preset for this template. |
40
+ | `sensitive` | Printing confirms first and records who and what the labels name. Always true on an identity scheme. |
41
+
42
+ Label tokens:
43
+
44
+ | Token | Value |
45
+ |---|---|
46
+ | `{target}` | The code's target (action schemes). |
47
+ | `{item.<facet>}` | A facet of the row the target came from, or a column of a pasted list. |
48
+ | `{user.display_name}`, `{user.name}`, `{user.email}`, `{user.roles}`, `{user.<property>}` | The badge holder (identity schemes). |
49
+ | `{scheme.name}` | The scheme's name. |
50
+
51
+ A token with no value prints empty, and the preview warns about it
52
+ (`missing_token`, naming the facts the label does have). Captions take tokens
53
+ too; a caption left blank prints the rule's name as written. Identity
54
+ credentials never print as text:
55
+ `{target}` and `{user.<identity key>}` are refused on identity templates.
56
+
57
+ Manage templates on **Admin → Scan Codes → (scheme) → Labels**, through
58
+ `PUT /api/labels/templates/:name`, or with the `upsert_label_template` MCP
59
+ tool. Every write bumps the template's `revision`; an edit that names
60
+ `expected_revision` is refused when someone else saved first.
61
+
62
+ ## Targets
63
+
64
+ A print job is a template plus a source of targets:
65
+
66
+ | Source | Targets |
67
+ |---|---|
68
+ | `{ kind: 'range', prefix, from, to, pad, suffix }` | A numbered run: `A-01` to `A-40`. Targets can be printed before anything else is known about them. |
69
+ | `{ kind: 'list', text }` | One target per line. A header row starting with `target` names the other columns, which fill `{item.<column>}`. |
70
+ | `{ kind: 'escalations', ids }` | Rows selected in a list. Each row is read as the caller; its metadata fills `{item.*}`. |
71
+ | `{ kind: 'facets', query }` | Every row a faceted search returns, searched as the caller. The newest row per target wins. |
72
+ | `{ kind: 'users', userIds, role }` | Users carrying the identity scheme's key: the ids given, everyone in `role`, or with neither, every badge holder. The only source an identity template accepts. On **Accounts**, **Print badges** prints the selected users, or with none selected, everyone or everyone in a role. |
73
+
74
+ A job holds at most `LT_LABELS_MAX_PER_JOB` labels (default 1000) and at most
75
+ `LT_LABELS_MAX_CREDENTIALS_PER_JOB` badges (default 200).
76
+
77
+ ## Media and layout
78
+
79
+ Shipped presets (`GET /api/labels/media`):
80
+
81
+ | Family | Presets |
82
+ |---|---|
83
+ | A4 | `a4-l7160` (21 per sheet), `a4-l7163` (14), `a4-l7165` (8), `a4-l7173` (10), `a4-l7651` (65), `a4-a6` (4), `a4-placard` (1), `a4-cr80` (10 ID cards) |
84
+ | Letter | `letter-5160` (30), `letter-5163` (10), `letter-22805` (24 squares), `letter-placard` (1), `letter-cr80` (8 ID cards) |
85
+ | Thermal | `thermal-4x6`, `thermal-4x2`, `thermal-2x1` at 203 dpi |
86
+
87
+ A job prints on the media it names, then the template's media, then the
88
+ deployment default (`LT_LABELS_DEFAULT_MEDIA`, `a4-l7160` unless set). A job
89
+ can also pass a custom grid: page size, rows and columns, label size,
90
+ margins and gutters, all in millimetres.
91
+
92
+ Per job:
93
+
94
+ - `startPosition` skips used labels on the first sheet (counted from 1).
95
+ - `copies` prints each label several times, together.
96
+ - `onePerPage` puts each label on its own page (placards).
97
+ - `cutMarks` prints trim marks for card stock.
98
+
99
+ Labels lay out to fit their box. When a code would print below the stock's
100
+ minimum bar width (`minModuleMm`, 0.25 mm on the presets) or without its blank
101
+ margin, the job reports a `scale` or `quiet_zone` warning.
102
+
103
+ ## Output
104
+
105
+ `POST /api/labels/issue` delivers a job as:
106
+
107
+ | `output` | Result |
108
+ |---|---|
109
+ | `sheet` | The laid-out sheet as JSON. The dashboard prints it through the browser at exact size. |
110
+ | `pdf` | A PDF at the media's exact page size. |
111
+ | `zpl` | ZPL for thermal media, using the printer's own barcode commands. |
112
+ | `transport:<name>` | Sent through a registered [printer transport](#printer-transports). |
113
+
114
+ PDF text uses Helvetica, which covers Latin names with accents. A deployment
115
+ that prints names in other scripts registers a font with
116
+ `start({ labels: { font: { regular, bold } } })`.
117
+
118
+ ## Checking codes before printing
119
+
120
+ A preview (`POST /api/labels/preview`) lays out the job without printing or
121
+ recording it, and lists a warning for every label that would fail on the floor:
122
+
123
+ - `unparseable`: the code does not read back as its scheme, or the scheme is disabled.
124
+ - `rule_disabled`: the code's rule is disabled; scanning it does nothing.
125
+ - `unresolved`: the target names no row today, or the badge holder is not an active user.
126
+ - `missing_token`: the heading, a line or a caption reads `{item.<facet>}` or `{user.<key>}`, and the label's data has no such value.
127
+ - `scale`, `quiet_zone`, `overflow`, `unencodable`: the code or text does not fit the label.
128
+
129
+ The dashboard prints only after a preview of the same choice. In Chrome, the
130
+ preview can also decode every code on screen and report any it cannot read
131
+ back.
132
+
133
+ ## Badges are credentials
134
+
135
+ An identity scheme's code acts as a person, so printing one follows its own
136
+ rules:
137
+
138
+ - Only a credential issuer may print or reissue a badge (see [Who may print](#who-may-print)).
139
+ - A badge preview is masked: it shows where each code goes, never the code.
140
+ - Printing asks for confirmation (`confirm: true`), and the ledger row naming the requester and every holder is written before any code is composed.
141
+ - Badge codes travel in response bodies with `Cache-Control: no-store`, never in URLs, and never in logs or the ledger.
142
+ - User reads (`GET /api/users`, `GET /api/users/:id`, user writes' responses) leave identity keys out of `metadata` and list them in `identity_bound`.
143
+ - Setting or removing an identity key by hand (`PATCH /api/users/:id/properties`) needs the same access and is recorded as a `bind`.
144
+ - Badge scans are unchanged: a scanned token resolves against `lt_users.metadata` on the server, as before.
145
+
146
+ The user API protections (the last two points, and the refusal of identity keys
147
+ in wholesale `metadata` writes) are on by default.
148
+ `start({ labels: { protectIdentityKeys: false } })` or
149
+ `LT_PROTECT_IDENTITY_KEYS=false` keeps the earlier users API behavior; badge
150
+ printing and reissue still need `credentialIssuer`. Either way, a `metadata`
151
+ replace keeps the identity keys it leaves out.
152
+
153
+ **Reissue** (`POST /api/labels/badges/reissue`) mints a new credential that
154
+ fits the scheme's encoding, writes it and its ledger row in one statement, and
155
+ prints the new badge. On a delimited identity scheme the credential is
156
+ `target_length` random characters (8 to 64, default 10; **Badge length** on
157
+ the scheme page), and the badge encodes it with its prefix, for example
158
+ `14:0:7KQ2M9XW4H`. On a fixed scheme it is `target_length` digits. Badges of
159
+ any length keep scanning; the length only shapes new ones. Ten characters keep
160
+ a Code 128 badge on an ID card comfortably above the minimum bar width. The old code resolves to no one from that moment. An
161
+ acting grant minted from the old badge before the reissue lasts until its
162
+ `grant_ttl_seconds` runs out.
163
+
164
+ ## Who may print
165
+
166
+ | Labels | Access |
167
+ |---|---|
168
+ | Item labels (action schemes) | Admin access or role management (admin, superadmin, the `engineer` role). |
169
+ | Badges (identity schemes) | The `credentialIssuer` capability: superadmin, or a holder of the `credential-issuer` role. Admin type alone does not grant it. |
170
+ | Templates | Role management to write; any signed-in user to read. |
171
+
172
+ ## The label ledger
173
+
174
+ Every print, reissue and binding is a row in `lt_label_jobs`: who asked, when,
175
+ the template and its revision (with a snapshot), the media and output, and
176
+ what the labels name: targets for item labels, user ids for badges. Rows are
177
+ never deleted by the platform; the only columns it updates are the delivery
178
+ stamps of a transport job.
179
+
180
+ **Admin → Label History** (`GET /api/labels/jobs`) lists the ledger.
181
+ Credential issuers see every row; other readers see item jobs and their own.
182
+ **Print again** (`POST /api/labels/jobs/:id/reprint`) prints a job, or chosen
183
+ labels of it, again from its source with the template as it is now, and
184
+ records a new job. A badge reprint confirms again.
185
+
186
+ An `idempotencyKey` on an issue request makes it safe to repeat, which is what
187
+ a workflow activity retry does. The repeat records nothing new and prints only
188
+ the labels the first request recorded:
189
+
190
+ - A sheet, PDF or ZPL output renders those labels again.
191
+ - A transport output is sent under a delivery lease. Claiming the lease is one
192
+ statement, so concurrent repeats send once. A job already delivered is not
193
+ sent again. A job whose send failed, or whose sender stopped before the
194
+ transport accepted, is sent by the next repeat once its lease
195
+ (`LT_LABELS_DELIVERY_LEASE_SECONDS`, default 120) lapses.
196
+ - A key used before for a different template or output answers `409`.
197
+
198
+ Workflow activities pass their workflow id as the key.
199
+
200
+ ## Printer transports
201
+
202
+ A transport routes issued labels to a printer: a thermal printer on the
203
+ network, a print server, a watched folder. Hosts register transports by name:
204
+
205
+ ```typescript
206
+ import type { LTLabelTransport } from '@hotmeshio/long-tail';
207
+
208
+ const thermal: LTLabelTransport = {
209
+ formats: ['zpl'],
210
+ async send({ jobId, payload, destination }) {
211
+ await sendToPrinter(destination, payload as string);
212
+ return { accepted: true, detail: jobId };
213
+ },
214
+ };
215
+
216
+ start({ labels: { transports: { thermal }, defaultMedia: 'a4-l7160' } });
217
+ ```
218
+
219
+ A job sends with `output: 'transport:thermal'`; `destination` on the request
220
+ passes through to `send` as given, and the transport decides what it names. A name with no registered transport is refused
221
+ before anything is recorded. `GET /api/labels/transports` lists the registered
222
+ names, and the dashboard offers **Send** when one accepts the job's format.
223
+
224
+ The examples register `storage-drop`, which writes each job to file storage at
225
+ `labels/<jobId>.<format>`.
226
+
227
+ ## Declaring templates in code
228
+
229
+ Templates declare with their scheme and follow the
230
+ [code-owned configuration](code-owned-configuration.md) contract as one unit
231
+ with it:
232
+
233
+ ```typescript
234
+ scanSchemes: [
235
+ {
236
+ version: 14,
237
+ name: 'Container',
238
+ target_facet: 'containerId',
239
+ encoding: 'delimited',
240
+ rules: [
241
+ { category: '0', name: 'Check in', steps: [/* … */] },
242
+ { category: '1', name: 'Check out', steps: [/* … */] },
243
+ ],
244
+ labels: [
245
+ {
246
+ name: 'container',
247
+ title: 'Container',
248
+ codes: [{ category: '0', tone: 'solid' }, { category: '1', tone: 'outline' }],
249
+ text: { title: '{target}', lines: ['{item.subtitle}'] },
250
+ media: 'a4-l7160',
251
+ },
252
+ ],
253
+ },
254
+ ],
255
+ ```
256
+
257
+ ## Agents
258
+
259
+ The admin MCP server carries `list_label_templates`, `upsert_label_template`,
260
+ `delete_label_template`, and `render_label_sheet`. `render_label_sheet` issues
261
+ item labels as the caller, stores the PDF or ZPL in file storage, and returns
262
+ the job id, the file ref, a link valid for ten minutes, and the warnings.
263
+ It refuses sensitive and identity templates: people print badges.
264
+
265
+ The `relabel` example workflow shows labels printed from a workflow: it asks a
266
+ person for a label's second line, then prints the label with it through a
267
+ transport, keyed by its workflow id.
@@ -31,6 +31,7 @@ canonical action surface. A scan is an **ECA rule** over that surface:
31
31
  - [Capture on the dashboard](#capture-on-the-dashboard)
32
32
  - [Scanner setup](#scanner-setup)
33
33
  - [Admin configuration](#admin-configuration)
34
+ - [Printing labels](label-sheets.md)
34
35
  - [The printer demo](#the-printer-demo)
35
36
  - [The bag and bin demo](#the-bag-and-bin-demo)
36
37
 
@@ -273,6 +274,10 @@ receives the raw value and renders it with the list's formatter, so an ISO
273
274
  instant in metadata reads the same on the station as in a list column (and
274
275
  in the deployment's display time zone, when one is set).
275
276
 
277
+ `show` names a [roster](hitl/x-lt-roster.md) field of the row's form, rendered
278
+ above the choices as a hold renders it: an arrival screen lists what came in
279
+ the container before the person taps Arrive.
280
+
276
281
  Without `facts`, the station lists the row's metadata, leaving out the
277
282
  bookkeeping a bench never acts on: scan provenance (`scannedAt`,
278
283
  `scanScheme`, `scanCategory`, `scanStation`, `scanActionName`),
@@ -358,7 +363,10 @@ set one ("Take the new label from the printer and stick it on C-12").
358
363
  Any step that writes may carry `done: { markdown }`: the copy the station shows,
359
364
  large, once the write lands and until the next scan ("Place it in
360
365
  **{container.containerCode}**. All good."). It reads the same bags its refusal copy
361
- reads. A fill or an into-subject add that leaves slots open shows its done
366
+ reads. `done.afterSeconds` (0-60) sets how long this act's copy stays up before
367
+ the station returns, over the role's `scan_done.after_seconds`, and
368
+ `done.nextPrompt` replaces the "Scan the next item" line under it when the next
369
+ act is not a scan ("Set the bag in tub **{container.tubCode}**"). A fill or an into-subject add that leaves slots open shows its done
362
370
  copy under the hold; without done copy the station shows the count ("2 of 5
363
371
  checked off" for a fill, "2 of 5 added" for an add).
364
372
 
@@ -375,6 +383,22 @@ unchanged.
375
383
  "show": "shoes" } }
376
384
  ```
377
385
 
386
+ **Ending the hold.** The hold card's button lets go of the item. By default it
387
+ reads "Put it down" and the station stays where it is. `hold.release` names it
388
+ for the bench: `label`, `tone: "accent"` to draw it as the screen's primary act,
389
+ and `return` (`home` or a dashboard route) for where the station goes once
390
+ released. Releasing writes nothing: items not yet scanned simply wait for the
391
+ next trip. With `hold.show`, `hold.whenAllIn` ends the hold on its own once
392
+ every entry on the roster is in. The station shows its done copy
393
+ (`markdown`, `afterSeconds`, `nextPrompt`, rendered against the held row), then
394
+ returns as after a completed act.
395
+
396
+ ```jsonc
397
+ "params": { "hold": { "label": "{item.tubCode}", "show": "bags",
398
+ "release": { "label": "I'm done", "tone": "accent", "return": "home" },
399
+ "whenAllIn": { "markdown": "Every bag is in **{item.tubCode}**.", "afterSeconds": 5 } } }
400
+ ```
401
+
378
402
  The server trusts nothing about the subject. Each request re-parses its
379
403
  code, re-reads the row under the station's read scope, requires the row to
380
404
  still carry the code's target and to be pending. A subject that fails is
@@ -418,6 +442,19 @@ printed code. With them, `{fill.pending}` lists the open entries by label,
418
442
  refusal's `expected` reads the labels. An entry the map does not name reads as
419
443
  its code; without `fill.labels`, both tokens read codes.
420
444
 
445
+ **Which key a fill takes.** A scan fills the first open key for its code, in
446
+ the row's order. When the same code is expected under several keys that each
447
+ belong to something the station can hold (two boxes of one item arriving in
448
+ two parcels), `fill.prefer` names a per-key map on the batch row naming the
449
+ value each key belongs to. Open keys whose value equals the held subject's
450
+ target (or, for a list value, contains it) fill first; the rest follow as
451
+ before. Held by parcel `P2`, scanning the item fills the key mapped to `P2`.
452
+
453
+ ```jsonc
454
+ "params": { "fill": { "into": "subject", "prefer": "envelope.key_parcels" } }
455
+ // the row's envelope: { "key_parcels": { "<code>#1": "P1", "<code>#2": "P2" } }
456
+ ```
457
+
421
458
  ```jsonc
422
459
  "refuse": { "markdown": "Not one of this order's shoes. Still to match: {fill.pending}." },
423
460
  "done": { "markdown": "Matched. Next: {fill.next}" },
@@ -443,6 +480,14 @@ declares `refuse.conflict` also clears the subject so the next item scan
443
480
  reads fresh state. Exactly one of two racing acts wins whenever both name
444
481
  the same row: the reciprocal statement writes both rows or neither.
445
482
 
483
+ **Where the scanned item is now.** Refusal and done copy may read
484
+ `{located.<facet>}`: the scanned code's own pending row, the newest one in any
485
+ role the reader may read (the held row excepted). Besides the row's facets it
486
+ carries `id`, `role` and `roleTitle` (the role's title, else its name), so a
487
+ refusal can say where the item belongs: "This bag is at
488
+ **{located.roleTitle}**." The row is read only for a step whose copy or Open
489
+ names it; with no such row the token renders empty.
490
+
446
491
  **The item's own row on an into-subject add.** A held container that collects
447
492
  item codes (a box being packed from a bin) often has items that each wait on
448
493
  their own row. `accumulate.item` locates that row and writes it as the
@@ -633,6 +678,30 @@ Pair kiosk with `x-lt-transition-done` on the role's form schema
633
678
  resolve lands back on the list rather than walking browser history — see
634
679
  [x-lt-transition](./hitl/x-lt-transition.md).
635
680
 
681
+ ### Open: from a scan result into its row
682
+
683
+ The station's answer stays light (right container or wrong one), but the moment
684
+ something is off the person needs the full form. A step's `open` puts an
685
+ **Open** button on the hold card, the done screen or the refusal it answers with:
686
+
687
+ ```jsonc
688
+ "open": { "target": "subject", "claim": true }
689
+ "open": { "target": "row", "label": "Open the bin", "list": { "facets": ["binCode"], "role": "binning" } }
690
+ "open": { "target": "located", "label": "Where it is" }
691
+ ```
692
+
693
+ `target` is the row the step acted on or located (`row`), the held row
694
+ (`subject`, on a hold the row just held), or the scanned code's own pending row
695
+ (`located`). Open lands on that row's detail page, in the app. With `list`, it
696
+ lands on the faceted list of rows sharing those facets with the target, the
697
+ values read from the target row on the server. With `claim`, the row is claimed
698
+ first as the person acting (the badge rides the claim) and opens claimed in
699
+ their name; a claim the server refuses (no badge, a scope that does not cover
700
+ it, someone else's claim) still opens the row, read-only, where the detail page
701
+ offers its own Claim. Opening from a hold lets go of the item. A target with no
702
+ row, or a list facet the row does not carry, offers no button. Every decision
703
+ (reject, missing, done) stays on the detail form.
704
+
636
705
  ### After a scan completes: the return
637
706
 
638
707
  A station works in one rhythm: badge, item, destination, done, back to the
@@ -644,7 +713,9 @@ list. A role names the last step in `properties.scan_done`:
644
713
 
645
714
  `return` is `home` (the role's kiosk home: its first portal, else its list) or
646
715
  a dashboard-relative route; `after_seconds` (0-60, default 2) is how long the
647
- done copy stays up first. The station returns once a scan act completes its
716
+ done copy stays up first, and a step's `done.afterSeconds` sets it for one act.
717
+ The done screen counts the seconds down. `button` (e.g. `"Done"`) adds a button
718
+ that returns at once. The station returns once a scan act completes its
648
719
  row: the last fill of a batch, an executed choice with done copy, any write
649
720
  that clears the subject. A fill that leaves entries pending stays on the hold
650
721
  card, a refusal never returns, and a `follow` runs first. A station holding
@@ -687,6 +758,11 @@ submit for ten minutes. A grant bound to a scanned subject (`grant_scope:
687
758
  locally, so the identity gate sits at the one place a record actually
688
759
  changes, once per change.
689
760
 
761
+ Claiming at a station works the same way. On a read-only station login, the
762
+ detail page's Claim asks for a badge and claims as whoever badges in; the badge
763
+ then stays primed for the work on the row, bounded by its grant's own uses and
764
+ lifetime. A claim the server refuses says why on the claim bar.
765
+
690
766
  Mutations attribute to the badged person (`assigned_to`, `resolved_by`)
691
767
  with the device recorded beside them (`scanStation` in the scan
692
768
  provenance) — every action individually owned and geographically placed.
@@ -708,12 +784,19 @@ A field can take a scan while the form is open: with
708
784
  [`x-lt-scan`](hitl/x-lt-scan.md), scanning a container into a claimed form
709
785
  fills its container field (checked against what the record expects), and
710
786
  `x-lt-scan-submit` submits once the scan fields are filled, which raises the
711
- badge prompt. A scan no field accepts runs globally as usual.
712
-
713
- Badge tokens are printed credentials: seed them as long random strings,
714
- bind them server-side (`lt_users.metadata`), and treat badge possession
715
- with the same physical policy as any badge system. Unknown badges answer
716
- `identity_unknown` and are auditable.
787
+ badge prompt. A batch [roster](hitl/x-lt-roster.md) that declares `x-lt-scan`
788
+ checks its entries off the same way: a scan of an accepted scheme, with nothing
789
+ focused, fills the row's first open entry for that code on the server, as the
790
+ person acting. A scan no field accepts runs globally as usual.
791
+
792
+ Badge tokens are printed credentials: bind them server-side
793
+ (`lt_users.metadata`) as random strings (generated badges are `target_length`
794
+ characters, default 10), and treat badge possession with
795
+ the same physical policy as any badge system. User reads leave identity keys
796
+ out of `metadata` and list them in `identity_bound`. Printing, reissuing and
797
+ binding a badge needs the `credentialIssuer` capability and is recorded in
798
+ the label ledger; see [label-sheets.md](label-sheets.md#badges-are-credentials).
799
+ Unknown badges answer `identity_unknown`.
717
800
 
718
801
  ## The fallback screen
719
802
 
@@ -839,7 +922,8 @@ UPC-A where numeric-only labels are already in circulation.
839
922
  at a target facet — its two-digit index is assigned for you. A scheme's detail
840
923
  page lists its actions; **Add an action** opens the rule editor:
841
924
 
842
- 1. **Name it** — the friendly label printed beside the physical code.
925
+ 1. **Name it** — the friendly label printed beside the physical code. Label
926
+ templates print it there; see [label-sheets.md](label-sheets.md).
843
927
  2. **Order the conditions** — each step picks a queue, a held-by filter,
844
928
  and its action; steps reorder with arrows. First match wins.
845
929
  3. **Set the fallback** — markdown for the no-match screen.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmeshio/long-tail",
3
- "version": "0.30.4",
3
+ "version": "0.31.0",
4
4
  "description": "Long Tail Workflows — Durable AI workflows with human-in-the-loop escalation. Powered by PostgreSQL.",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -87,9 +87,11 @@
87
87
  "@opentelemetry/resources": "^2.5.1",
88
88
  "@opentelemetry/sdk-node": "^0.218.0",
89
89
  "@opentelemetry/semantic-conventions": "^1.39.0",
90
+ "@pdf-lib/fontkit": "^1.1.1",
90
91
  "ajv": "^8.20.0",
91
92
  "arctic": "^3.7.0",
92
93
  "bcryptjs": "^2.4.3",
94
+ "bwip-js": "^4.11.4",
93
95
  "commander": "^14.0.3",
94
96
  "express": "^5.1.0",
95
97
  "hono": "^4.12.23",
@@ -97,6 +99,7 @@
97
99
  "nats": "^2.28.0",
98
100
  "openai": "^5.9.0",
99
101
  "ora": "^9.4.0",
102
+ "pdf-lib": "^1.17.1",
100
103
  "pg": "^8.13.0",
101
104
  "picocolors": "^1.1.1",
102
105
  "pino": "^9.6.0",
@@ -1,2 +0,0 @@
1
- import{a as m,j as e}from"./vendor-query-DvWWuNIB.js";import{w as ut,x as mt,c as xt,y as ht,M as Se,z as gt,A as ft,B as pt,E as bt,G as yt,H as jt,I as vt,K as Ct,L as kt,O as Nt,Q as wt,r as Pt,R as St,T as Rt,U as Et,V as Tt,W as At,X as Bt,Y as Ot,Z as Lt,_ as Mt,$ as Ft,a0 as zt,a1 as It,a2 as Ut,a3 as Vt,a4 as $t,a5 as _t,a6 as qt}from"./index-ygxyAKcc.js";import{a as Re,u as Ee,f as Ht}from"./vendor-react-_9U4mKFr.js";import{i as Kt}from"./task-queues-7-sHKPsN.js";import{X as re,al as Dt,z as Gt,am as Qt,an as Wt,a0 as Yt,j as Xt,ao as Jt,P as Zt,ap as es}from"./vendor-icons-en0_uSRD.js";import{u as Te,C as ts,r as ss,B as as,a as ns}from"./BulkAssignModal-CmLVxkz-.js";import{E as is}from"./EscalationTitleSelect-CT7mYHkb.js";import{u as ls,E as rs,a as os,t as cs}from"./EscalationTimeline-CLvSr1SD.js";import{m as ds,E as us,a as ms}from"./escalation-columns-Bvo6JI4Z.js";import{u as xs}from"./useFilterParams-DBRw1Hcv.js";import{u as hs}from"./useDebouncedValue-CgO0TGMd.js";import{D as gs}from"./DataTable-FjFhx0SE.js";import{S as fs}from"./StickyPagination-miUdVAKw.js";import{P as ps}from"./constants-CeBBTzf5.js";import{R as bs,a as ys}from"./RowActions-Bdd7z4eB.js";import{i as js}from"./validate-CAin6WM_.js";import"./escalation-items-DFGRwo49.js";import"./UserName-DKXnK7DD.js";import"./EntityTimelinePanel-DJN_ZEQa.js";import"./FilterBar-Dy0b7wwf.js";import"./PriorityBadge-r33mpDju.js";import"./RolePill-D3hkAdKf.js";import"./WorkflowPill-CKHip3hH.js";import"./CountdownTimer-CuPY7zkb.js";import"./EmptyState-DgC_6njU.js";import"./useContainerWidth-DSLp1gEm.js";import"./StatusBadge-DHVwxre2.js";function vs(){const{pathname:t,search:n}=Re(),u=Ee(),{resolveUrl:l}=ut();m.useEffect(()=>{const g=t+n;if(mt(g).length===0)return;const p=l(g);p!==g&&u(p,{replace:!0})},[t,n,l,u])}const Cs=["<","<=",">",">=","="],ks=["priority","created_at","updated_at","status","role"],O="input text-xs py-1",Ne="select text-xs py-1",H="text-text-tertiary hover:text-text-primary transition-colors";function we(t){return t==="true"?!0:t==="false"?!1:t.trim()!==""&&!Number.isNaN(Number(t))?Number(t):t}const Ns=t=>Object.entries(t??{}).map(([n,u])=>({key:n,value:String(u)})),ws=t=>(t??[]).map(n=>{const[u,l]=Object.entries(n)[0]??["",""];return{key:u,value:String(l)}});function A({title:t,hint:n,children:u}){return e.jsxs("div",{className:"border-t border-surface-border/50 py-3 first:border-t-0 first:pt-1",children:[e.jsxs("div",{className:"mb-1.5 flex items-baseline justify-between",children:[e.jsx("span",{className:"text-2xs font-medium uppercase tracking-wide text-text-tertiary",children:t}),n&&e.jsx("span",{className:"text-2xs font-mono text-text-tertiary/70",children:n})]}),u]})}function K({value:t,onChange:n,placeholder:u}){return e.jsx("input",{list:"lt-facet-keys",className:`${O} w-40`,placeholder:u,value:t,onChange:l=>n(l.target.value)})}function Ps({value:t,onChange:n,facetKeys:u=[],search:l="",onSearchChange:g}){const p=Ns(t.facets),b=ws(t.block),f=t.range??[],r=t.exists??[],k=t.orderBy??[],P=a=>{const o={};for(const c of a)c.key&&(o[c.key]=we(c.value));n({...t,facets:Object.keys(o).length?o:void 0})},E=a=>{const o=a.filter(c=>c.key).map(c=>({[c.key]:we(c.value)}));n({...t,block:o.length?o:void 0})},T=a=>n({...t,range:a.length?a:void 0}),y=a=>n({...t,exists:a.length?a:void 0}),v=a=>n({...t,orderBy:a.length?a:void 0});return e.jsxs("div",{className:"text-xs",children:[e.jsx("datalist",{id:"lt-facet-keys",children:u.map(a=>e.jsx("option",{value:a},a))}),e.jsxs("datalist",{id:"lt-sort-fields",children:[ks.map(a=>e.jsx("option",{value:a},a)),u.map(a=>e.jsx("option",{value:`metadata.${a}`},a))]}),g&&e.jsx(A,{title:"Match id",hint:"id · workflow · origin",children:e.jsx("input",{className:`${O} w-full`,placeholder:"Exact escalation, workflow, or origin id…",value:l,onChange:a=>g(a.target.value)})}),e.jsx(A,{title:"Has facet",hint:"metadata @>",children:[...p,{key:"",value:""}].map((a,o)=>e.jsxs("div",{className:"mb-1 flex items-center gap-1",children:[e.jsx(K,{value:a.key,placeholder:"key",onChange:c=>{const i=[...p];i[o]={...a,key:c},P(i)}}),e.jsx("span",{className:"text-text-tertiary",children:"="}),e.jsx("input",{className:`${O} w-40`,placeholder:"value",value:a.value,onChange:c=>{const i=[...p];i[o]={...a,value:c.target.value},P(i)}}),o<p.length&&e.jsx("button",{className:H,onClick:()=>P(p.filter((c,i)=>i!==o)),children:"×"})]},o))}),e.jsx(A,{title:"Range",hint:"numeric",children:[...f,{facet:"",op:"<=",value:0}].map((a,o)=>e.jsxs("div",{className:"mb-1 flex items-center gap-1",children:[e.jsx(K,{value:a.facet,placeholder:"numeric facet",onChange:c=>{const i=[...f];i[o]={...a,facet:c},T(i.filter(j=>j.facet))}}),e.jsx("select",{className:Ne,value:a.op,onChange:c=>{const i=[...f];i[o]={...a,op:c.target.value},T(i.filter(j=>j.facet))},children:Cs.map(c=>e.jsx("option",{value:c,children:c},c))}),e.jsx("input",{type:"number",className:`${O} w-24`,value:a.value,onChange:c=>{const i=[...f];i[o]={...a,value:Number(c.target.value)},T(i.filter(j=>j.facet))}}),o<f.length&&e.jsx("button",{className:H,onClick:()=>T(f.filter((c,i)=>i!==o)),children:"×"})]},o))}),e.jsx(A,{title:"Has key",hint:"metadata ? key",children:e.jsxs("div",{className:"flex flex-wrap items-center gap-1",children:[r.map(a=>e.jsxs("span",{className:"flex items-center gap-1 rounded bg-accent/15 px-1.5 py-0.5 text-accent",children:[a,e.jsx("button",{className:"text-accent/70 hover:text-accent",onClick:()=>y(r.filter(o=>o!==a)),children:"×"})]},a)),e.jsx(K,{value:"",placeholder:"+ key",onChange:a=>{a&&!r.includes(a)&&y([...r,a])}})]})}),e.jsx(A,{title:"Exclude",hint:"NOT @>",children:[...b,{key:"",value:""}].map((a,o)=>e.jsxs("div",{className:"mb-1 flex items-center gap-1",children:[e.jsx(K,{value:a.key,placeholder:"key",onChange:c=>{const i=[...b];i[o]={...a,key:c},E(i)}}),e.jsx("span",{className:"text-text-tertiary",children:"="}),e.jsx("input",{className:`${O} w-40`,placeholder:"value",value:a.value,onChange:c=>{const i=[...b];i[o]={...a,value:c.target.value},E(i)}}),o<b.length&&e.jsx("button",{className:H,onClick:()=>E(b.filter((c,i)=>i!==o)),children:"×"})]},o))}),e.jsx(A,{title:"Sort by",children:[...k,{field:"",direction:"asc"}].map((a,o)=>e.jsxs("div",{className:"mb-1 flex items-center gap-1",children:[e.jsx("input",{list:"lt-sort-fields",className:`${O} w-44`,placeholder:"column or metadata.key",value:a.field,onChange:c=>{const i=[...k];i[o]={...a,field:c.target.value},v(i.filter(j=>j.field))}}),e.jsxs("select",{className:Ne,value:a.direction??"asc",onChange:c=>{const i=[...k];i[o]={...a,direction:c.target.value},v(i.filter(j=>j.field))},children:[e.jsx("option",{value:"asc",children:"asc"}),e.jsx("option",{value:"desc",children:"desc"})]}),e.jsxs("label",{className:"flex items-center gap-1 text-text-tertiary",children:[e.jsx("input",{type:"checkbox",checked:!!a.numeric,onChange:c=>{const i=[...k];i[o]={...a,numeric:c.target.checked},v(i.filter(j=>j.field))}}),"num"]}),o<k.length&&e.jsx("button",{className:H,onClick:()=>v(k.filter((c,i)=>i!==o)),children:"×"})]},o))})]})}function Ss({value:t,onChange:n,facetKeys:u,search:l,onSearchChange:g,activeFacetCount:p,onClear:b,onClose:f}){return e.jsxs("div",{className:"h-full overflow-y-auto",children:[e.jsxs("div",{className:"sticky top-0 z-10 flex items-center justify-between px-4 py-3 bg-surface-raised border-b border-surface-border/50",children:[e.jsx("span",{className:"text-xs font-semibold text-text-primary",children:"Faceted query"}),e.jsxs("div",{className:"flex items-center gap-2",children:[p>0&&e.jsx("button",{onClick:b,className:"text-2xs text-text-tertiary hover:text-text-primary transition-colors",children:"Clear"}),e.jsx("button",{onClick:f,className:"p-1 rounded hover:bg-surface-hover text-text-tertiary hover:text-text-primary transition-colors",title:"Close",children:e.jsx(re,{className:"w-4 h-4"})})]})]}),e.jsxs("div",{className:"px-4 py-2",children:[e.jsxs("p",{className:"mb-2 text-2xs leading-snug text-text-tertiary",children:["Precise metadata facets plus exact correlation-id lookup — they compose in one SQL query. Facet keys are the ones that actually exist in your visible escalations. Set status to ",e.jsx("span",{className:"font-medium",children:"All"})," to find an order across every status; the whole query is shareable via the URL."]}),e.jsx(Ps,{value:t,onChange:n,facetKeys:u,search:l,onSearchChange:g})]})]})}const Rs=t=>t.isPriorityPending||t.isClaimPending||t.isAssignPending||t.isUnassignPending||t.isTriagePending||t.isCancelPending,D="inline-flex items-center h-7 px-2.5 text-2xs font-medium text-text-secondary bg-surface border border-surface-border rounded-[4px] hover:border-accent/50 hover:text-text-primary transition-colors disabled:opacity-50 disabled:hover:border-surface-border",Pe=`${D} appearance-none cursor-pointer`,Es="inline-flex items-center h-7 px-2.5 text-2xs font-medium text-status-error bg-surface border border-status-error/30 rounded-[4px] hover:border-status-error hover:bg-status-error/5 transition-colors disabled:opacity-50";function Ts(t){var f;const n=Rs(t),u=Te(),{data:l}=xt(),g=ht(),p=g!==null?g:((f=l==null?void 0:l.ai)==null?void 0:f.enabled)===!0,b=t.selectedCount>0;return e.jsx("div",{className:`grid transition-all duration-200 ease-in-out ${b?"grid-rows-[1fr] opacity-100":"grid-rows-[0fr] opacity-0 pointer-events-none"}`,children:e.jsx("div",{className:"overflow-hidden",children:e.jsxs("div",{className:"flex flex-wrap items-center gap-2 py-2.5 pl-3 pr-2 mt-4 mb-3 bg-surface-sunken/60 border-l-2 border-l-accent",children:[e.jsxs("span",{className:"text-2xs font-semibold uppercase tracking-wider text-accent tabular-nums",children:[t.selectedCount," selected"]}),e.jsx("div",{className:"mx-1 h-4 w-px bg-surface-border"}),e.jsxs("select",{onChange:r=>{r.target.value&&(t.onSetPriority(parseInt(r.target.value)),r.target.value="")},disabled:n,className:Pe,defaultValue:"",children:[e.jsx("option",{value:"",disabled:!0,children:"Priority…"}),ps.map(r=>e.jsx("option",{value:r.value,children:r.label},r.value))]}),e.jsxs("select",{onChange:r=>{r.target.value&&(t.onClaim(parseInt(r.target.value)),r.target.value="")},disabled:n,className:Pe,defaultValue:"",children:[e.jsx("option",{value:"",disabled:!0,children:"Claim for…"}),u.map(r=>e.jsx("option",{value:r.value,children:r.label},r.value))]}),e.jsx("button",{onClick:t.onAssign,disabled:n,className:D,children:t.isAssignPending?"Assigning…":"Assign to…"}),e.jsx("button",{onClick:t.onUnassign,disabled:n,className:D,children:t.isUnassignPending?"Unassigning…":"Unassign"}),p&&e.jsx("button",{onClick:t.onTriage,disabled:n,className:D,children:t.isTriagePending?"Triaging…":"Triage"}),t.cancelLabel!==!1&&e.jsx("button",{onClick:t.onCancel,disabled:n,className:Es,children:t.isCancelPending?t.cancelLabel?`${t.cancelLabel}…`:"Cancelling…":t.cancelLabel||"Cancel"}),e.jsx("div",{className:"flex-1"}),n&&e.jsx("span",{className:"text-2xs text-text-tertiary animate-pulse",children:"Processing…"}),e.jsx("button",{onClick:t.onClearSelection,className:"px-1 text-2xs font-medium text-text-tertiary hover:text-text-primary transition-colors",children:"Clear"})]})})})}function As({open:t,onClose:n,selectedCount:u,onSubmit:l,isPending:g}){const[p,b]=m.useState(""),f=()=>{l(p||void 0)};return e.jsx(Se,{open:t,onClose:n,title:"Submit for AI Triage",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("p",{className:"text-sm text-text-secondary",children:["Submit ",e.jsx("span",{className:"font-medium text-text-primary",children:u})," escalation(s) for AI triage? The triage orchestrator will take over resolution."]}),e.jsxs("div",{children:[e.jsxs("label",{className:"text-xs font-medium text-text-secondary block mb-1",children:["Triage hint ",e.jsx("span",{className:"text-text-tertiary",children:"(optional)"})]}),e.jsx("input",{type:"text",value:p,onChange:r=>b(r.target.value),placeholder:"e.g., image_orientation",className:"input text-xs font-mono w-full"}),e.jsx("p",{className:"text-2xs text-text-tertiary mt-1",children:"Guides the triage workflow on what remediation to apply"})]}),e.jsxs("div",{className:"flex justify-end gap-3 pt-2",children:[e.jsx("button",{onClick:n,className:"btn-secondary text-xs",children:"Cancel"}),e.jsx("button",{onClick:f,disabled:g,className:"btn-primary text-xs",children:g?"Submitting...":"Submit for Triage"})]})]})})}function B(t,n,u){return l=>{t.mutate(l,{onSuccess:()=>{n(),u==null||u()}})}}function Bs(t){const n=()=>[...t.selectedIds];return{handleSetPriority:r=>{B(t.setPriority,t.clearSelection)({ids:n(),priority:r})},handleBulkClaim:r=>{B(t.bulkClaim,t.clearSelection)({ids:n(),durationMinutes:r})},handleBulkTriage:r=>{B(t.bulkTriage,t.clearSelection,t.closeTriageModal)({ids:n(),hint:r})},handleBulkAssign:(r,k,P)=>{B(t.bulkAssign,t.clearSelection,t.closeAssignModal)({ids:n(),targetUserId:r,durationMinutes:k,reassign:P})},handleBulkUnassign:()=>{B(t.bulkUnassign,t.clearSelection)({ids:n()})},handleBulkCancel:()=>{B(t.bulkCancel,t.clearSelection,t.closeCancelModal)({ids:n()})}}}function Os({claimTarget:t,onClose:n,claimDuration:u,onDurationChange:l,claimDurations:g,onCustomClaimChange:p,onClaim:b,isPending:f}){return e.jsx(Se,{open:!!t,onClose:n,title:"Claim Escalation",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("p",{className:"text-sm text-text-secondary",children:["Claim ",e.jsx("span",{className:"font-medium text-text-primary",children:t==null?void 0:t.type})," for:"]}),e.jsxs("select",{value:u,onChange:r=>{l(r.target.value)},className:"select w-full text-sm",children:[g.map(r=>e.jsx("option",{value:r.value,children:r.label},r.value)),e.jsx("option",{value:"custom",children:"Other..."})]}),u==="custom"&&e.jsx(ts,{onChange:p,autoFocus:!0}),e.jsxs("div",{className:"flex justify-end gap-3 pt-2",children:[e.jsx("button",{onClick:n,className:"btn-secondary text-xs",children:"Cancel"}),e.jsx("button",{onClick:b,className:"btn-primary text-xs",disabled:f,children:f?"Claiming...":"Claim"})]})]})})}function ra(){var ke;vs();const t=Ee(),{filters:n,setFilter:u,pagination:l}=xs({filters:{role:"",type:"",subtype:"",priority:"",status:"available",search:""}});gt({role:n.role||null,verbs:["created","claimed","updated"]});const g=hs(n.search),p=Te(),[b,f]=m.useState(null),[r,k]=m.useState("30"),[P,E]=m.useState(0),T=m.useCallback(s=>E(s),[]),[y,v]=m.useState(new Set),a=m.useRef(null),o=m.useRef(null),c=m.useCallback(s=>{var x;if((x=o.current)==null||x.disconnect(),o.current=null,!s||typeof ResizeObserver>"u")return;const d=new ResizeObserver(()=>{var q;(q=a.current)==null||q.style.setProperty("--lt-sticky-top",`${s.offsetHeight-1}px`)});d.observe(s),o.current=d},[]),[i,j]=m.useState(!1),[L,M]=Ht(),h=m.useMemo(()=>ft(L),[L]),N=m.useCallback(s=>{M(d=>{const x=new URLSearchParams(d);return pt(x,s),x.delete("page"),x})},[M]),{data:F}=bt(i),z=yt(h)+(n.search?1:0),G="facet-query",{setPanel:oe,closePanel:ce,open:Ae,ownerKey:Be}=jt();m.useEffect(()=>{if(!i){ce(G);return}oe(e.jsx(Ss,{value:h,onChange:N,facetKeys:(F==null?void 0:F.keys)??[],search:n.search??"",onSearchChange:s=>u("search",s),activeFacetCount:z,onClear:()=>{N({}),u("search","")},onClose:()=>j(!1)}),{width:420,key:G})},[i,h,N,F,n.search,u,z,oe,ce]);const de=Ae&&Be===G,Q=m.useRef(!1);m.useEffect(()=>{if(de){Q.current=!0;return}Q.current&&(Q.current=!1,j(!1))},[de]);const[Oe,W]=m.useState(!1),[Le,Y]=m.useState(!1),[Me,X]=m.useState(!1),Fe=m.useCallback(s=>N({...h,orderBy:s}),[h,N]),I=Re(),{data:U}=vt(),ue=Ct(),ze=m.useCallback(()=>{var x;const s=window.prompt("Pin label:");if(!(s!=null&&s.trim()))return;const d=((x=U==null?void 0:U.preferences)==null?void 0:x.pinnedViews)??[];ue.mutate({pinnedViews:[...d,{id:kt(),label:s.trim(),url:I.pathname+I.search,badge:!0}]})},[I.pathname,I.search,U,ue]),{canBulk:Ie}=Nt(),{kiosk:J}=wt(),me=h.facets?Object.keys(h.facets):[],Ue=L.get("view"),Ve=m.useCallback(s=>{M(d=>{const x=new URLSearchParams(d);return s?x.set("view",s):x.delete("view"),x},{replace:!0})},[M]),Z=Ue==="timeline",$e=m.useCallback(s=>{const{[s]:d,...x}=h.facets??{};N({...h,facets:Object.keys(x).length>0?x:void 0})},[h,N]),xe=Pt(),he=St(),ge=Rt(),ee=Et(),fe=Tt(),te=At(),V=Bt(),{data:se}=Ot(),{data:S}=Lt(),{data:ae}=Mt(),{user:$,isSuperAdmin:_e,hasRoleType:qe}=Ft(),pe=_e||qe("admin"),be=m.useMemo(()=>new Set((($==null?void 0:$.roles)??[]).map(s=>s.role)),[$]),He=m.useMemo(()=>{const s=(S==null?void 0:S.roles)??[];return(pe?s:s.filter(x=>be.has(x.role)&&!Kt(x.role))).map(x=>({value:x.role,label:zt(x)})).sort((x,q)=>x.label.localeCompare(q.label))},[S,pe,be]);m.useEffect(()=>{v(new Set)},[n.role,n.type,n.subtype,n.priority,n.status,g,l.page,l.pageSize]);const ne=m.useMemo(()=>({...It(L,_t.AVAILABLE),search:g||void 0}),[L,g]),ye=100,{escalations:C,total:w,groups:Ke,listSchema:De,listSchemaVersion:Ge,singleRole:R,hasRichView:je,isLoading:Qe,isFetching:ve,error:_,refetch:We}=ls(ne,{limit:Z?ye:l.pageSize,offset:l.offset}),Ye=Ut(R??"",void 0,!!R),ie=R?ss((ke=Ye.data)==null?void 0:ke.form_schema).cancel:void 0,le=Vt(ne.view,je),Xe=le===qt.RICH,Ce=m.useMemo(()=>{if(!h.jeopardy||!R)return null;const s=((S==null?void 0:S.roles)??[]).find(x=>x.role===R),d=(s==null?void 0:s.priority_threshold_minutes)??(s==null?void 0:s.sla_minutes)??null;return d!=null?$t(d*6e4):null},[h.jeopardy,R,S]),Je=m.useMemo(()=>{const s=new Set;for(const d of C)y.has(d.id)&&s.add(d.role);return[...s]},[C,y]),Ze=m.useMemo(()=>C.filter(s=>y.has(s.id)&&js(s)).length,[C,y]),et=m.useCallback(()=>v(new Set),[]),tt=()=>{if(!b)return;const s=r==="custom"?P:parseInt(r);!s||s<=0||xe.mutate({id:b.id,durationMinutes:s},{onSuccess:()=>{f(null),t(`/escalations/detail/${b.id}`)}})},{handleSetPriority:st,handleBulkClaim:at,handleBulkTriage:nt,handleBulkAssign:it,handleBulkUnassign:lt,handleBulkCancel:rt}=Bs({selectedIds:y,clearSelection:et,setPriority:he,bulkClaim:ge,bulkTriage:te,bulkAssign:ee,bulkUnassign:fe,bulkCancel:V,closeTriageModal:()=>W(!1),closeAssignModal:()=>Y(!1),closeCancelModal:()=>X(!1)}),ot=s=>{const d=new Set(y);d.has(s)?d.delete(s):d.add(s),v(d)},ct=()=>{y.size===C.length?v(new Set):v(new Set(C.map(s=>s.id)))},dt=[Ie?{key:"select",label:e.jsx("input",{type:"checkbox",checked:C.length>0&&y.size===C.length,onChange:ct,className:"rounded"}),render:s=>e.jsx("input",{type:"checkbox",checked:y.has(s.id),onChange:d=>{d.stopPropagation(),ot(s.id)},onClick:d=>d.stopPropagation(),className:"rounded"}),className:"w-10",priority:1}:{key:"spacer",label:"",render:()=>null,className:"w-10",priority:3},...ds({highlightKeys:me}),{key:"actions",label:"",render:s=>e.jsx(bs,{children:e.jsx(ys,{icon:Dt,title:"Claim escalation",onClick:()=>f(s),alwaysVisible:!0,colorClass:"text-accent/40 hover:text-accent",size:"sm"})}),className:"w-10 text-right"}];return e.jsxs("div",{ref:a,children:[e.jsxs("div",{className:"flex items-center gap-2 mb-10 min-w-0",children:[e.jsx(is,{role:n.role,options:He,onChange:s=>u("role",s),locked:J}),!J&&e.jsx("button",{onClick:()=>{window.location.hash="#docs:dashboard.md:all-escalations"},className:"text-text-quaternary hover:text-accent transition-colors mt-1 shrink-0",title:"Open docs for this page",children:e.jsx(Gt,{className:"w-4 h-4",strokeWidth:1.5})})]}),e.jsxs("div",{ref:c,className:"sticky top-0 z-20 bg-surface",children:[e.jsx(us,{filters:n,setFilter:u,roles:(se==null?void 0:se.roles)??[],types:(ae==null?void 0:ae.types)??[],showStatus:!0,showSearch:!1,showRole:!J,actions:e.jsxs(e.Fragment,{children:[Z&&e.jsxs("span",{className:"text-2xs text-text-tertiary whitespace-nowrap",children:[w>100&&e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"font-medium text-text-secondary",children:[(l.page-1)*100+1,"–",Math.min(l.page*100,w)]})," of "]}),e.jsx("span",{className:"font-medium text-text-secondary",children:w})," ",w===1?"escalation":"escalations"]}),e.jsx(rs,{orderBy:h.orderBy,onChange:Fe}),e.jsx("div",{role:"radiogroup","aria-label":"List view",className:"flex items-center rounded overflow-hidden border border-surface-border",children:[{key:"table",title:"Table view",Icon:Qt},{key:"rich",title:"Rich view",Icon:Wt},{key:"timeline",title:"Timeline view",Icon:Yt}].filter(s=>s.key!=="rich"||je).map(({key:s,title:d,Icon:x})=>e.jsx("button",{role:"radio","aria-checked":le===s,onClick:()=>Ve(s),className:`px-1.5 py-1 transition-colors ${le===s?"bg-accent text-text-inverse":"icon-link hover:bg-surface-hover"}`,title:d,children:e.jsx(x,{className:"w-3.5 h-3.5"})},s))}),e.jsxs("button",{onClick:()=>j(s=>!s),"aria-pressed":i,className:`relative rounded border border-surface-border px-1.5 py-1 transition-colors ${i?"bg-accent text-text-inverse":"icon-link hover:bg-surface-hover"}`,title:"Faceted query",children:[e.jsx(Xt,{className:"w-3.5 h-3.5"}),z>0&&e.jsx("span",{className:"absolute -right-1 -top-1 flex h-3.5 min-w-[14px] items-center justify-center rounded-full bg-accent px-0.5 text-2xs font-medium text-text-inverse",children:z})]}),e.jsxs("div",{className:"flex items-center gap-0.5",children:[e.jsx("button",{onClick:()=>We(),disabled:ve,className:"inline-flex h-7 w-7 items-center justify-center rounded icon-link hover:bg-surface-hover disabled:opacity-50",title:"Refresh",children:e.jsx(Jt,{className:`w-4 h-4 ${ve?"animate-spin":""}`})}),e.jsx("button",{onClick:ze,className:"inline-flex h-7 w-7 items-center justify-center rounded icon-link hover:bg-surface-hover",title:"Pin this view — save the current filters to your Pinned section","data-testid":"pin-current-view",children:e.jsx(Zt,{className:"w-4 h-4"})})]})]})}),e.jsx(Ts,{selectedCount:y.size,onClearSelection:()=>v(new Set),onSetPriority:st,onClaim:at,onAssign:()=>Y(!0),onUnassign:lt,onTriage:()=>W(!0),onCancel:()=>X(!0),isPriorityPending:he.isPending,isClaimPending:ge.isPending,isAssignPending:ee.isPending,isUnassignPending:fe.isPending,isTriagePending:te.isPending,isCancelPending:V.isPending,cancelLabel:ie}),(h.facets&&Object.keys(h.facets).length>0||h.jeopardy)&&e.jsxs("div",{className:"bg-surface/98 backdrop-blur-sm border-b border-surface-border/30 -mx-page-x px-page-x py-2 flex items-center gap-1.5 flex-wrap",children:[h.jeopardy&&e.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full bg-status-error px-2.5 py-0.5 text-2xs font-semibold text-text-inverse",children:[e.jsx(es,{className:"w-2.5 h-2.5",strokeWidth:2.5}),"in jeopardy",Ce&&e.jsxs("span",{className:"font-mono font-normal opacity-90",children:["> ",Ce]}),e.jsx("button",{onClick:()=>N({...h,jeopardy:void 0}),className:"ml-0.5 -mr-0.5 flex items-center text-text-inverse/70 hover:text-text-inverse transition-colors","aria-label":"Clear jeopardy filter",children:e.jsx(re,{className:"w-2.5 h-2.5"})})]}),Object.entries(h.facets??{}).map(([s,d])=>e.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full border border-accent/25 bg-accent/8 px-2.5 py-0.5 text-2xs font-medium text-accent/90",children:[e.jsx("span",{className:"font-mono text-text-tertiary",children:s}),e.jsx("span",{className:"text-text-quaternary",children:"="}),e.jsx("span",{className:"font-mono max-w-[160px] truncate",title:String(d),children:String(d)}),e.jsx("button",{onClick:()=>$e(s),className:"ml-0.5 -mr-0.5 flex items-center text-text-quaternary hover:text-status-error transition-colors","aria-label":`Remove ${s} filter`,children:e.jsx(re,{className:"w-2.5 h-2.5"})})]},s)),Object.keys(h.facets??{}).length>1&&e.jsx("button",{onClick:()=>N({...h,facets:void 0}),className:"text-2xs text-text-quaternary hover:text-text-secondary transition-colors px-1",children:"clear all"})]})]}),_&&e.jsx("div",{className:"mb-4 px-4 py-3 rounded-md bg-status-error/10 border border-status-error/20 text-xs text-status-error",children:_.message==="Session expired"?"Your session has expired. Please log in again.":`Failed to load escalations: ${_.message}`}),Z?e.jsx(os,{escalations:C,highlightKeys:me,onRowClick:s=>t(`/escalations/detail/${s.id}`,{state:{from:"/escalations/available"}}),total:w,page:l.page,totalPages:Math.ceil(w/ye),onPageChange:l.setPage}):Xe?e.jsx(ms,{role:R,listSchema:De,listSchemaVersion:Ge,activeEscalations:C,groups:Ke,onRowClick:s=>t(`/escalations/detail/${s.id}`,{state:{from:"/escalations/available"}}),onOpenGroup:s=>t(s),onAddFacet:(s,d)=>N({...h,facets:{...h.facets??{},[s]:typeof d=="object"&&d!==null?JSON.stringify(d):d}}),total:w,page:l.page,totalPages:l.totalPages(w),pageSize:l.pageSize,onPageChange:l.setPage,onPageSizeChange:l.setPageSize}):e.jsxs(e.Fragment,{children:[e.jsx(gs,{columns:dt,data:C,layout:"fixed",...cs(ne.layout),keyFn:s=>s.id,onRowClick:s=>t(`/escalations/detail/${s.id}`,{state:{from:"/escalations/available"}}),isLoading:Qe,emptyMessage:_?"Unable to load data":"No escalations"}),e.jsx(fs,{page:l.page,totalPages:l.totalPages(w),onPageChange:l.setPage,total:w,pageSize:l.pageSize,onPageSizeChange:l.setPageSize})]}),e.jsx(Os,{claimTarget:b,onClose:()=>f(null),claimDuration:r,onDurationChange:s=>{k(s),E(0)},claimDurations:p,customClaimMinutes:P,onCustomClaimChange:T,onClaim:tt,isPending:xe.isPending}),e.jsx(As,{open:Oe,onClose:()=>W(!1),selectedCount:y.size,onSubmit:nt,isPending:te.isPending}),e.jsx(as,{open:Le,onClose:()=>Y(!1),selectedCount:y.size,selectedRoles:Je,claimedCount:Ze,onSubmit:it,isPending:ee.isPending}),e.jsx(ns,{open:Me,onClose:()=>X(!1),onConfirm:rt,selectedCount:y.size,isPending:V.isPending,error:V.error,actionLabel:typeof ie=="string"?ie:void 0})]})}export{ra as AvailableEscalationsPage};
2
- //# sourceMappingURL=AvailableEscalationsPage-GFn8Sgg1.js.map