@hotmeshio/long-tail 0.30.5 → 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 (367) hide show
  1. package/build/api/labels/errors.d.ts +3 -0
  2. package/build/api/labels/errors.js +15 -0
  3. package/build/api/labels/index.d.ts +2 -0
  4. package/build/api/labels/index.js +17 -0
  5. package/build/api/labels/issue.d.ts +54 -0
  6. package/build/api/labels/issue.js +144 -0
  7. package/build/api/labels/templates.d.ts +29 -0
  8. package/build/api/labels/templates.js +98 -0
  9. package/build/api/users.d.ts +8 -4
  10. package/build/api/users.js +51 -13
  11. package/build/index.d.ts +1 -0
  12. package/build/index.js +4 -2
  13. package/build/lib/db/schemas/044_label_sheets.sql +65 -0
  14. package/build/lib/db/schemas/045_label_job_delivery.sql +14 -0
  15. package/build/lib/labels/transports.d.ts +23 -0
  16. package/build/lib/labels/transports.js +39 -0
  17. package/build/modules/auth.d.ts +2 -0
  18. package/build/modules/auth.js +3 -1
  19. package/build/modules/capabilities.d.ts +5 -1
  20. package/build/modules/capabilities.js +38 -8
  21. package/build/modules/config.d.ts +10 -0
  22. package/build/modules/config.js +10 -0
  23. package/build/routes/index.js +2 -0
  24. package/build/routes/labels.d.ts +2 -0
  25. package/build/routes/labels.js +135 -0
  26. package/build/routes/users.js +1 -1
  27. package/build/services/labels/content.d.ts +13 -0
  28. package/build/services/labels/content.js +81 -0
  29. package/build/services/labels/errors.d.ts +5 -0
  30. package/build/services/labels/errors.js +12 -0
  31. package/build/services/labels/index.d.ts +11 -0
  32. package/build/services/labels/index.js +52 -0
  33. package/build/services/labels/issue.d.ts +38 -0
  34. package/build/services/labels/issue.js +181 -0
  35. package/build/services/labels/jobs.d.ts +37 -0
  36. package/build/services/labels/jobs.js +75 -0
  37. package/build/services/labels/media.d.ts +11 -0
  38. package/build/services/labels/media.js +44 -0
  39. package/build/services/labels/reissue.d.ts +13 -0
  40. package/build/services/labels/reissue.js +65 -0
  41. package/build/services/labels/render-pdf.d.ts +11 -0
  42. package/build/services/labels/render-pdf.js +138 -0
  43. package/build/services/labels/targets.d.ts +18 -0
  44. package/build/services/labels/targets.js +216 -0
  45. package/build/services/labels/templates/index.d.ts +3 -0
  46. package/build/services/labels/templates/index.js +18 -0
  47. package/build/services/labels/templates/read.d.ts +4 -0
  48. package/build/services/labels/templates/read.js +36 -0
  49. package/build/services/labels/templates/sql.d.ts +8 -0
  50. package/build/services/labels/templates/sql.js +50 -0
  51. package/build/services/labels/templates/validate.d.ts +19 -0
  52. package/build/services/labels/templates/validate.js +93 -0
  53. package/build/services/labels/templates/write.d.ts +16 -0
  54. package/build/services/labels/templates/write.js +75 -0
  55. package/build/services/labels/token.d.ts +9 -0
  56. package/build/services/labels/token.js +28 -0
  57. package/build/services/labels/verify.d.ts +4 -0
  58. package/build/services/labels/verify.js +38 -0
  59. package/build/services/scan-code/validate.d.ts +3 -0
  60. package/build/services/scan-code/validate.js +10 -0
  61. package/build/services/user/crud.d.ts +13 -1
  62. package/build/services/user/crud.js +42 -11
  63. package/build/services/user/index.d.ts +3 -2
  64. package/build/services/user/index.js +7 -1
  65. package/build/services/user/redact.d.ts +17 -0
  66. package/build/services/user/redact.js +32 -0
  67. package/build/services/user/sql.d.ts +8 -15
  68. package/build/services/user/sql.js +27 -3
  69. package/build/services/user/types.d.ts +21 -1
  70. package/build/shared/labels/compose.d.ts +12 -0
  71. package/build/shared/labels/compose.js +43 -0
  72. package/build/shared/labels/index.d.ts +9 -0
  73. package/build/shared/labels/index.js +54 -0
  74. package/build/shared/labels/label-content.d.ts +17 -0
  75. package/build/shared/labels/label-content.js +137 -0
  76. package/build/shared/labels/layout.d.ts +23 -0
  77. package/build/shared/labels/layout.js +81 -0
  78. package/build/shared/labels/media.d.ts +22 -0
  79. package/build/shared/labels/media.js +116 -0
  80. package/build/shared/labels/render-svg.d.ts +10 -0
  81. package/build/shared/labels/render-svg.js +58 -0
  82. package/build/shared/labels/render-zpl.d.ts +9 -0
  83. package/build/shared/labels/render-zpl.js +63 -0
  84. package/build/shared/labels/symbol.d.ts +18 -0
  85. package/build/shared/labels/symbol.js +74 -0
  86. package/build/shared/labels/tokens.d.ts +18 -0
  87. package/build/shared/labels/tokens.js +43 -0
  88. package/build/shared/labels/types.d.ts +105 -0
  89. package/build/shared/labels/types.js +11 -0
  90. package/build/start/adapters.js +16 -0
  91. package/build/start/workers.js +18 -2
  92. package/build/system/mcp-servers/admin/index.js +2 -0
  93. package/build/system/mcp-servers/admin/labels-schemas.d.ts +192 -0
  94. package/build/system/mcp-servers/admin/labels-schemas.js +46 -0
  95. package/build/system/mcp-servers/admin/labels.d.ts +9 -0
  96. package/build/system/mcp-servers/admin/labels.js +101 -0
  97. package/build/system/mcp-servers/admin/schemas.d.ts +30 -30
  98. package/build/system/mcp-servers/admin/users.js +1 -1
  99. package/build/system/seed/tool-manifests-admin.js +5 -0
  100. package/build/tsconfig.tsbuildinfo +1 -1
  101. package/build/types/capability.d.ts +2 -1
  102. package/build/types/index.d.ts +2 -1
  103. package/build/types/labels/index.d.ts +4 -0
  104. package/build/types/labels/index.js +2 -0
  105. package/build/types/labels/job.d.ts +51 -0
  106. package/build/types/labels/job.js +2 -0
  107. package/build/types/labels/source.d.ts +44 -0
  108. package/build/types/labels/source.js +2 -0
  109. package/build/types/labels/template.d.ts +46 -0
  110. package/build/types/labels/template.js +2 -0
  111. package/build/types/labels/transport.d.ts +24 -0
  112. package/build/types/labels/transport.js +2 -0
  113. package/build/types/scan-code/rule.d.ts +5 -0
  114. package/build/types/startup.d.ts +37 -0
  115. package/build/types/user.d.ts +2 -0
  116. package/dashboard/dist/assets/{AdminDashboard-D12QiMM5.js → AdminDashboard-BafKaq50.js} +2 -2
  117. package/dashboard/dist/assets/{AdminDashboard-D12QiMM5.js.map → AdminDashboard-BafKaq50.js.map} +1 -1
  118. package/dashboard/dist/assets/{AgentConfigPage-BKQd9b8m.js → AgentConfigPage-CFHf31DT.js} +6 -6
  119. package/dashboard/dist/assets/{AgentConfigPage-BKQd9b8m.js.map → AgentConfigPage-CFHf31DT.js.map} +1 -1
  120. package/dashboard/dist/assets/{AgentDetailPage-ie-DxsIj.js → AgentDetailPage-CEvz5rJr.js} +3 -3
  121. package/dashboard/dist/assets/{AgentDetailPage-ie-DxsIj.js.map → AgentDetailPage-CEvz5rJr.js.map} +1 -1
  122. package/dashboard/dist/assets/{AgentsPage-Nqm2DxCP.js → AgentsPage-DjQaio0O.js} +2 -2
  123. package/dashboard/dist/assets/{AgentsPage-Nqm2DxCP.js.map → AgentsPage-DjQaio0O.js.map} +1 -1
  124. package/dashboard/dist/assets/AvailableEscalationsPage-UB03VTJx.js +2 -0
  125. package/dashboard/dist/assets/AvailableEscalationsPage-UB03VTJx.js.map +1 -0
  126. package/dashboard/dist/assets/{BotPicker-BizdmeJp.js → BotPicker-C7MNWOF7.js} +2 -2
  127. package/dashboard/dist/assets/{BotPicker-BizdmeJp.js.map → BotPicker-C7MNWOF7.js.map} +1 -1
  128. package/dashboard/dist/assets/BulkAssignModal-h5fX-_cV.js +2 -0
  129. package/dashboard/dist/assets/{BulkAssignModal-BWfzPrRk.js.map → BulkAssignModal-h5fX-_cV.js.map} +1 -1
  130. package/dashboard/dist/assets/{CapabilitiesPage-DT8q7Zlh.js → CapabilitiesPage-BIzDl-ZT.js} +2 -2
  131. package/dashboard/dist/assets/{CapabilitiesPage-DT8q7Zlh.js.map → CapabilitiesPage-BIzDl-ZT.js.map} +1 -1
  132. package/dashboard/dist/assets/{CollapsibleSection-al5mqR4O.js → CollapsibleSection-B5TivtEg.js} +2 -2
  133. package/dashboard/dist/assets/{CollapsibleSection-al5mqR4O.js.map → CollapsibleSection-B5TivtEg.js.map} +1 -1
  134. package/dashboard/dist/assets/{ConfirmDeleteModal-BrlVktv2.js → ConfirmDeleteModal-CB4nKePb.js} +2 -2
  135. package/dashboard/dist/assets/{ConfirmDeleteModal-BrlVktv2.js.map → ConfirmDeleteModal-CB4nKePb.js.map} +1 -1
  136. package/dashboard/dist/assets/{ConnectedAppsPage-CLAsJ2yQ.js → ConnectedAppsPage-B3S5gVWw.js} +2 -2
  137. package/dashboard/dist/assets/{ConnectedAppsPage-CLAsJ2yQ.js.map → ConnectedAppsPage-B3S5gVWw.js.map} +1 -1
  138. package/dashboard/dist/assets/{CountdownTimer-D2D68exl.js → CountdownTimer-BHVIq3kA.js} +2 -2
  139. package/dashboard/dist/assets/{CountdownTimer-D2D68exl.js.map → CountdownTimer-BHVIq3kA.js.map} +1 -1
  140. package/dashboard/dist/assets/CredentialConfirmModal-w0AGmCIe.js +2 -0
  141. package/dashboard/dist/assets/CredentialConfirmModal-w0AGmCIe.js.map +1 -0
  142. package/dashboard/dist/assets/{CredentialsPage-DWrZbEI0.js → CredentialsPage-BtCGBJrT.js} +2 -2
  143. package/dashboard/dist/assets/{CredentialsPage-DWrZbEI0.js.map → CredentialsPage-BtCGBJrT.js.map} +1 -1
  144. package/dashboard/dist/assets/{CronLabel-DuXR8iWq.js → CronLabel-BG1rZK-5.js} +2 -2
  145. package/dashboard/dist/assets/{CronLabel-DuXR8iWq.js.map → CronLabel-BG1rZK-5.js.map} +1 -1
  146. package/dashboard/dist/assets/{DropZone-DefYTYQy.js → DropZone-D8ZVdEb5.js} +2 -2
  147. package/dashboard/dist/assets/{DropZone-DefYTYQy.js.map → DropZone-D8ZVdEb5.js.map} +1 -1
  148. package/dashboard/dist/assets/{ElapsedCell-ronqG5-E.js → ElapsedCell-l4m8Yvfv.js} +2 -2
  149. package/dashboard/dist/assets/{ElapsedCell-ronqG5-E.js.map → ElapsedCell-l4m8Yvfv.js.map} +1 -1
  150. package/dashboard/dist/assets/{EntityTimelinePanel-CKsktd84.js → EntityTimelinePanel-BOHlIaxF.js} +2 -2
  151. package/dashboard/dist/assets/{EntityTimelinePanel-CKsktd84.js.map → EntityTimelinePanel-BOHlIaxF.js.map} +1 -1
  152. package/dashboard/dist/assets/{EscalationListSchemaPage-C954ngy3.js → EscalationListSchemaPage-BotlwlX3.js} +3 -3
  153. package/dashboard/dist/assets/{EscalationListSchemaPage-C954ngy3.js.map → EscalationListSchemaPage-BotlwlX3.js.map} +1 -1
  154. package/dashboard/dist/assets/{EscalationSchemaPage-Dij9K0ON.js → EscalationSchemaPage-CfZSVOSD.js} +3 -3
  155. package/dashboard/dist/assets/{EscalationSchemaPage-Dij9K0ON.js.map → EscalationSchemaPage-CfZSVOSD.js.map} +1 -1
  156. package/dashboard/dist/assets/{EscalationTimeline-DT2Owdl0.js → EscalationTimeline-CCKpuRBU.js} +2 -2
  157. package/dashboard/dist/assets/{EscalationTimeline-DT2Owdl0.js.map → EscalationTimeline-CCKpuRBU.js.map} +1 -1
  158. package/dashboard/dist/assets/{EscalationTitleSelect-BdbfMA98.js → EscalationTitleSelect-cpTzPHiW.js} +2 -2
  159. package/dashboard/dist/assets/{EscalationTitleSelect-BdbfMA98.js.map → EscalationTitleSelect-cpTzPHiW.js.map} +1 -1
  160. package/dashboard/dist/assets/{EscalationsOverview-niahs84P.js → EscalationsOverview-DS-nK0qV.js} +2 -2
  161. package/dashboard/dist/assets/{EscalationsOverview-niahs84P.js.map → EscalationsOverview-DS-nK0qV.js.map} +1 -1
  162. package/dashboard/dist/assets/{EventTable-DuLMBrSx.js → EventTable-UfebhJf0.js} +2 -2
  163. package/dashboard/dist/assets/{EventTable-DuLMBrSx.js.map → EventTable-UfebhJf0.js.map} +1 -1
  164. package/dashboard/dist/assets/{FilterBar-jtY6KNpL.js → FilterBar-newA5l-X.js} +2 -2
  165. package/dashboard/dist/assets/{FilterBar-jtY6KNpL.js.map → FilterBar-newA5l-X.js.map} +1 -1
  166. package/dashboard/dist/assets/{GraphInvokePage-DSRAI0Zt.js → GraphInvokePage-6SCDyQcK.js} +2 -2
  167. package/dashboard/dist/assets/{GraphInvokePage-DSRAI0Zt.js.map → GraphInvokePage-6SCDyQcK.js.map} +1 -1
  168. package/dashboard/dist/assets/HomePage-BEc-XdKj.js +2 -0
  169. package/dashboard/dist/assets/{HomePage-BUlSnCg8.js.map → HomePage-BEc-XdKj.js.map} +1 -1
  170. package/dashboard/dist/assets/LabelJobsPage-BO50zXT5.js +2 -0
  171. package/dashboard/dist/assets/LabelJobsPage-BO50zXT5.js.map +1 -0
  172. package/dashboard/dist/assets/{LinePage-BJKhVM9Y.js → LinePage-NYxJQ-ex.js} +3 -3
  173. package/dashboard/dist/assets/{LinePage-BJKhVM9Y.js.map → LinePage-NYxJQ-ex.js.map} +1 -1
  174. package/dashboard/dist/assets/{LinesPage-CrpJua3_.js → LinesPage-RbWTaQRh.js} +3 -3
  175. package/dashboard/dist/assets/{LinesPage-CrpJua3_.js.map → LinesPage-RbWTaQRh.js.map} +1 -1
  176. package/dashboard/dist/assets/{ListToolbar-BN0UPt0L.js → ListToolbar-B-E9-toh.js} +2 -2
  177. package/dashboard/dist/assets/{ListToolbar-BN0UPt0L.js.map → ListToolbar-B-E9-toh.js.map} +1 -1
  178. package/dashboard/dist/assets/{McpOverview-BgbJXYPh.js → McpOverview-Shcf9QhZ.js} +2 -2
  179. package/dashboard/dist/assets/{McpOverview-BgbJXYPh.js.map → McpOverview-Shcf9QhZ.js.map} +1 -1
  180. package/dashboard/dist/assets/{McpQueryDetailPage-BNjm2nrc.js → McpQueryDetailPage-D8kmjy2v.js} +3 -3
  181. package/dashboard/dist/assets/{McpQueryDetailPage-BNjm2nrc.js.map → McpQueryDetailPage-D8kmjy2v.js.map} +1 -1
  182. package/dashboard/dist/assets/{McpQueryPage-DplR8wP9.js → McpQueryPage-ck-o5m8A.js} +2 -2
  183. package/dashboard/dist/assets/{McpQueryPage-DplR8wP9.js.map → McpQueryPage-ck-o5m8A.js.map} +1 -1
  184. package/dashboard/dist/assets/McpRunDetailPage-BJKkM9-3.js +2 -0
  185. package/dashboard/dist/assets/{McpRunDetailPage-BHVEcKV5.js.map → McpRunDetailPage-BJKkM9-3.js.map} +1 -1
  186. package/dashboard/dist/assets/{McpRunsPage-CtlLagcs.js → McpRunsPage-DqhHfD5G.js} +2 -2
  187. package/dashboard/dist/assets/{McpRunsPage-CtlLagcs.js.map → McpRunsPage-DqhHfD5G.js.map} +1 -1
  188. package/dashboard/dist/assets/{NamespacePill-CeSfHH-j.js → NamespacePill--uIaGtrN.js} +2 -2
  189. package/dashboard/dist/assets/{NamespacePill-CeSfHH-j.js.map → NamespacePill--uIaGtrN.js.map} +1 -1
  190. package/dashboard/dist/assets/{OperationsPage-DH67bcW9.js → OperationsPage-D6B9Vv__.js} +3 -3
  191. package/dashboard/dist/assets/{OperationsPage-DH67bcW9.js.map → OperationsPage-D6B9Vv__.js.map} +1 -1
  192. package/dashboard/dist/assets/OperatorDashboard-CIH1cxjQ.js +2 -0
  193. package/dashboard/dist/assets/{OperatorDashboard-CMkgMewd.js.map → OperatorDashboard-CIH1cxjQ.js.map} +1 -1
  194. package/dashboard/dist/assets/{PageHeader-DiGWAQlR.js → PageHeader-DClJ33fV.js} +2 -2
  195. package/dashboard/dist/assets/{PageHeader-DiGWAQlR.js.map → PageHeader-DClJ33fV.js.map} +1 -1
  196. package/dashboard/dist/assets/{PageHeaderWithStats-DwnKQ06j.js → PageHeaderWithStats-C-TrbKQL.js} +2 -2
  197. package/dashboard/dist/assets/{PageHeaderWithStats-DwnKQ06j.js.map → PageHeaderWithStats-C-TrbKQL.js.map} +1 -1
  198. package/dashboard/dist/assets/PersonaDetailPage-DjvfyIph.js +2 -0
  199. package/dashboard/dist/assets/{PersonaDetailPage-Cs1FFdNq.js.map → PersonaDetailPage-DjvfyIph.js.map} +1 -1
  200. package/dashboard/dist/assets/{PersonasPage-CHTRdneF.js → PersonasPage-D7ryA8Vc.js} +2 -2
  201. package/dashboard/dist/assets/{PersonasPage-CHTRdneF.js.map → PersonasPage-D7ryA8Vc.js.map} +1 -1
  202. package/dashboard/dist/assets/{PortalPage-ChB5pBTZ.js → PortalPage-D3ybr0mo.js} +2 -2
  203. package/dashboard/dist/assets/{PortalPage-ChB5pBTZ.js.map → PortalPage-D3ybr0mo.js.map} +1 -1
  204. package/dashboard/dist/assets/PrintLabelsPanel-D0HF5x8b.js +2 -0
  205. package/dashboard/dist/assets/PrintLabelsPanel-D0HF5x8b.js.map +1 -0
  206. package/dashboard/dist/assets/{ProcessDetailPage-CzyqSfal.js → ProcessDetailPage-0xS9EdHe.js} +2 -2
  207. package/dashboard/dist/assets/{ProcessDetailPage-CzyqSfal.js.map → ProcessDetailPage-0xS9EdHe.js.map} +1 -1
  208. package/dashboard/dist/assets/{ProcessesListPage-rOwNkaU9.js → ProcessesListPage-93SMj1Fd.js} +2 -2
  209. package/dashboard/dist/assets/{ProcessesListPage-rOwNkaU9.js.map → ProcessesListPage-93SMj1Fd.js.map} +1 -1
  210. package/dashboard/dist/assets/{ResolverForm-DibnlZ-A.js → ResolverForm-DfogHDzl.js} +5 -5
  211. package/dashboard/dist/assets/{ResolverForm-DibnlZ-A.js.map → ResolverForm-DfogHDzl.js.map} +1 -1
  212. package/dashboard/dist/assets/{RoleDetailPage-Bv9R7iQC.js → RoleDetailPage-DlUOJWSB.js} +3 -3
  213. package/dashboard/dist/assets/{RoleDetailPage-Bv9R7iQC.js.map → RoleDetailPage-DlUOJWSB.js.map} +1 -1
  214. package/dashboard/dist/assets/{RolePill-D3hkAdKf.js → RolePill-BjD1Qw5y.js} +2 -2
  215. package/dashboard/dist/assets/{RolePill-D3hkAdKf.js.map → RolePill-BjD1Qw5y.js.map} +1 -1
  216. package/dashboard/dist/assets/RolesPage-DqhHSvaw.js +2 -0
  217. package/dashboard/dist/assets/{RolesPage-CUP7EH5U.js.map → RolesPage-DqhHSvaw.js.map} +1 -1
  218. package/dashboard/dist/assets/{RosterWidget-DZtmQcjU.js → RosterWidget-BrIq61HR.js} +2 -2
  219. package/dashboard/dist/assets/{RosterWidget-DZtmQcjU.js.map → RosterWidget-BrIq61HR.js.map} +1 -1
  220. package/dashboard/dist/assets/RunAsSelector-D6zQrCNr.js +2 -0
  221. package/dashboard/dist/assets/{RunAsSelector-B9-1vgZr.js.map → RunAsSelector-D6zQrCNr.js.map} +1 -1
  222. package/dashboard/dist/assets/ScanCodesPage-B2S9DR2f.js +2 -0
  223. package/dashboard/dist/assets/{ScanCodesPage-KN_e2rJl.js.map → ScanCodesPage-B2S9DR2f.js.map} +1 -1
  224. package/dashboard/dist/assets/ScanSchemeDetailPage-gpxKN-pL.js +5 -0
  225. package/dashboard/dist/assets/ScanSchemeDetailPage-gpxKN-pL.js.map +1 -0
  226. package/dashboard/dist/assets/ScanStationPage-B-UTgXsG.js +2 -0
  227. package/dashboard/dist/assets/{ScanStationPage-B0qbUOwc.js.map → ScanStationPage-B-UTgXsG.js.map} +1 -1
  228. package/dashboard/dist/assets/{SchemeMatchFields-CL7TKnw3.js → SchemeMatchFields-BK24aa7K.js} +2 -2
  229. package/dashboard/dist/assets/{SchemeMatchFields-CL7TKnw3.js.map → SchemeMatchFields-BK24aa7K.js.map} +1 -1
  230. package/dashboard/dist/assets/{ScopeBadge-DGz79rmG.js → ScopeBadge-ofLQ6HW-.js} +2 -2
  231. package/dashboard/dist/assets/{ScopeBadge-DGz79rmG.js.map → ScopeBadge-ofLQ6HW-.js.map} +1 -1
  232. package/dashboard/dist/assets/{StickyPagination-CUwxfBQH.js → StickyPagination-CgVv7vc_.js} +2 -2
  233. package/dashboard/dist/assets/{StickyPagination-CUwxfBQH.js.map → StickyPagination-CgVv7vc_.js.map} +1 -1
  234. package/dashboard/dist/assets/{StreamMessageDetail-DOjcO7d2.js → StreamMessageDetail-B9sxDVw4.js} +2 -2
  235. package/dashboard/dist/assets/{StreamMessageDetail-DOjcO7d2.js.map → StreamMessageDetail-B9sxDVw4.js.map} +1 -1
  236. package/dashboard/dist/assets/{SwimlaneTimeline-SPMpoLHP.js → SwimlaneTimeline-DQc0CYSL.js} +2 -2
  237. package/dashboard/dist/assets/{SwimlaneTimeline-SPMpoLHP.js.map → SwimlaneTimeline-DQc0CYSL.js.map} +1 -1
  238. package/dashboard/dist/assets/{TagInput-DaIdhv3h.js → TagInput-47qVYzke.js} +2 -2
  239. package/dashboard/dist/assets/{TagInput-DaIdhv3h.js.map → TagInput-47qVYzke.js.map} +1 -1
  240. package/dashboard/dist/assets/{TaskDetailPage-DvfzR2IQ.js → TaskDetailPage-D6VOsA1f.js} +2 -2
  241. package/dashboard/dist/assets/{TaskDetailPage-DvfzR2IQ.js.map → TaskDetailPage-D6VOsA1f.js.map} +1 -1
  242. package/dashboard/dist/assets/{TaskQueuePill-sUA1nZe-.js → TaskQueuePill-C5KmdXAl.js} +2 -2
  243. package/dashboard/dist/assets/{TaskQueuePill-sUA1nZe-.js.map → TaskQueuePill-C5KmdXAl.js.map} +1 -1
  244. package/dashboard/dist/assets/{TasksListPage-Jp6wmL7t.js → TasksListPage-DG8hvO8G.js} +2 -2
  245. package/dashboard/dist/assets/{TasksListPage-Jp6wmL7t.js.map → TasksListPage-DG8hvO8G.js.map} +1 -1
  246. package/dashboard/dist/assets/{TimeAgo-BCQA0Gb_.js → TimeAgo-CL02EhFi.js} +2 -2
  247. package/dashboard/dist/assets/{TimeAgo-BCQA0Gb_.js.map → TimeAgo-CL02EhFi.js.map} +1 -1
  248. package/dashboard/dist/assets/{TimestampCell-xhdMHDQt.js → TimestampCell-BE7oKVJg.js} +2 -2
  249. package/dashboard/dist/assets/{TimestampCell-xhdMHDQt.js.map → TimestampCell-BE7oKVJg.js.map} +1 -1
  250. package/dashboard/dist/assets/{ToolPill-CpBAFdEX.js → ToolPill-Cp9Drk1s.js} +2 -2
  251. package/dashboard/dist/assets/{ToolPill-CpBAFdEX.js.map → ToolPill-Cp9Drk1s.js.map} +1 -1
  252. package/dashboard/dist/assets/{ToolTestPanel-D8M3ITrJ.js → ToolTestPanel-CRecLh6S.js} +2 -2
  253. package/dashboard/dist/assets/{ToolTestPanel-D8M3ITrJ.js.map → ToolTestPanel-CRecLh6S.js.map} +1 -1
  254. package/dashboard/dist/assets/{TopicDetailPage-DdBJQp31.js → TopicDetailPage-QzkinTfN.js} +3 -3
  255. package/dashboard/dist/assets/{TopicDetailPage-DdBJQp31.js.map → TopicDetailPage-QzkinTfN.js.map} +1 -1
  256. package/dashboard/dist/assets/{TopicsPage-vpvsynD9.js → TopicsPage-D8dW6J65.js} +2 -2
  257. package/dashboard/dist/assets/{TopicsPage-vpvsynD9.js.map → TopicsPage-D8dW6J65.js.map} +1 -1
  258. package/dashboard/dist/assets/{UserName-BK6Lzsdw.js → UserName-Dw3R_zrl.js} +2 -2
  259. package/dashboard/dist/assets/{UserName-BK6Lzsdw.js.map → UserName-Dw3R_zrl.js.map} +1 -1
  260. package/dashboard/dist/assets/WorkflowExecutionPage-BTocv8or.js +2 -0
  261. package/dashboard/dist/assets/{WorkflowExecutionPage-DkM1TS4I.js.map → WorkflowExecutionPage-BTocv8or.js.map} +1 -1
  262. package/dashboard/dist/assets/{WorkflowPill-CKHip3hH.js → WorkflowPill-BiLYq__w.js} +2 -2
  263. package/dashboard/dist/assets/{WorkflowPill-CKHip3hH.js.map → WorkflowPill-BiLYq__w.js.map} +1 -1
  264. package/dashboard/dist/assets/WorkflowsDashboard-CIPEt3et.js +2 -0
  265. package/dashboard/dist/assets/{WorkflowsDashboard-g_N4y3QS.js.map → WorkflowsDashboard-CIPEt3et.js.map} +1 -1
  266. package/dashboard/dist/assets/{WorkflowsOverview-Drjo-Lu-.js → WorkflowsOverview-Bj4MJIE-.js} +2 -2
  267. package/dashboard/dist/assets/{WorkflowsOverview-Drjo-Lu-.js.map → WorkflowsOverview-Bj4MJIE-.js.map} +1 -1
  268. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CLltNHjZ.js → YamlWorkflowDetailPage-DMEk5k9-.js} +2 -2
  269. package/dashboard/dist/assets/{YamlWorkflowDetailPage-CLltNHjZ.js.map → YamlWorkflowDetailPage-DMEk5k9-.js.map} +1 -1
  270. package/dashboard/dist/assets/{YamlWorkflowsPage-CxQCB-Zi.js → YamlWorkflowsPage-F2yyyoiB.js} +2 -2
  271. package/dashboard/dist/assets/{YamlWorkflowsPage-CxQCB-Zi.js.map → YamlWorkflowsPage-F2yyyoiB.js.map} +1 -1
  272. package/dashboard/dist/assets/{agents-Dk25jjhj.js → agents-mSgxEPpI.js} +2 -2
  273. package/dashboard/dist/assets/{agents-Dk25jjhj.js.map → agents-mSgxEPpI.js.map} +1 -1
  274. package/dashboard/dist/assets/{bots-bRkCqhlq.js → bots-p4Hp0CV6.js} +2 -2
  275. package/dashboard/dist/assets/{bots-bRkCqhlq.js.map → bots-p4Hp0CV6.js.map} +1 -1
  276. package/dashboard/dist/assets/{capabilities-DARawLry.js → capabilities-D_-I_SXR.js} +2 -2
  277. package/dashboard/dist/assets/{capabilities-DARawLry.js.map → capabilities-D_-I_SXR.js.map} +1 -1
  278. package/dashboard/dist/assets/{controlplane-DKccxxs6.js → controlplane-DjdoQnRU.js} +2 -2
  279. package/dashboard/dist/assets/{controlplane-DKccxxs6.js.map → controlplane-DjdoQnRU.js.map} +1 -1
  280. package/dashboard/dist/assets/{escalation-columns-BaYuzMYf.js → escalation-columns-R_IEVQjQ.js} +2 -2
  281. package/dashboard/dist/assets/{escalation-columns-BaYuzMYf.js.map → escalation-columns-R_IEVQjQ.js.map} +1 -1
  282. package/dashboard/dist/assets/{escalation-items-CwbNFnsH.js → escalation-items-BGZlJMpk.js} +2 -2
  283. package/dashboard/dist/assets/{escalation-items-CwbNFnsH.js.map → escalation-items-BGZlJMpk.js.map} +1 -1
  284. package/dashboard/dist/assets/{index-Cf6qCgTf.js → index-BEMdD58x.js} +2 -2
  285. package/dashboard/dist/assets/{index-Cf6qCgTf.js.map → index-BEMdD58x.js.map} +1 -1
  286. package/dashboard/dist/assets/index-BUmz0NMg.css +1 -0
  287. package/dashboard/dist/assets/{index-hKOlahpE.js → index-BuCEhhnl.js} +2 -2
  288. package/dashboard/dist/assets/{index-hKOlahpE.js.map → index-BuCEhhnl.js.map} +1 -1
  289. package/dashboard/dist/assets/{index-D1uliPqS.js → index-BxbQmeqh.js} +2 -2
  290. package/dashboard/dist/assets/{index-D1uliPqS.js.map → index-BxbQmeqh.js.map} +1 -1
  291. package/dashboard/dist/assets/index-C5osluV3.js +2 -0
  292. package/dashboard/dist/assets/{index-CtrSYqmL.js.map → index-C5osluV3.js.map} +1 -1
  293. package/dashboard/dist/assets/{index-CU2UW2y6.js → index-C_dAJUzh.js} +25 -25
  294. package/dashboard/dist/assets/index-C_dAJUzh.js.map +1 -0
  295. package/dashboard/dist/assets/{index-Bx9HVzuT.js → index-D-FYj9jT.js} +2 -2
  296. package/dashboard/dist/assets/{index-Bx9HVzuT.js.map → index-D-FYj9jT.js.map} +1 -1
  297. package/dashboard/dist/assets/{index-BZgtzkkG.js → index-D6K_IgCz.js} +2 -2
  298. package/dashboard/dist/assets/{index-BZgtzkkG.js.map → index-D6K_IgCz.js.map} +1 -1
  299. package/dashboard/dist/assets/index-D7L_VoBD.js +2 -0
  300. package/dashboard/dist/assets/index-D7L_VoBD.js.map +1 -0
  301. package/dashboard/dist/assets/{index-DgpL_Lgc.js → index-D9RAN9sA.js} +2 -2
  302. package/dashboard/dist/assets/{index-DgpL_Lgc.js.map → index-D9RAN9sA.js.map} +1 -1
  303. package/dashboard/dist/assets/{index-dShcvdg3.js → index-DUYAGxwc.js} +2 -2
  304. package/dashboard/dist/assets/{index-dShcvdg3.js.map → index-DUYAGxwc.js.map} +1 -1
  305. package/dashboard/dist/assets/{index-E_hJ7vtX.js → index-Dk2KKo0z.js} +2 -2
  306. package/dashboard/dist/assets/{index-E_hJ7vtX.js.map → index-Dk2KKo0z.js.map} +1 -1
  307. package/dashboard/dist/assets/{index-DU2QCbgH.js → index-DlJkZ12b.js} +2 -2
  308. package/dashboard/dist/assets/{index-DU2QCbgH.js.map → index-DlJkZ12b.js.map} +1 -1
  309. package/dashboard/dist/assets/{index-kzifJWbM.js → index-FiNThtNU.js} +3 -3
  310. package/dashboard/dist/assets/{index-kzifJWbM.js.map → index-FiNThtNU.js.map} +1 -1
  311. package/dashboard/dist/assets/{knowledge-DOe5ks-E.js → knowledge-DSsPTqkK.js} +2 -2
  312. package/dashboard/dist/assets/{knowledge-DOe5ks-E.js.map → knowledge-DSsPTqkK.js.map} +1 -1
  313. package/dashboard/dist/assets/{machines-Zq_00v7k.js → machines-DSgGtqqr.js} +2 -2
  314. package/dashboard/dist/assets/{machines-Zq_00v7k.js.map → machines-DSgGtqqr.js.map} +1 -1
  315. package/dashboard/dist/assets/{mcp-BL8kD0oh.js → mcp-Cg-_uLw8.js} +2 -2
  316. package/dashboard/dist/assets/{mcp-BL8kD0oh.js.map → mcp-Cg-_uLw8.js.map} +1 -1
  317. package/dashboard/dist/assets/{mcp-query-BpokmJWi.js → mcp-query-DQombEK_.js} +2 -2
  318. package/dashboard/dist/assets/{mcp-query-BpokmJWi.js.map → mcp-query-DQombEK_.js.map} +1 -1
  319. package/dashboard/dist/assets/{personas-BubCnQZ8.js → personas-DYrcoVBu.js} +2 -2
  320. package/dashboard/dist/assets/{personas-BubCnQZ8.js.map → personas-DYrcoVBu.js.map} +1 -1
  321. package/dashboard/dist/assets/{pipelines--DUoMx7K.js → pipelines-wdb4xsey.js} +2 -2
  322. package/dashboard/dist/assets/{pipelines--DUoMx7K.js.map → pipelines-wdb4xsey.js.map} +1 -1
  323. package/dashboard/dist/assets/{tasks-CJXN4OB4.js → tasks-Bil7gvm9.js} +2 -2
  324. package/dashboard/dist/assets/{tasks-CJXN4OB4.js.map → tasks-Bil7gvm9.js.map} +1 -1
  325. package/dashboard/dist/assets/{topics-CAG08Ruo.js → topics-wBqaVhRR.js} +2 -2
  326. package/dashboard/dist/assets/{topics-CAG08Ruo.js.map → topics-wBqaVhRR.js.map} +1 -1
  327. package/dashboard/dist/assets/{useDebouncedValue-DQ2D8cm2.js → useDebouncedValue-CwrY8TpV.js} +2 -2
  328. package/dashboard/dist/assets/{useDebouncedValue-DQ2D8cm2.js.map → useDebouncedValue-CwrY8TpV.js.map} +1 -1
  329. package/dashboard/dist/assets/{useNamespace-DjEVAlJQ.js → useNamespace-Sod_xApz.js} +2 -2
  330. package/dashboard/dist/assets/{useNamespace-DjEVAlJQ.js.map → useNamespace-Sod_xApz.js.map} +1 -1
  331. package/dashboard/dist/assets/{useYamlActivityEvents-etcpfIwo.js → useYamlActivityEvents-CKLInV3C.js} +2 -2
  332. package/dashboard/dist/assets/{useYamlActivityEvents-etcpfIwo.js.map → useYamlActivityEvents-CKLInV3C.js.map} +1 -1
  333. package/dashboard/dist/assets/{validate-YJK_6a7m.js → validate-CYhW1xMJ.js} +2 -2
  334. package/dashboard/dist/assets/{validate-YJK_6a7m.js.map → validate-CYhW1xMJ.js.map} +1 -1
  335. package/dashboard/dist/assets/{vendor-icons-en0_uSRD.js → vendor-icons-ed7mYQw4.js} +2 -2
  336. package/dashboard/dist/assets/{vendor-icons-en0_uSRD.js.map → vendor-icons-ed7mYQw4.js.map} +1 -1
  337. package/dashboard/dist/assets/{yaml-workflows-D97Bz6li.js → yaml-workflows-C20qHo3L.js} +2 -2
  338. package/dashboard/dist/assets/{yaml-workflows-D97Bz6li.js.map → yaml-workflows-C20qHo3L.js.map} +1 -1
  339. package/dashboard/dist/index.html +3 -3
  340. package/docs/api/http/labels.md +115 -0
  341. package/docs/api/http/users.md +2 -0
  342. package/docs/api/mcp/admin.md +76 -1
  343. package/docs/code-owned-configuration.md +1 -1
  344. package/docs/iam.md +12 -0
  345. package/docs/label-sheets.md +267 -0
  346. package/docs/scan-codes.md +11 -5
  347. package/package.json +4 -1
  348. package/dashboard/dist/assets/AvailableEscalationsPage-BRKyG5qZ.js +0 -2
  349. package/dashboard/dist/assets/AvailableEscalationsPage-BRKyG5qZ.js.map +0 -1
  350. package/dashboard/dist/assets/BulkAssignModal-BWfzPrRk.js +0 -2
  351. package/dashboard/dist/assets/HomePage-BUlSnCg8.js +0 -2
  352. package/dashboard/dist/assets/McpRunDetailPage-BHVEcKV5.js +0 -2
  353. package/dashboard/dist/assets/OperatorDashboard-CMkgMewd.js +0 -2
  354. package/dashboard/dist/assets/PersonaDetailPage-Cs1FFdNq.js +0 -2
  355. package/dashboard/dist/assets/RolesPage-CUP7EH5U.js +0 -2
  356. package/dashboard/dist/assets/RunAsSelector-B9-1vgZr.js +0 -2
  357. package/dashboard/dist/assets/ScanCodesPage-KN_e2rJl.js +0 -2
  358. package/dashboard/dist/assets/ScanSchemeDetailPage-CqItQ67Y.js +0 -5
  359. package/dashboard/dist/assets/ScanSchemeDetailPage-CqItQ67Y.js.map +0 -1
  360. package/dashboard/dist/assets/ScanStationPage-B0qbUOwc.js +0 -2
  361. package/dashboard/dist/assets/WorkflowExecutionPage-DkM1TS4I.js +0 -2
  362. package/dashboard/dist/assets/WorkflowsDashboard-g_N4y3QS.js +0 -2
  363. package/dashboard/dist/assets/index-BmzscsXK.css +0 -1
  364. package/dashboard/dist/assets/index-CU2UW2y6.js.map +0 -1
  365. package/dashboard/dist/assets/index-CtrSYqmL.js +0 -2
  366. package/dashboard/dist/assets/index-DU-1gMks.js +0 -2
  367. package/dashboard/dist/assets/index-DU-1gMks.js.map +0 -1
@@ -0,0 +1,216 @@
1
+ "use strict";
2
+ // Resolves a print job's source into targets, reading as the caller.
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.MAX_RANGE_PAD = void 0;
38
+ exports.parseListSource = parseListSource;
39
+ exports.expandRangeSource = expandRangeSource;
40
+ exports.resolveLabelTargets = resolveLabelTargets;
41
+ exports.markResolvedTargets = markResolvedTargets;
42
+ const db_1 = require("../../lib/db");
43
+ const config_1 = require("../../modules/config");
44
+ const types_1 = require("../../types");
45
+ const errors_1 = require("./errors");
46
+ exports.MAX_RANGE_PAD = 12;
47
+ function cap(scheme) {
48
+ return scheme.kind === types_1.SCAN_SCHEME_KINDS.IDENTITY
49
+ ? config_1.config.LT_LABELS_MAX_CREDENTIALS_PER_JOB
50
+ : config_1.config.LT_LABELS_MAX_PER_JOB;
51
+ }
52
+ function assertCount(n, scheme) {
53
+ if (n === 0)
54
+ throw new errors_1.LabelRequestError(400, 'the source names no targets');
55
+ if (n > cap(scheme))
56
+ throw new errors_1.LabelRequestError(400, `the source names ${n} targets; one job prints at most ${cap(scheme)}`);
57
+ }
58
+ /** Targets from pasted lines or CSV. A first row naming `target` is a header; its columns become item tokens. */
59
+ function parseListSource(text) {
60
+ const rows = text.split(/\r?\n/).map((l) => l.trim()).filter(Boolean)
61
+ .map((l) => l.split(/[,\t]/).map((c) => c.trim()));
62
+ if (rows.length === 0)
63
+ return [];
64
+ const header = rows[0][0].toLowerCase() === 'target' ? rows.shift().map((h) => h.replace(/[^a-zA-Z0-9_]/g, '_')) : null;
65
+ return rows.map((cells) => {
66
+ const item = {};
67
+ cells.slice(1).forEach((value, i) => { item[header?.[i + 1] || `col${i + 2}`] = value; });
68
+ return { target: cells[0], item };
69
+ });
70
+ }
71
+ /** Targets from a numeric run: prefix + zero-padded number + suffix. */
72
+ function expandRangeSource(source, max) {
73
+ const { from, to, pad = 0, prefix = '', suffix = '' } = source;
74
+ if (!Number.isInteger(from) || !Number.isInteger(to) || from < 0 || to < from) {
75
+ throw new errors_1.LabelRequestError(400, 'a range needs whole numbers with from ≤ to');
76
+ }
77
+ if (!Number.isInteger(pad) || pad < 0 || pad > exports.MAX_RANGE_PAD) {
78
+ throw new errors_1.LabelRequestError(400, `pad must be between 0 and ${exports.MAX_RANGE_PAD}`);
79
+ }
80
+ if (to - from + 1 > max)
81
+ throw new errors_1.LabelRequestError(400, `the range names ${to - from + 1} targets; one job prints at most ${max}`);
82
+ return Array.from({ length: to - from + 1 }, (_, i) => ({
83
+ target: `${prefix}${String(from + i).padStart(pad, '0')}${suffix}`,
84
+ }));
85
+ }
86
+ /** Rows read at once for a selection; each read applies the caller's own access check. */
87
+ const ESCALATION_READ_CHUNK = 25;
88
+ async function escalationTargets(ids, scheme, auth) {
89
+ const { getEscalation } = await Promise.resolve().then(() => __importStar(require('../../api/escalations/single')));
90
+ const unique = [...new Set(ids)];
91
+ const byTarget = new Map();
92
+ for (let i = 0; i < unique.length; i += ESCALATION_READ_CHUNK) {
93
+ const chunk = unique.slice(i, i + ESCALATION_READ_CHUNK);
94
+ const results = await Promise.all(chunk.map((id) => getEscalation({ id }, auth)));
95
+ results.forEach((result, j) => {
96
+ if (result.status !== 200) {
97
+ throw new errors_1.LabelRequestError(result.status === 404 ? 404 : 403, `escalation ${chunk[j]}: ${result.error}`);
98
+ }
99
+ addRow(byTarget, result.data, scheme);
100
+ });
101
+ }
102
+ return [...byTarget.values()];
103
+ }
104
+ async function facetTargets(source, scheme, auth) {
105
+ const { searchByFacets } = await Promise.resolve().then(() => __importStar(require('../../api/escalations/facets')));
106
+ const result = await searchByFacets({ ...source.query, limit: cap(scheme) + 1 }, auth);
107
+ if (result.status !== 200)
108
+ throw new errors_1.LabelRequestError(result.status === 400 ? 400 : 403, result.error ?? 'facet search refused');
109
+ const byTarget = new Map();
110
+ for (const row of result.data.escalations)
111
+ addRow(byTarget, row, scheme);
112
+ return [...byTarget.values()];
113
+ }
114
+ /** Keep the newest row per target; a member facet contributes each of its values. */
115
+ function addRow(byTarget, row, scheme) {
116
+ const value = row.metadata?.[scheme.target_facet];
117
+ const values = Array.isArray(value) && scheme.target_match === types_1.SCAN_TARGET_MATCH.MEMBER ? value : [value];
118
+ for (const v of values) {
119
+ if (v === undefined || v === null || v === '')
120
+ continue;
121
+ const target = String(v);
122
+ const seen = byTarget.get(target);
123
+ if (!seen || String(row.created_at) > String(seen.item?.__created_at ?? '')) {
124
+ byTarget.set(target, { target, item: { ...row.metadata, __created_at: row.created_at }, resolved: true });
125
+ }
126
+ }
127
+ }
128
+ const USERS_WITH_KEY = `
129
+ SELECT u.id FROM lt_users u
130
+ WHERE u.metadata ? $1
131
+ AND ($2::uuid[] IS NOT NULL OR u.status = 'active')
132
+ AND ($2::uuid[] IS NULL OR u.id = ANY($2::uuid[]))
133
+ AND ($3::text IS NULL OR EXISTS (SELECT 1 FROM lt_user_roles r WHERE r.user_id = u.id AND r.role = $3))
134
+ ORDER BY u.display_name NULLS LAST, u.external_id
135
+ LIMIT $4`;
136
+ async function userTargets(source, scheme) {
137
+ const { getUser, getIdentityPropertyKeys } = await Promise.resolve().then(() => __importStar(require('../user')));
138
+ const { onlyUuids } = await Promise.resolve().then(() => __importStar(require('../../lib/uuid')));
139
+ const ids = source.userIds ? onlyUuids(source.userIds) : null;
140
+ if (source.userIds && ids.length !== new Set(source.userIds).size) {
141
+ throw new errors_1.LabelRequestError(400, 'userIds must be user ids');
142
+ }
143
+ const { rows } = await (0, db_1.getPool)().query(USERS_WITH_KEY, [scheme.target_facet, ids, source.role ?? null, cap(scheme) + 1]);
144
+ const identityKeys = await getIdentityPropertyKeys();
145
+ const users = await Promise.all(rows.map((r) => getUser(r.id)));
146
+ return users.filter((u) => u !== null).map((u) => {
147
+ const metadata = { ...(u.metadata ?? {}) };
148
+ for (const key of identityKeys)
149
+ delete metadata[key];
150
+ return {
151
+ target: String(u.metadata[scheme.target_facet]),
152
+ userId: u.id,
153
+ resolved: u.status === 'active',
154
+ user: {
155
+ ...metadata,
156
+ name: u.display_name ?? u.external_id,
157
+ display_name: u.display_name,
158
+ email: u.email,
159
+ roles: u.roles.map((r) => r.role),
160
+ },
161
+ };
162
+ });
163
+ }
164
+ /**
165
+ * The targets a source names. Identity schemes read users only: a pasted or
166
+ * ranged credential would mint a badge for no one. Rows are read as the
167
+ * caller, so a job never prints what the caller cannot see.
168
+ */
169
+ async function resolveLabelTargets(source, scheme, auth) {
170
+ const identity = scheme.kind === types_1.SCAN_SCHEME_KINDS.IDENTITY;
171
+ if (identity && source.kind !== 'users') {
172
+ throw new errors_1.LabelRequestError(400, 'identity labels print for users; use a users source');
173
+ }
174
+ if (!identity && source.kind === 'users') {
175
+ throw new errors_1.LabelRequestError(400, 'a users source prints identity labels only');
176
+ }
177
+ let targets;
178
+ switch (source.kind) {
179
+ case 'escalations':
180
+ if (!Array.isArray(source.ids))
181
+ throw new errors_1.LabelRequestError(400, 'ids must be a list');
182
+ assertCount(new Set(source.ids).size, scheme);
183
+ targets = await escalationTargets(source.ids, scheme, auth);
184
+ break;
185
+ case 'facets':
186
+ targets = await facetTargets(source, scheme, auth);
187
+ break;
188
+ case 'users':
189
+ targets = await userTargets(source, scheme);
190
+ break;
191
+ case 'list':
192
+ targets = parseListSource(String(source.text ?? ''));
193
+ break;
194
+ case 'range':
195
+ targets = expandRangeSource(source, cap(scheme));
196
+ break;
197
+ default:
198
+ throw new errors_1.LabelRequestError(400, `unknown source kind "${source.kind}"`);
199
+ }
200
+ for (const t of targets)
201
+ delete t.item?.__created_at;
202
+ assertCount(targets.length, scheme);
203
+ return targets;
204
+ }
205
+ /** Marks which action targets name a row today, in one statement. */
206
+ async function markResolvedTargets(targets, scheme) {
207
+ const unchecked = targets.filter((t) => t.resolved === undefined);
208
+ if (unchecked.length === 0)
209
+ return;
210
+ const member = scheme.target_match === types_1.SCAN_TARGET_MATCH.MEMBER;
211
+ const { rows } = await (0, db_1.getPool)().query(`SELECT t FROM unnest($2::text[]) AS t
212
+ WHERE EXISTS (SELECT 1 FROM lt_escalations e WHERE e.metadata @> ${member ? 'jsonb_build_object($1::text, jsonb_build_array(t))' : 'jsonb_build_object($1::text, t)'})`, [scheme.target_facet, unchecked.map((t) => t.target)]);
213
+ const found = new Set(rows.map((r) => r.t));
214
+ for (const t of unchecked)
215
+ t.resolved = found.has(t.target);
216
+ }
@@ -0,0 +1,3 @@
1
+ export { listLabelTemplates, getLabelTemplate, mapTemplate } from './read';
2
+ export { upsertLabelTemplate, deleteLabelTemplate, seedLabelTemplate, applyLabelTemplate, LabelTemplateConflictError, } from './write';
3
+ export { assertValidTemplate, LabelTemplateValidationError, MAX_TEMPLATE_CODES, MAX_TEMPLATE_LINES, type TemplateContext, } from './validate';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MAX_TEMPLATE_LINES = exports.MAX_TEMPLATE_CODES = exports.LabelTemplateValidationError = exports.assertValidTemplate = exports.LabelTemplateConflictError = exports.applyLabelTemplate = exports.seedLabelTemplate = exports.deleteLabelTemplate = exports.upsertLabelTemplate = exports.mapTemplate = exports.getLabelTemplate = exports.listLabelTemplates = void 0;
4
+ var read_1 = require("./read");
5
+ Object.defineProperty(exports, "listLabelTemplates", { enumerable: true, get: function () { return read_1.listLabelTemplates; } });
6
+ Object.defineProperty(exports, "getLabelTemplate", { enumerable: true, get: function () { return read_1.getLabelTemplate; } });
7
+ Object.defineProperty(exports, "mapTemplate", { enumerable: true, get: function () { return read_1.mapTemplate; } });
8
+ var write_1 = require("./write");
9
+ Object.defineProperty(exports, "upsertLabelTemplate", { enumerable: true, get: function () { return write_1.upsertLabelTemplate; } });
10
+ Object.defineProperty(exports, "deleteLabelTemplate", { enumerable: true, get: function () { return write_1.deleteLabelTemplate; } });
11
+ Object.defineProperty(exports, "seedLabelTemplate", { enumerable: true, get: function () { return write_1.seedLabelTemplate; } });
12
+ Object.defineProperty(exports, "applyLabelTemplate", { enumerable: true, get: function () { return write_1.applyLabelTemplate; } });
13
+ Object.defineProperty(exports, "LabelTemplateConflictError", { enumerable: true, get: function () { return write_1.LabelTemplateConflictError; } });
14
+ var validate_1 = require("./validate");
15
+ Object.defineProperty(exports, "assertValidTemplate", { enumerable: true, get: function () { return validate_1.assertValidTemplate; } });
16
+ Object.defineProperty(exports, "LabelTemplateValidationError", { enumerable: true, get: function () { return validate_1.LabelTemplateValidationError; } });
17
+ Object.defineProperty(exports, "MAX_TEMPLATE_CODES", { enumerable: true, get: function () { return validate_1.MAX_TEMPLATE_CODES; } });
18
+ Object.defineProperty(exports, "MAX_TEMPLATE_LINES", { enumerable: true, get: function () { return validate_1.MAX_TEMPLATE_LINES; } });
@@ -0,0 +1,4 @@
1
+ import type { LabelTemplate } from '../../../types/labels';
2
+ export declare function mapTemplate(row: any): LabelTemplate;
3
+ export declare function listLabelTemplates(schemeVersion?: number): Promise<LabelTemplate[]>;
4
+ export declare function getLabelTemplate(name: string): Promise<LabelTemplate | null>;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mapTemplate = mapTemplate;
4
+ exports.listLabelTemplates = listLabelTemplates;
5
+ exports.getLabelTemplate = getLabelTemplate;
6
+ const db_1 = require("../../../lib/db");
7
+ const sql_1 = require("./sql");
8
+ function mapTemplate(row) {
9
+ return {
10
+ name: row.name,
11
+ scheme_version: row.scheme_version,
12
+ title: row.title,
13
+ description: row.description ?? null,
14
+ codes: row.codes ?? [],
15
+ text: row.text ?? {},
16
+ symbology: row.symbology,
17
+ human_readable: row.human_readable,
18
+ media: row.media ?? null,
19
+ sensitive: row.sensitive,
20
+ enabled: row.enabled,
21
+ revision: row.revision,
22
+ source: row.source,
23
+ created_at: row.created_at,
24
+ updated_at: row.updated_at,
25
+ };
26
+ }
27
+ async function listLabelTemplates(schemeVersion) {
28
+ const { rows } = schemeVersion === undefined
29
+ ? await (0, db_1.getPool)().query(sql_1.LIST_TEMPLATES)
30
+ : await (0, db_1.getPool)().query(sql_1.LIST_TEMPLATES_BY_SCHEME, [schemeVersion]);
31
+ return rows.map(mapTemplate);
32
+ }
33
+ async function getLabelTemplate(name) {
34
+ const { rows } = await (0, db_1.getPool)().query(sql_1.GET_TEMPLATE, [name]);
35
+ return rows[0] ? mapTemplate(rows[0]) : null;
36
+ }
@@ -0,0 +1,8 @@
1
+ export declare const LIST_TEMPLATES = "SELECT * FROM lt_config_label_templates ORDER BY scheme_version, name";
2
+ export declare const LIST_TEMPLATES_BY_SCHEME = "SELECT * FROM lt_config_label_templates WHERE scheme_version = $1 ORDER BY name";
3
+ export declare const GET_TEMPLATE = "SELECT * FROM lt_config_label_templates WHERE name = $1";
4
+ export declare const DELETE_TEMPLATE = "DELETE FROM lt_config_label_templates WHERE name = $1";
5
+ /** API write. $13 is the expected revision; null writes unconditionally. */
6
+ export declare const UPSERT_TEMPLATE = "INSERT INTO lt_config_label_templates (name, scheme_version, title, description, codes, text, symbology,\n human_readable, media, sensitive, enabled, source)\nVALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)\nON CONFLICT (name) DO UPDATE SET scheme_version = EXCLUDED.scheme_version,\n title = EXCLUDED.title,\n description = EXCLUDED.description,\n codes = EXCLUDED.codes,\n text = EXCLUDED.text,\n symbology = EXCLUDED.symbology,\n human_readable = EXCLUDED.human_readable,\n media = EXCLUDED.media,\n sensitive = EXCLUDED.sensitive,\n enabled = EXCLUDED.enabled,\n source = EXCLUDED.source,\n revision = lt_config_label_templates.revision + 1\nWHERE $13::int IS NULL OR lt_config_label_templates.revision = $13::int\nRETURNING *";
7
+ export declare const SEED_TEMPLATE = "INSERT INTO lt_config_label_templates (name, scheme_version, title, description, codes, text, symbology,\n human_readable, media, sensitive, enabled, source)\nVALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)\nON CONFLICT (name) DO NOTHING";
8
+ export declare const APPLY_TEMPLATE = "INSERT INTO lt_config_label_templates (name, scheme_version, title, description, codes, text, symbology,\n human_readable, media, sensitive, enabled, source)\nVALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)\nON CONFLICT (name) DO UPDATE SET scheme_version = EXCLUDED.scheme_version,\n title = EXCLUDED.title,\n description = EXCLUDED.description,\n codes = EXCLUDED.codes,\n text = EXCLUDED.text,\n symbology = EXCLUDED.symbology,\n human_readable = EXCLUDED.human_readable,\n media = EXCLUDED.media,\n sensitive = EXCLUDED.sensitive,\n enabled = EXCLUDED.enabled,\n source = EXCLUDED.source,\n revision = lt_config_label_templates.revision + 1\nWHERE (lt_config_label_templates.scheme_version, lt_config_label_templates.title,\n lt_config_label_templates.description, lt_config_label_templates.codes,\n lt_config_label_templates.text, lt_config_label_templates.symbology,\n lt_config_label_templates.human_readable, lt_config_label_templates.media,\n lt_config_label_templates.sensitive, lt_config_label_templates.enabled,\n lt_config_label_templates.source)\n IS DISTINCT FROM\n (EXCLUDED.scheme_version, EXCLUDED.title, EXCLUDED.description, EXCLUDED.codes,\n EXCLUDED.text, EXCLUDED.symbology, EXCLUDED.human_readable, EXCLUDED.media,\n EXCLUDED.sensitive, EXCLUDED.enabled, EXCLUDED.source)\nRETURNING (xmax = 0) AS inserted";
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ // lt_config_label_templates. Writes bump `revision`; the apply pass is a
3
+ // zero-row no-op when the declaration is unchanged.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.APPLY_TEMPLATE = exports.SEED_TEMPLATE = exports.UPSERT_TEMPLATE = exports.DELETE_TEMPLATE = exports.GET_TEMPLATE = exports.LIST_TEMPLATES_BY_SCHEME = exports.LIST_TEMPLATES = void 0;
6
+ const COLUMNS = `name, scheme_version, title, description, codes, text, symbology,
7
+ human_readable, media, sensitive, enabled, source`;
8
+ const VALUES = '$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12';
9
+ const SET = `scheme_version = EXCLUDED.scheme_version,
10
+ title = EXCLUDED.title,
11
+ description = EXCLUDED.description,
12
+ codes = EXCLUDED.codes,
13
+ text = EXCLUDED.text,
14
+ symbology = EXCLUDED.symbology,
15
+ human_readable = EXCLUDED.human_readable,
16
+ media = EXCLUDED.media,
17
+ sensitive = EXCLUDED.sensitive,
18
+ enabled = EXCLUDED.enabled,
19
+ source = EXCLUDED.source,
20
+ revision = lt_config_label_templates.revision + 1`;
21
+ exports.LIST_TEMPLATES = 'SELECT * FROM lt_config_label_templates ORDER BY scheme_version, name';
22
+ exports.LIST_TEMPLATES_BY_SCHEME = 'SELECT * FROM lt_config_label_templates WHERE scheme_version = $1 ORDER BY name';
23
+ exports.GET_TEMPLATE = 'SELECT * FROM lt_config_label_templates WHERE name = $1';
24
+ exports.DELETE_TEMPLATE = 'DELETE FROM lt_config_label_templates WHERE name = $1';
25
+ /** API write. $13 is the expected revision; null writes unconditionally. */
26
+ exports.UPSERT_TEMPLATE = `\
27
+ INSERT INTO lt_config_label_templates (${COLUMNS})
28
+ VALUES (${VALUES})
29
+ ON CONFLICT (name) DO UPDATE SET ${SET}
30
+ WHERE $13::int IS NULL OR lt_config_label_templates.revision = $13::int
31
+ RETURNING *`;
32
+ exports.SEED_TEMPLATE = `\
33
+ INSERT INTO lt_config_label_templates (${COLUMNS})
34
+ VALUES (${VALUES})
35
+ ON CONFLICT (name) DO NOTHING`;
36
+ exports.APPLY_TEMPLATE = `\
37
+ INSERT INTO lt_config_label_templates (${COLUMNS})
38
+ VALUES (${VALUES})
39
+ ON CONFLICT (name) DO UPDATE SET ${SET}
40
+ WHERE (lt_config_label_templates.scheme_version, lt_config_label_templates.title,
41
+ lt_config_label_templates.description, lt_config_label_templates.codes,
42
+ lt_config_label_templates.text, lt_config_label_templates.symbology,
43
+ lt_config_label_templates.human_readable, lt_config_label_templates.media,
44
+ lt_config_label_templates.sensitive, lt_config_label_templates.enabled,
45
+ lt_config_label_templates.source)
46
+ IS DISTINCT FROM
47
+ (EXCLUDED.scheme_version, EXCLUDED.title, EXCLUDED.description, EXCLUDED.codes,
48
+ EXCLUDED.text, EXCLUDED.symbology, EXCLUDED.human_readable, EXCLUDED.media,
49
+ EXCLUDED.sensitive, EXCLUDED.enabled, EXCLUDED.source)
50
+ RETURNING (xmax = 0) AS inserted`;
@@ -0,0 +1,19 @@
1
+ import { type ScanRule, type ScanScheme } from '../../../types';
2
+ import type { LabelTemplateInput } from '../../../types/labels';
3
+ /** A template declaration that cannot be stored. */
4
+ export declare class LabelTemplateValidationError extends Error {
5
+ status: number;
6
+ constructor(message: string);
7
+ }
8
+ export declare const MAX_TEMPLATE_CODES = 4;
9
+ export declare const MAX_TEMPLATE_LINES = 2;
10
+ export interface TemplateContext {
11
+ scheme: ScanScheme | null;
12
+ rules: ScanRule[];
13
+ /** Every identity key in use, so a token can never print a credential as text. */
14
+ identityKeys: string[];
15
+ /** Media preset ids the deployment knows. */
16
+ mediaIds: string[];
17
+ }
18
+ /** Throws LabelTemplateValidationError unless the template fits its scheme. */
19
+ export declare function assertValidTemplate(input: LabelTemplateInput, ctx: TemplateContext): void;
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ // Template validation against its scheme, its rules and the identity keys.
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.MAX_TEMPLATE_LINES = exports.MAX_TEMPLATE_CODES = exports.LabelTemplateValidationError = void 0;
5
+ exports.assertValidTemplate = assertValidTemplate;
6
+ const types_1 = require("../../../shared/labels/types");
7
+ const compose_1 = require("../../../shared/labels/compose");
8
+ const tokens_1 = require("../../../shared/labels/tokens");
9
+ const types_2 = require("../../../types");
10
+ /** A template declaration that cannot be stored. */
11
+ class LabelTemplateValidationError extends Error {
12
+ constructor(message) {
13
+ super(message);
14
+ this.status = 400;
15
+ this.name = 'LabelTemplateValidationError';
16
+ }
17
+ }
18
+ exports.LabelTemplateValidationError = LabelTemplateValidationError;
19
+ exports.MAX_TEMPLATE_CODES = 4;
20
+ exports.MAX_TEMPLATE_LINES = 2;
21
+ const MAX_TEXT_LENGTH = 160;
22
+ const NAME = /^[a-z0-9][a-z0-9-]{0,62}$/;
23
+ function fail(message) {
24
+ throw new LabelTemplateValidationError(message);
25
+ }
26
+ function assertText(label, text) {
27
+ if (typeof text !== 'string')
28
+ fail(`${label} must be text`);
29
+ if (text.length > MAX_TEXT_LENGTH)
30
+ fail(`${label} is longer than ${MAX_TEXT_LENGTH} characters`);
31
+ }
32
+ /** Throws LabelTemplateValidationError unless the template fits its scheme. */
33
+ function assertValidTemplate(input, ctx) {
34
+ if (typeof input.name !== 'string' || !NAME.test(input.name)) {
35
+ fail('name must be lowercase letters, digits and dashes, starting with a letter or digit');
36
+ }
37
+ const { scheme } = ctx;
38
+ if (!scheme)
39
+ fail(`scan scheme ${input.scheme_version} does not exist`);
40
+ if (!(0, compose_1.isMintableScheme)(scheme)) {
41
+ fail(`scheme ${scheme.version} reads ${scheme.encoding} codes; templates print fixed and delimited codes only`);
42
+ }
43
+ if (!input.title || typeof input.title !== 'string')
44
+ fail('title is required');
45
+ assertText('title', input.title);
46
+ if (input.description != null)
47
+ assertText('description', input.description);
48
+ if (!Array.isArray(input.codes) || input.codes.length < 1 || input.codes.length > exports.MAX_TEMPLATE_CODES) {
49
+ fail(`a template prints 1 to ${exports.MAX_TEMPLATE_CODES} codes`);
50
+ }
51
+ const categories = new Set();
52
+ for (const code of input.codes) {
53
+ if (!ctx.rules.some((r) => r.category === code.category)) {
54
+ fail(`scheme ${scheme.version} has no rule for category "${code.category}"`);
55
+ }
56
+ if (categories.has(code.category))
57
+ fail(`category "${code.category}" is printed twice`);
58
+ categories.add(code.category);
59
+ if (!types_1.LABEL_TONES.includes(code.tone))
60
+ fail(`tone must be one of ${types_1.LABEL_TONES.join(', ')}`);
61
+ if (code.caption != null)
62
+ assertText('caption', code.caption);
63
+ }
64
+ const lines = input.text?.lines ?? [];
65
+ if (!Array.isArray(lines) || lines.length > exports.MAX_TEMPLATE_LINES)
66
+ fail(`a template prints up to ${exports.MAX_TEMPLATE_LINES} lines`);
67
+ const texts = [input.text?.title ?? '', ...lines, ...input.codes.map((c) => c.caption ?? '')];
68
+ texts.forEach((t, i) => assertText(i === 0 ? 'text title' : 'text line', t));
69
+ const identity = scheme.kind === types_2.SCAN_SCHEME_KINDS.IDENTITY;
70
+ for (const text of texts) {
71
+ const unknown = (0, tokens_1.unknownLabelTokens)(text);
72
+ if (unknown.length)
73
+ fail(`unknown token {${unknown[0]}}; use {target}, {item.<facet>}, {user.<key>} or {scheme.name}`);
74
+ const tokens = (0, tokens_1.listLabelTokens)(text);
75
+ if (identity && tokens.some((t) => t.startsWith('item.')))
76
+ fail('an identity template reads {user.<key>} tokens, not {item.<facet>}');
77
+ if (!identity && tokens.some((t) => t.startsWith('user.')))
78
+ fail('{user.<key>} tokens print on identity templates only');
79
+ const credential = (0, tokens_1.userTokenKeys)(text).find((k) => ctx.identityKeys.includes(k) || k === scheme.target_facet);
80
+ if (credential)
81
+ fail(`{user.${credential}} is an identity credential and never prints as text`);
82
+ if (identity && tokens.includes('target'))
83
+ fail('{target} on an identity template is the credential; it never prints as text');
84
+ }
85
+ const symbology = input.symbology ?? 'code128';
86
+ if (!types_1.LABEL_SYMBOLOGIES.includes(symbology)) {
87
+ fail(`symbology must be one of ${types_1.LABEL_SYMBOLOGIES.join(', ')}`);
88
+ }
89
+ if (input.media != null && !ctx.mediaIds.includes(input.media))
90
+ fail(`unknown media "${input.media}"`);
91
+ if (identity && input.sensitive === false)
92
+ fail('a template on an identity scheme is always sensitive');
93
+ }
@@ -0,0 +1,16 @@
1
+ import type { LabelTemplate, LabelTemplateInput } from '../../../types/labels';
2
+ /** An API write raced another: the stored revision is not the one the caller read. */
3
+ export declare class LabelTemplateConflictError extends Error {
4
+ status: number;
5
+ constructor(name: string, revision: number);
6
+ }
7
+ /**
8
+ * Create or replace a template from the API. With `expectedRevision`, the
9
+ * write lands only on that revision; otherwise LabelTemplateConflictError.
10
+ */
11
+ export declare function upsertLabelTemplate(input: LabelTemplateInput, expectedRevision?: number): Promise<LabelTemplate>;
12
+ export declare function deleteLabelTemplate(name: string): Promise<boolean>;
13
+ /** Insert a template only when absent (database-owned configuration). */
14
+ export declare function seedLabelTemplate(input: LabelTemplateInput): Promise<boolean>;
15
+ /** Apply a template declared in code; unchanged declarations write nothing. */
16
+ export declare function applyLabelTemplate(input: LabelTemplateInput): Promise<'applied' | 'unchanged'>;
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LabelTemplateConflictError = void 0;
4
+ exports.upsertLabelTemplate = upsertLabelTemplate;
5
+ exports.deleteLabelTemplate = deleteLabelTemplate;
6
+ exports.seedLabelTemplate = seedLabelTemplate;
7
+ exports.applyLabelTemplate = applyLabelTemplate;
8
+ const db_1 = require("../../../lib/db");
9
+ const types_1 = require("../../../types");
10
+ const scan_code_1 = require("../../scan-code");
11
+ const user_1 = require("../../user");
12
+ const media_1 = require("../media");
13
+ const read_1 = require("./read");
14
+ const sql_1 = require("./sql");
15
+ const validate_1 = require("./validate");
16
+ /** An API write raced another: the stored revision is not the one the caller read. */
17
+ class LabelTemplateConflictError extends Error {
18
+ constructor(name, revision) {
19
+ super(`label template "${name}" changed (now revision ${revision}); reload and try again`);
20
+ this.status = 409;
21
+ this.name = 'LabelTemplateConflictError';
22
+ }
23
+ }
24
+ exports.LabelTemplateConflictError = LabelTemplateConflictError;
25
+ async function validated(input) {
26
+ const [scheme, rules, identityKeys] = await Promise.all([
27
+ (0, scan_code_1.getScanScheme)(input.scheme_version),
28
+ (0, scan_code_1.listScanRules)(input.scheme_version),
29
+ (0, user_1.getIdentityPropertyKeys)(),
30
+ ]);
31
+ (0, validate_1.assertValidTemplate)(input, { scheme, rules, identityKeys, mediaIds: (0, media_1.labelMediaPresets)().map((m) => m.id) });
32
+ return { ...input, sensitive: scheme.kind === types_1.SCAN_SCHEME_KINDS.IDENTITY || !!input.sensitive };
33
+ }
34
+ function params(input, source) {
35
+ return [
36
+ input.name,
37
+ input.scheme_version,
38
+ input.title,
39
+ input.description ?? null,
40
+ JSON.stringify(input.codes.map((c) => ({ category: c.category, caption: c.caption ?? null, tone: c.tone }))),
41
+ JSON.stringify({ title: input.text?.title ?? '', lines: input.text?.lines ?? [] }),
42
+ input.symbology ?? 'code128',
43
+ input.human_readable ?? true,
44
+ input.media ?? null,
45
+ input.sensitive,
46
+ input.enabled ?? true,
47
+ source,
48
+ ];
49
+ }
50
+ /**
51
+ * Create or replace a template from the API. With `expectedRevision`, the
52
+ * write lands only on that revision; otherwise LabelTemplateConflictError.
53
+ */
54
+ async function upsertLabelTemplate(input, expectedRevision) {
55
+ const row = await validated(input);
56
+ const { rows } = await (0, db_1.getPool)().query(sql_1.UPSERT_TEMPLATE, [...params(row, 'api'), expectedRevision ?? null]);
57
+ if (rows[0])
58
+ return (0, read_1.mapTemplate)(rows[0]);
59
+ const current = await (0, db_1.getPool)().query(sql_1.GET_TEMPLATE, [input.name]);
60
+ throw new LabelTemplateConflictError(input.name, current.rows[0]?.revision ?? 0);
61
+ }
62
+ async function deleteLabelTemplate(name) {
63
+ const { rowCount } = await (0, db_1.getPool)().query(sql_1.DELETE_TEMPLATE, [name]);
64
+ return (rowCount ?? 0) > 0;
65
+ }
66
+ /** Insert a template only when absent (database-owned configuration). */
67
+ async function seedLabelTemplate(input) {
68
+ const { rowCount } = await (0, db_1.getPool)().query(sql_1.SEED_TEMPLATE, params(await validated(input), 'api'));
69
+ return (rowCount ?? 0) > 0;
70
+ }
71
+ /** Apply a template declared in code; unchanged declarations write nothing. */
72
+ async function applyLabelTemplate(input) {
73
+ const { rowCount } = await (0, db_1.getPool)().query(sql_1.APPLY_TEMPLATE, params(await validated(input), 'code'));
74
+ return (rowCount ?? 0) > 0 ? 'applied' : 'unchanged';
75
+ }
@@ -0,0 +1,9 @@
1
+ import type { ScanScheme } from '../../types';
2
+ /** Characters in a minted delimited credential when the scheme sets no target_length (about 50 bits). */
3
+ export declare const DEFAULT_IDENTITY_TOKEN_LENGTH = 10;
4
+ /**
5
+ * A random credential for the scheme: Crockford base32 of the scheme's
6
+ * target_length (default 10) when delimited, that many digits when fixed.
7
+ * The scheme prefix is added when the code is composed, never stored.
8
+ */
9
+ export declare function mintIdentityToken(scheme: Pick<ScanScheme, 'encoding' | 'target_length'>): string;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ // New identity credentials, minted to fit the scheme's encoding.
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.DEFAULT_IDENTITY_TOKEN_LENGTH = void 0;
5
+ exports.mintIdentityToken = mintIdentityToken;
6
+ const crypto_1 = require("crypto");
7
+ const errors_1 = require("./errors");
8
+ const CROCKFORD = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';
9
+ /** Characters in a minted delimited credential when the scheme sets no target_length (about 50 bits). */
10
+ exports.DEFAULT_IDENTITY_TOKEN_LENGTH = 10;
11
+ /**
12
+ * A random credential for the scheme: Crockford base32 of the scheme's
13
+ * target_length (default 10) when delimited, that many digits when fixed.
14
+ * The scheme prefix is added when the code is composed, never stored.
15
+ */
16
+ function mintIdentityToken(scheme) {
17
+ if (scheme.encoding === 'delimited') {
18
+ const bytes = (0, crypto_1.randomBytes)(scheme.target_length ?? exports.DEFAULT_IDENTITY_TOKEN_LENGTH);
19
+ return Array.from(bytes, (b) => CROCKFORD[b % 32]).join('');
20
+ }
21
+ if (scheme.encoding === 'fixed') {
22
+ const length = scheme.target_length ?? 0;
23
+ if (length < 1)
24
+ throw new errors_1.LabelRequestError(400, 'the scheme has no target length');
25
+ return Array.from({ length }, () => String((0, crypto_1.randomInt)(10))).join('');
26
+ }
27
+ throw new errors_1.LabelRequestError(400, `credentials are minted for fixed and delimited schemes, not ${scheme.encoding}`);
28
+ }
@@ -0,0 +1,4 @@
1
+ import { type ScanRule, type ScanScheme } from '../../types';
2
+ import type { LabelContent, LabelWarning } from '../../shared/labels/types';
3
+ import type { LabelTarget, LabelTemplate } from '../../types/labels';
4
+ export declare function verifyLabels(template: LabelTemplate, scheme: ScanScheme, schemes: ScanScheme[], rules: ScanRule[], targets: LabelTarget[], contents: LabelContent[]): LabelWarning[];
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ // Flags labels that would fail on the floor: a code that does not parse back,
3
+ // a disabled rule or scheme, or a target that names nothing today.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.verifyLabels = verifyLabels;
6
+ const parse_1 = require("../../shared/scan-code/parse");
7
+ const types_1 = require("../../types");
8
+ function verifyLabels(template, scheme, schemes, rules, targets, contents) {
9
+ const identity = scheme.kind === types_1.SCAN_SCHEME_KINDS.IDENTITY;
10
+ const warnings = [];
11
+ if (!scheme.enabled) {
12
+ contents.forEach((_c, index) => warnings.push({ index, kind: 'unparseable', detail: `scheme ${scheme.version} is disabled; its codes do not scan` }));
13
+ return warnings;
14
+ }
15
+ const disabled = template.codes.filter((c) => !rules.find((r) => r.category === c.category)?.enabled);
16
+ contents.forEach((content, index) => {
17
+ for (const c of disabled) {
18
+ warnings.push({ index, kind: 'rule_disabled', detail: `the rule for category ${c.category} is disabled; that code does nothing when scanned` });
19
+ }
20
+ for (const { code } of content.codes) {
21
+ const parsed = (0, parse_1.parseScanCode)(code, schemes);
22
+ const same = parsed.ok && parsed.parsed.version === scheme.version && parsed.parsed.target === targets[index].target;
23
+ if (!same) {
24
+ warnings.push({
25
+ index, kind: 'unparseable',
26
+ detail: identity ? 'a badge code does not read back as this scheme' : `${code} does not read back as scheme ${scheme.version}`,
27
+ });
28
+ }
29
+ }
30
+ if (targets[index].resolved === false) {
31
+ warnings.push({
32
+ index, kind: 'unresolved',
33
+ detail: identity ? 'the badge holder is not an active user' : `${targets[index].target} names no row today`,
34
+ });
35
+ }
36
+ });
37
+ return warnings;
38
+ }
@@ -4,6 +4,9 @@ import { type ScanScheme, type ScanStep } from '../../types';
4
4
  * problem — a bad scheme silently misparsing every scan is far worse
5
5
  * than a loud upsert failure.
6
6
  */
7
+ /** Generated badges on a delimited identity scheme: long enough to resist guessing, short enough to scan. */
8
+ export declare const IDENTITY_TOKEN_MIN_LENGTH = 8;
9
+ export declare const IDENTITY_TOKEN_MAX_LENGTH = 64;
7
10
  export declare function assertValidScheme(scheme: Partial<ScanScheme>): void;
8
11
  /**
9
12
  * A scheme must read codes no other scheme reads. Delimited and fixed