@hotmeshio/long-tail 0.22.1 → 0.22.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (331) hide show
  1. package/build/api/escalations/accumulate.js +38 -19
  2. package/build/api/escalations/lookups.d.ts +9 -2
  3. package/build/api/escalations/lookups.js +15 -3
  4. package/build/api/escalations/metadata.d.ts +2 -0
  5. package/build/api/escalations/metadata.js +9 -0
  6. package/build/api/escalations/resolve-batch.js +18 -11
  7. package/build/api/roles.js +4 -0
  8. package/build/api/scan-codes/badge-policy.d.ts +10 -0
  9. package/build/api/scan-codes/badge-policy.js +72 -0
  10. package/build/api/scan-codes/choice.js +16 -10
  11. package/build/api/scan-codes/context.d.ts +45 -1
  12. package/build/api/scan-codes/context.js +51 -3
  13. package/build/api/scan-codes/execute.js +73 -35
  14. package/build/api/scan-codes/grant.d.ts +27 -0
  15. package/build/api/scan-codes/grant.js +67 -0
  16. package/build/api/scan-codes/hold.d.ts +10 -0
  17. package/build/api/scan-codes/hold.js +98 -0
  18. package/build/api/scan-codes/identity.d.ts +5 -2
  19. package/build/api/scan-codes/identity.js +26 -8
  20. package/build/api/scan-codes/locate.js +4 -0
  21. package/build/api/scan-codes/present.d.ts +1 -1
  22. package/build/api/scan-codes/present.js +43 -0
  23. package/build/api/scan-codes/subject.d.ts +15 -0
  24. package/build/api/scan-codes/subject.js +68 -0
  25. package/build/api/scan-codes/verb-accumulate.d.ts +24 -0
  26. package/build/api/scan-codes/verb-accumulate.js +151 -0
  27. package/build/api/scan-codes/verb-fill.d.ts +6 -0
  28. package/build/api/scan-codes/verb-fill.js +155 -0
  29. package/build/api/scan-codes/verb-into-subject.d.ts +12 -0
  30. package/build/api/scan-codes/verb-into-subject.js +157 -0
  31. package/build/api/scan-codes/verbs-subject.d.ts +33 -0
  32. package/build/api/scan-codes/verbs-subject.js +247 -0
  33. package/build/api/scan-codes/verbs.d.ts +11 -29
  34. package/build/api/scan-codes/verbs.js +51 -131
  35. package/build/index.d.ts +1 -0
  36. package/build/index.js +9 -2
  37. package/build/lib/db/schemas/037_scan_gtin_and_subject_grants.sql +27 -0
  38. package/build/routes/escalations/acting.d.ts +5 -0
  39. package/build/routes/escalations/acting.js +8 -1
  40. package/build/routes/scan-codes.js +3 -0
  41. package/build/sdk/index.d.ts +1 -0
  42. package/build/services/escalation/claim-asserted.d.ts +10 -0
  43. package/build/services/escalation/claim-asserted.js +64 -0
  44. package/build/services/escalation/facets.d.ts +3 -1
  45. package/build/services/escalation/facets.js +7 -3
  46. package/build/services/escalation/index.d.ts +1 -0
  47. package/build/services/escalation/index.js +3 -1
  48. package/build/services/iam/acting-identity.d.ts +29 -4
  49. package/build/services/iam/acting-identity.js +60 -17
  50. package/build/services/iam/ephemeral.d.ts +21 -0
  51. package/build/services/iam/ephemeral.js +32 -1
  52. package/build/services/iam/sql.d.ts +10 -0
  53. package/build/services/iam/sql.js +32 -3
  54. package/build/services/knowledge/lookup-cache.d.ts +16 -4
  55. package/build/services/knowledge/lookup-cache.js +53 -20
  56. package/build/services/knowledge/lookup-refs.d.ts +3 -2
  57. package/build/services/knowledge/lookup-refs.js +6 -4
  58. package/build/services/knowledge/sql.d.ts +2 -0
  59. package/build/services/knowledge/sql.js +9 -1
  60. package/build/services/mcp/server-tools.js +1 -1
  61. package/build/services/orchestrator/condition.d.ts +13 -10
  62. package/build/services/orchestrator/condition.js +8 -6
  63. package/build/services/role/badge-grant.d.ts +5 -0
  64. package/build/services/role/badge-grant.js +36 -0
  65. package/build/services/role/seed.js +5 -0
  66. package/build/services/role/types.d.ts +14 -0
  67. package/build/services/role/types.js +5 -0
  68. package/build/services/scan-code/index.d.ts +3 -2
  69. package/build/services/scan-code/index.js +8 -1
  70. package/build/services/scan-code/parse.d.ts +23 -20
  71. package/build/services/scan-code/parse.js +45 -90
  72. package/build/services/scan-code/read.js +1 -0
  73. package/build/services/scan-code/sql.d.ts +3 -3
  74. package/build/services/scan-code/sql.js +11 -8
  75. package/build/services/scan-code/validate-facts.d.ts +5 -0
  76. package/build/services/scan-code/validate-facts.js +24 -0
  77. package/build/services/scan-code/validate-query.d.ts +8 -0
  78. package/build/services/scan-code/validate-query.js +36 -0
  79. package/build/services/scan-code/validate-subject.d.ts +7 -0
  80. package/build/services/scan-code/validate-subject.js +185 -0
  81. package/build/services/scan-code/validate.d.ts +7 -0
  82. package/build/services/scan-code/validate.js +103 -18
  83. package/build/services/scan-code/write.d.ts +1 -0
  84. package/build/services/scan-code/write.js +9 -3
  85. package/build/shared/form-validation/field-validator.js +4 -0
  86. package/build/shared/form-validation/index.d.ts +1 -0
  87. package/build/shared/form-validation/index.js +1 -0
  88. package/build/shared/form-validation/x-lt-scan.d.ts +52 -0
  89. package/build/shared/form-validation/x-lt-scan.js +166 -0
  90. package/build/shared/scan-code/gtin.d.ts +11 -0
  91. package/build/shared/scan-code/gtin.js +38 -0
  92. package/build/shared/scan-code/index.d.ts +2 -0
  93. package/build/shared/scan-code/index.js +11 -0
  94. package/build/shared/scan-code/parse.d.ts +46 -0
  95. package/build/shared/scan-code/parse.js +133 -0
  96. package/build/system/mcp-servers/admin/scan-codes.js +10 -4
  97. package/build/system/mcp-servers/admin/schemas.d.ts +939 -28
  98. package/build/system/mcp-servers/admin/schemas.js +72 -6
  99. package/build/system/mcp-servers/human-queue-schemas.d.ts +6 -6
  100. package/build/system/seed/tool-manifests-admin.d.ts +202 -1
  101. package/build/system/seed/tool-manifests-admin.js +2 -2
  102. package/build/tsconfig.tsbuildinfo +1 -1
  103. package/build/types/escalation.d.ts +16 -8
  104. package/build/types/escalation.js +18 -7
  105. package/build/types/index.d.ts +4 -4
  106. package/build/types/index.js +10 -1
  107. package/build/types/scan-code/constants.d.ts +182 -0
  108. package/build/types/{scan-code.js → scan-code/constants.js} +72 -11
  109. package/build/types/scan-code/index.d.ts +3 -0
  110. package/build/types/scan-code/index.js +17 -0
  111. package/build/types/scan-code/response.d.ts +145 -0
  112. package/build/types/scan-code/response.js +2 -0
  113. package/build/types/scan-code/rule.d.ts +229 -0
  114. package/build/types/scan-code/rule.js +2 -0
  115. package/build/types/startup.d.ts +3 -1
  116. package/dashboard/dist/assets/{AdminDashboard-BbWve-Ax.js → AdminDashboard-hI5-kKpL.js} +2 -2
  117. package/dashboard/dist/assets/{AdminDashboard-BbWve-Ax.js.map → AdminDashboard-hI5-kKpL.js.map} +1 -1
  118. package/dashboard/dist/assets/{AgentConfigPage-M-9eTKhP.js → AgentConfigPage-DetU4HZe.js} +2 -2
  119. package/dashboard/dist/assets/{AgentConfigPage-M-9eTKhP.js.map → AgentConfigPage-DetU4HZe.js.map} +1 -1
  120. package/dashboard/dist/assets/{AgentDetailPage-CsakSlx5.js → AgentDetailPage-DrGXo8KQ.js} +3 -3
  121. package/dashboard/dist/assets/{AgentDetailPage-CsakSlx5.js.map → AgentDetailPage-DrGXo8KQ.js.map} +1 -1
  122. package/dashboard/dist/assets/{AgentsPage-Cj_cRTT1.js → AgentsPage-D4md5BzM.js} +2 -2
  123. package/dashboard/dist/assets/{AgentsPage-Cj_cRTT1.js.map → AgentsPage-D4md5BzM.js.map} +1 -1
  124. package/dashboard/dist/assets/{AvailableEscalationsPage-BXJmMBM1.js → AvailableEscalationsPage-B2bS2ZJy.js} +2 -2
  125. package/dashboard/dist/assets/{AvailableEscalationsPage-BXJmMBM1.js.map → AvailableEscalationsPage-B2bS2ZJy.js.map} +1 -1
  126. package/dashboard/dist/assets/{BotPicker-CGB16rYU.js → BotPicker-BXtey255.js} +2 -2
  127. package/dashboard/dist/assets/{BotPicker-CGB16rYU.js.map → BotPicker-BXtey255.js.map} +1 -1
  128. package/dashboard/dist/assets/{BulkAssignModal-MjxcU7N1.js → BulkAssignModal-CSL_PeZv.js} +2 -2
  129. package/dashboard/dist/assets/{BulkAssignModal-MjxcU7N1.js.map → BulkAssignModal-CSL_PeZv.js.map} +1 -1
  130. package/dashboard/dist/assets/CapabilitiesPage-5scufTHW.js +2 -0
  131. package/dashboard/dist/assets/{CapabilitiesPage-BxadotXn.js.map → CapabilitiesPage-5scufTHW.js.map} +1 -1
  132. package/dashboard/dist/assets/{CollapsibleSection-BBNpP-6h.js → CollapsibleSection-DjjDGxP_.js} +2 -2
  133. package/dashboard/dist/assets/{CollapsibleSection-BBNpP-6h.js.map → CollapsibleSection-DjjDGxP_.js.map} +1 -1
  134. package/dashboard/dist/assets/{ConfirmDeleteModal-D_kAbT_D.js → ConfirmDeleteModal-DJSmsHQM.js} +2 -2
  135. package/dashboard/dist/assets/{ConfirmDeleteModal-D_kAbT_D.js.map → ConfirmDeleteModal-DJSmsHQM.js.map} +1 -1
  136. package/dashboard/dist/assets/CountdownTimer-C5ZRYPfF.js +2 -0
  137. package/dashboard/dist/assets/{CountdownTimer-CI_JOAvk.js.map → CountdownTimer-C5ZRYPfF.js.map} +1 -1
  138. package/dashboard/dist/assets/{CredentialsPage-C9OA1Q2J.js → CredentialsPage-CV6e60yC.js} +2 -2
  139. package/dashboard/dist/assets/{CredentialsPage-C9OA1Q2J.js.map → CredentialsPage-CV6e60yC.js.map} +1 -1
  140. package/dashboard/dist/assets/{CronLabel-sxLLBf2I.js → CronLabel-CnqhqW0B.js} +2 -2
  141. package/dashboard/dist/assets/{CronLabel-sxLLBf2I.js.map → CronLabel-CnqhqW0B.js.map} +1 -1
  142. package/dashboard/dist/assets/{ElapsedCell-jH9m8Dgl.js → ElapsedCell-C1IOn-tj.js} +2 -2
  143. package/dashboard/dist/assets/{ElapsedCell-jH9m8Dgl.js.map → ElapsedCell-C1IOn-tj.js.map} +1 -1
  144. package/dashboard/dist/assets/{EntityTimelinePanel-Dl3Nr2kk.js → EntityTimelinePanel-Dz6Liig4.js} +2 -2
  145. package/dashboard/dist/assets/{EntityTimelinePanel-Dl3Nr2kk.js.map → EntityTimelinePanel-Dz6Liig4.js.map} +1 -1
  146. package/dashboard/dist/assets/{EscalationListSchemaPage-DAK6It5J.js → EscalationListSchemaPage-bgdmLmrh.js} +3 -3
  147. package/dashboard/dist/assets/{EscalationListSchemaPage-DAK6It5J.js.map → EscalationListSchemaPage-bgdmLmrh.js.map} +1 -1
  148. package/dashboard/dist/assets/{EscalationListView-CAHbdxKR.js → EscalationListView-CrlD3ZGt.js} +2 -2
  149. package/dashboard/dist/assets/{EscalationListView-CAHbdxKR.js.map → EscalationListView-CrlD3ZGt.js.map} +1 -1
  150. package/dashboard/dist/assets/{EscalationSchemaPage-DotfAMCL.js → EscalationSchemaPage-dxXO_T3t.js} +3 -3
  151. package/dashboard/dist/assets/{EscalationSchemaPage-DotfAMCL.js.map → EscalationSchemaPage-dxXO_T3t.js.map} +1 -1
  152. package/dashboard/dist/assets/{EscalationTimeline-DqmFydnU.js → EscalationTimeline-C3WQZQuM.js} +2 -2
  153. package/dashboard/dist/assets/{EscalationTimeline-DqmFydnU.js.map → EscalationTimeline-C3WQZQuM.js.map} +1 -1
  154. package/dashboard/dist/assets/{EscalationTitleSelect-BpRquguO.js → EscalationTitleSelect-CTtcETUO.js} +2 -2
  155. package/dashboard/dist/assets/{EscalationTitleSelect-BpRquguO.js.map → EscalationTitleSelect-CTtcETUO.js.map} +1 -1
  156. package/dashboard/dist/assets/{EscalationsOverview-DtGOqnP4.js → EscalationsOverview-DAjZ7JY2.js} +2 -2
  157. package/dashboard/dist/assets/{EscalationsOverview-DtGOqnP4.js.map → EscalationsOverview-DAjZ7JY2.js.map} +1 -1
  158. package/dashboard/dist/assets/{EventTable-DSHqKyX2.js → EventTable-B72DQP_v.js} +2 -2
  159. package/dashboard/dist/assets/{EventTable-DSHqKyX2.js.map → EventTable-B72DQP_v.js.map} +1 -1
  160. package/dashboard/dist/assets/{FilterBar-Dxd0wNSW.js → FilterBar-CCTaA_LH.js} +2 -2
  161. package/dashboard/dist/assets/{FilterBar-Dxd0wNSW.js.map → FilterBar-CCTaA_LH.js.map} +1 -1
  162. package/dashboard/dist/assets/GrantScopeField-BzWGzBfA.js +2 -0
  163. package/dashboard/dist/assets/GrantScopeField-BzWGzBfA.js.map +1 -0
  164. package/dashboard/dist/assets/{GraphInvokePage-ChqqGkro.js → GraphInvokePage-CAsCgFo3.js} +2 -2
  165. package/dashboard/dist/assets/{GraphInvokePage-ChqqGkro.js.map → GraphInvokePage-CAsCgFo3.js.map} +1 -1
  166. package/dashboard/dist/assets/{HomePage-ByKesG8w.js → HomePage-DseE_iSr.js} +2 -2
  167. package/dashboard/dist/assets/{HomePage-ByKesG8w.js.map → HomePage-DseE_iSr.js.map} +1 -1
  168. package/dashboard/dist/assets/{ListToolbar-Ddz_S2av.js → ListToolbar-1zdqnjW6.js} +2 -2
  169. package/dashboard/dist/assets/{ListToolbar-Ddz_S2av.js.map → ListToolbar-1zdqnjW6.js.map} +1 -1
  170. package/dashboard/dist/assets/{McpOverview-CVe13tEv.js → McpOverview-DS_JXDW5.js} +2 -2
  171. package/dashboard/dist/assets/{McpOverview-CVe13tEv.js.map → McpOverview-DS_JXDW5.js.map} +1 -1
  172. package/dashboard/dist/assets/{McpQueryDetailPage-BQYF2Mjq.js → McpQueryDetailPage-BeMUGcv3.js} +2 -2
  173. package/dashboard/dist/assets/{McpQueryDetailPage-BQYF2Mjq.js.map → McpQueryDetailPage-BeMUGcv3.js.map} +1 -1
  174. package/dashboard/dist/assets/{McpQueryPage-DZi5lm7s.js → McpQueryPage-CeiLO_LR.js} +2 -2
  175. package/dashboard/dist/assets/{McpQueryPage-DZi5lm7s.js.map → McpQueryPage-CeiLO_LR.js.map} +1 -1
  176. package/dashboard/dist/assets/{McpRunDetailPage-DreARTE1.js → McpRunDetailPage-DYp1uZK2.js} +2 -2
  177. package/dashboard/dist/assets/{McpRunDetailPage-DreARTE1.js.map → McpRunDetailPage-DYp1uZK2.js.map} +1 -1
  178. package/dashboard/dist/assets/{McpRunsPage-DmO0YVhT.js → McpRunsPage-VeaDzcL4.js} +2 -2
  179. package/dashboard/dist/assets/{McpRunsPage-DmO0YVhT.js.map → McpRunsPage-VeaDzcL4.js.map} +1 -1
  180. package/dashboard/dist/assets/{OperationsPage-DpjCO85T.js → OperationsPage-DK2mgaXf.js} +2 -2
  181. package/dashboard/dist/assets/{OperationsPage-DpjCO85T.js.map → OperationsPage-DK2mgaXf.js.map} +1 -1
  182. package/dashboard/dist/assets/{OperatorDashboard-Vv_MEBkv.js → OperatorDashboard-BNjLF0f7.js} +2 -2
  183. package/dashboard/dist/assets/{OperatorDashboard-Vv_MEBkv.js.map → OperatorDashboard-BNjLF0f7.js.map} +1 -1
  184. package/dashboard/dist/assets/{PersonaDetailPage-CW-2uBHY.js → PersonaDetailPage-IQ2fZLa6.js} +2 -2
  185. package/dashboard/dist/assets/{PersonaDetailPage-CW-2uBHY.js.map → PersonaDetailPage-IQ2fZLa6.js.map} +1 -1
  186. package/dashboard/dist/assets/{PersonasPage-CO6yYQdm.js → PersonasPage-DpGFEcU-.js} +2 -2
  187. package/dashboard/dist/assets/{PersonasPage-CO6yYQdm.js.map → PersonasPage-DpGFEcU-.js.map} +1 -1
  188. package/dashboard/dist/assets/{PortalPage-DcNqhBlg.js → PortalPage-D07xyvG_.js} +2 -2
  189. package/dashboard/dist/assets/{PortalPage-DcNqhBlg.js.map → PortalPage-D07xyvG_.js.map} +1 -1
  190. package/dashboard/dist/assets/{ProcessDetailPage-BuipGZcC.js → ProcessDetailPage-t8EEYSMk.js} +2 -2
  191. package/dashboard/dist/assets/{ProcessDetailPage-BuipGZcC.js.map → ProcessDetailPage-t8EEYSMk.js.map} +1 -1
  192. package/dashboard/dist/assets/{ProcessesListPage-D9DYntvl.js → ProcessesListPage-BDUXLFdb.js} +2 -2
  193. package/dashboard/dist/assets/{ProcessesListPage-D9DYntvl.js.map → ProcessesListPage-BDUXLFdb.js.map} +1 -1
  194. package/dashboard/dist/assets/ResolverForm-BwWOYv_Z.js +8 -0
  195. package/dashboard/dist/assets/ResolverForm-BwWOYv_Z.js.map +1 -0
  196. package/dashboard/dist/assets/RoleDetailPage-zMF3x2xi.js +8 -0
  197. package/dashboard/dist/assets/RoleDetailPage-zMF3x2xi.js.map +1 -0
  198. package/dashboard/dist/assets/{RolesPage-0QJOBSzF.js → RolesPage-CEBp_PpL.js} +2 -2
  199. package/dashboard/dist/assets/{RolesPage-0QJOBSzF.js.map → RolesPage-CEBp_PpL.js.map} +1 -1
  200. package/dashboard/dist/assets/{RunAsSelector-Dh4lyyRo.js → RunAsSelector-CC_EHN3z.js} +2 -2
  201. package/dashboard/dist/assets/{RunAsSelector-Dh4lyyRo.js.map → RunAsSelector-CC_EHN3z.js.map} +1 -1
  202. package/dashboard/dist/assets/ScanCodesPage-DD4uU-jY.js +2 -0
  203. package/dashboard/dist/assets/ScanCodesPage-DD4uU-jY.js.map +1 -0
  204. package/dashboard/dist/assets/ScanSchemeDetailPage-CUW8gYFh.js +2 -0
  205. package/dashboard/dist/assets/ScanSchemeDetailPage-CUW8gYFh.js.map +1 -0
  206. package/dashboard/dist/assets/ScanStationPage-DpO_ESuf.js +2 -0
  207. package/dashboard/dist/assets/ScanStationPage-DpO_ESuf.js.map +1 -0
  208. package/dashboard/dist/assets/{StickyPagination-BSUyf5ja.js → StickyPagination-cNqSDm5f.js} +2 -2
  209. package/dashboard/dist/assets/{StickyPagination-BSUyf5ja.js.map → StickyPagination-cNqSDm5f.js.map} +1 -1
  210. package/dashboard/dist/assets/{StreamMessageDetail--tp7l2Sd.js → StreamMessageDetail-C4oZqQdB.js} +2 -2
  211. package/dashboard/dist/assets/{StreamMessageDetail--tp7l2Sd.js.map → StreamMessageDetail-C4oZqQdB.js.map} +1 -1
  212. package/dashboard/dist/assets/{SwimlaneTimeline-CxBZ2THh.js → SwimlaneTimeline-BjBiV7GT.js} +2 -2
  213. package/dashboard/dist/assets/{SwimlaneTimeline-CxBZ2THh.js.map → SwimlaneTimeline-BjBiV7GT.js.map} +1 -1
  214. package/dashboard/dist/assets/{TaskDetailPage-BJ1QrmPH.js → TaskDetailPage-pO_AnVS1.js} +2 -2
  215. package/dashboard/dist/assets/{TaskDetailPage-BJ1QrmPH.js.map → TaskDetailPage-pO_AnVS1.js.map} +1 -1
  216. package/dashboard/dist/assets/{TasksListPage-5BydGWmt.js → TasksListPage-DKDHlWP7.js} +2 -2
  217. package/dashboard/dist/assets/{TasksListPage-5BydGWmt.js.map → TasksListPage-DKDHlWP7.js.map} +1 -1
  218. package/dashboard/dist/assets/{TimeAgo-CCnz84Y4.js → TimeAgo-D2qchUuJ.js} +2 -2
  219. package/dashboard/dist/assets/{TimeAgo-CCnz84Y4.js.map → TimeAgo-D2qchUuJ.js.map} +1 -1
  220. package/dashboard/dist/assets/{TimestampCell-D0ru7Lya.js → TimestampCell-DeswZGGo.js} +2 -2
  221. package/dashboard/dist/assets/{TimestampCell-D0ru7Lya.js.map → TimestampCell-DeswZGGo.js.map} +1 -1
  222. package/dashboard/dist/assets/{ToolTestPanel-3Kpofmen.js → ToolTestPanel-DJh7PIUa.js} +2 -2
  223. package/dashboard/dist/assets/{ToolTestPanel-3Kpofmen.js.map → ToolTestPanel-DJh7PIUa.js.map} +1 -1
  224. package/dashboard/dist/assets/{TopicDetailPage-BaBXD_AK.js → TopicDetailPage-CsgDJ4Z4.js} +2 -2
  225. package/dashboard/dist/assets/{TopicDetailPage-BaBXD_AK.js.map → TopicDetailPage-CsgDJ4Z4.js.map} +1 -1
  226. package/dashboard/dist/assets/{TopicsPage-Cnm1AAjh.js → TopicsPage-tBRZDVDN.js} +2 -2
  227. package/dashboard/dist/assets/{TopicsPage-Cnm1AAjh.js.map → TopicsPage-tBRZDVDN.js.map} +1 -1
  228. package/dashboard/dist/assets/{UserName-CXsdPiMZ.js → UserName-B-5JcDck.js} +2 -2
  229. package/dashboard/dist/assets/{UserName-CXsdPiMZ.js.map → UserName-B-5JcDck.js.map} +1 -1
  230. package/dashboard/dist/assets/{WorkflowExecutionPage-zx3AUJFd.js → WorkflowExecutionPage-BPHVnhp6.js} +2 -2
  231. package/dashboard/dist/assets/{WorkflowExecutionPage-zx3AUJFd.js.map → WorkflowExecutionPage-BPHVnhp6.js.map} +1 -1
  232. package/dashboard/dist/assets/{WorkflowsDashboard-DfAGK1l7.js → WorkflowsDashboard-CxLlfZmY.js} +2 -2
  233. package/dashboard/dist/assets/{WorkflowsDashboard-DfAGK1l7.js.map → WorkflowsDashboard-CxLlfZmY.js.map} +1 -1
  234. package/dashboard/dist/assets/{WorkflowsOverview-QIYvoa13.js → WorkflowsOverview-C4az5rwp.js} +2 -2
  235. package/dashboard/dist/assets/{WorkflowsOverview-QIYvoa13.js.map → WorkflowsOverview-C4az5rwp.js.map} +1 -1
  236. package/dashboard/dist/assets/{YamlWorkflowDetailPage-DGgO3hyB.js → YamlWorkflowDetailPage-BmhlAUFQ.js} +8 -8
  237. package/dashboard/dist/assets/{YamlWorkflowDetailPage-DGgO3hyB.js.map → YamlWorkflowDetailPage-BmhlAUFQ.js.map} +1 -1
  238. package/dashboard/dist/assets/{YamlWorkflowsPage-CEsHm0B9.js → YamlWorkflowsPage-CSbG5o2V.js} +2 -2
  239. package/dashboard/dist/assets/{YamlWorkflowsPage-CEsHm0B9.js.map → YamlWorkflowsPage-CSbG5o2V.js.map} +1 -1
  240. package/dashboard/dist/assets/{agents-v_HH3Rji.js → agents-BohEn7vw.js} +2 -2
  241. package/dashboard/dist/assets/{agents-v_HH3Rji.js.map → agents-BohEn7vw.js.map} +1 -1
  242. package/dashboard/dist/assets/{bots-bwvWYrXz.js → bots-BG2EO-Wi.js} +2 -2
  243. package/dashboard/dist/assets/{bots-bwvWYrXz.js.map → bots-BG2EO-Wi.js.map} +1 -1
  244. package/dashboard/dist/assets/{capabilities-D4vaw_nQ.js → capabilities-CeFrBmYX.js} +2 -2
  245. package/dashboard/dist/assets/{capabilities-D4vaw_nQ.js.map → capabilities-CeFrBmYX.js.map} +1 -1
  246. package/dashboard/dist/assets/{controlplane-CiiZ6LJF.js → controlplane-Dhvt8l8F.js} +2 -2
  247. package/dashboard/dist/assets/{controlplane-CiiZ6LJF.js.map → controlplane-Dhvt8l8F.js.map} +1 -1
  248. package/dashboard/dist/assets/{escalation-columns-Dv-MB3eC.js → escalation-columns-BWMNxImp.js} +2 -2
  249. package/dashboard/dist/assets/{escalation-columns-Dv-MB3eC.js.map → escalation-columns-BWMNxImp.js.map} +1 -1
  250. package/dashboard/dist/assets/{index-CzjUgFt_.js → index-Bd_dgyfJ.js} +2 -2
  251. package/dashboard/dist/assets/{index-CzjUgFt_.js.map → index-Bd_dgyfJ.js.map} +1 -1
  252. package/dashboard/dist/assets/{index-IJmtbuLh.js → index-C8VlM2Oe.js} +2 -2
  253. package/dashboard/dist/assets/{index-IJmtbuLh.js.map → index-C8VlM2Oe.js.map} +1 -1
  254. package/dashboard/dist/assets/{index-CcuvGdvf.js → index-CiqSVDga.js} +2 -2
  255. package/dashboard/dist/assets/{index-CcuvGdvf.js.map → index-CiqSVDga.js.map} +1 -1
  256. package/dashboard/dist/assets/{index-C3WutFpT.js → index-Cl_YXEdp.js} +2 -2
  257. package/dashboard/dist/assets/{index-C3WutFpT.js.map → index-Cl_YXEdp.js.map} +1 -1
  258. package/dashboard/dist/assets/index-CtZWpy22.js +2 -0
  259. package/dashboard/dist/assets/index-CtZWpy22.js.map +1 -0
  260. package/dashboard/dist/assets/{index-CjenRVX_.js → index-D90D9y0J.js} +2 -2
  261. package/dashboard/dist/assets/{index-CjenRVX_.js.map → index-D90D9y0J.js.map} +1 -1
  262. package/dashboard/dist/assets/{index-BLB77tc8.js → index-DABkM7s-.js} +2 -2
  263. package/dashboard/dist/assets/{index-BLB77tc8.js.map → index-DABkM7s-.js.map} +1 -1
  264. package/dashboard/dist/assets/index-Dbwu51xm.js +3 -0
  265. package/dashboard/dist/assets/index-Dbwu51xm.js.map +1 -0
  266. package/dashboard/dist/assets/{index-2tzsxFat.js → index-Dc3Om6G3.js} +2 -2
  267. package/dashboard/dist/assets/{index-2tzsxFat.js.map → index-Dc3Om6G3.js.map} +1 -1
  268. package/dashboard/dist/assets/{index-D2VKBMng.js → index-Dc_zWK23.js} +2 -2
  269. package/dashboard/dist/assets/{index-D2VKBMng.js.map → index-Dc_zWK23.js.map} +1 -1
  270. package/dashboard/dist/assets/index-DcppjzP5.css +1 -0
  271. package/dashboard/dist/assets/{index-C_ISDOWJ.js → index-Y-bdW8vo.js} +2 -2
  272. package/dashboard/dist/assets/{index-C_ISDOWJ.js.map → index-Y-bdW8vo.js.map} +1 -1
  273. package/dashboard/dist/assets/{index-C4Lce2ET.js → index-dYKgd06u.js} +3 -3
  274. package/dashboard/dist/assets/{index-C4Lce2ET.js.map → index-dYKgd06u.js.map} +1 -1
  275. package/dashboard/dist/assets/index-fUsx_gYx.js +67 -0
  276. package/dashboard/dist/assets/index-fUsx_gYx.js.map +1 -0
  277. package/dashboard/dist/assets/{knowledge-D1YP2NzS.js → knowledge-CCcTidNV.js} +2 -2
  278. package/dashboard/dist/assets/{knowledge-D1YP2NzS.js.map → knowledge-CCcTidNV.js.map} +1 -1
  279. package/dashboard/dist/assets/{mcp-Bb5psC61.js → mcp-CLA1z7Pg.js} +2 -2
  280. package/dashboard/dist/assets/{mcp-Bb5psC61.js.map → mcp-CLA1z7Pg.js.map} +1 -1
  281. package/dashboard/dist/assets/{mcp-query-D5jUdZwN.js → mcp-query-CWG0WMAs.js} +2 -2
  282. package/dashboard/dist/assets/{mcp-query-D5jUdZwN.js.map → mcp-query-CWG0WMAs.js.map} +1 -1
  283. package/dashboard/dist/assets/metadata-display-B7X5hGxG.js +2 -0
  284. package/dashboard/dist/assets/metadata-display-B7X5hGxG.js.map +1 -0
  285. package/dashboard/dist/assets/{personas-CDndbkp4.js → personas-8jURIzx6.js} +2 -2
  286. package/dashboard/dist/assets/{personas-CDndbkp4.js.map → personas-8jURIzx6.js.map} +1 -1
  287. package/dashboard/dist/assets/{pipelines-Dq3kNhKu.js → pipelines-hVVRAXqG.js} +2 -2
  288. package/dashboard/dist/assets/{pipelines-Dq3kNhKu.js.map → pipelines-hVVRAXqG.js.map} +1 -1
  289. package/dashboard/dist/assets/{tasks-BlpDsWCy.js → tasks-BE1O57Bf.js} +2 -2
  290. package/dashboard/dist/assets/{tasks-BlpDsWCy.js.map → tasks-BE1O57Bf.js.map} +1 -1
  291. package/dashboard/dist/assets/{topics-C0YaR9fu.js → topics-Bg96Wp1r.js} +2 -2
  292. package/dashboard/dist/assets/{topics-C0YaR9fu.js.map → topics-Bg96Wp1r.js.map} +1 -1
  293. package/dashboard/dist/assets/{useDebouncedValue-B-KC5ba3.js → useDebouncedValue-DmEveyEy.js} +2 -2
  294. package/dashboard/dist/assets/{useDebouncedValue-B-KC5ba3.js.map → useDebouncedValue-DmEveyEy.js.map} +1 -1
  295. package/dashboard/dist/assets/{useNamespace-Dkr5g2Ac.js → useNamespace-DHgkzIuL.js} +2 -2
  296. package/dashboard/dist/assets/{useNamespace-Dkr5g2Ac.js.map → useNamespace-DHgkzIuL.js.map} +1 -1
  297. package/dashboard/dist/assets/{useYamlActivityEvents-BANBOshA.js → useYamlActivityEvents-RU0PvU8S.js} +2 -2
  298. package/dashboard/dist/assets/{useYamlActivityEvents-BANBOshA.js.map → useYamlActivityEvents-RU0PvU8S.js.map} +1 -1
  299. package/dashboard/dist/assets/{yaml-workflows-BLYoJfmB.js → yaml-workflows-DQWE9ijc.js} +2 -2
  300. package/dashboard/dist/assets/{yaml-workflows-BLYoJfmB.js.map → yaml-workflows-DQWE9ijc.js.map} +1 -1
  301. package/dashboard/dist/index.html +2 -2
  302. package/docs/dashboard.md +1 -1
  303. package/docs/hitl/lookups.md +27 -18
  304. package/docs/hitl/x-lt-scan.md +51 -0
  305. package/docs/hitl/x-lt-validation.md +1 -1
  306. package/docs/hitl/x-lt-widget.md +1 -1
  307. package/docs/hitl-guide.md +3 -1
  308. package/docs/scan-codes.md +303 -33
  309. package/package.json +1 -1
  310. package/build/types/scan-code.d.ts +0 -317
  311. package/dashboard/dist/assets/CapabilitiesPage-BxadotXn.js +0 -2
  312. package/dashboard/dist/assets/CountdownTimer-CI_JOAvk.js +0 -2
  313. package/dashboard/dist/assets/ResolverForm-BVG8X0sS.js +0 -8
  314. package/dashboard/dist/assets/ResolverForm-BVG8X0sS.js.map +0 -1
  315. package/dashboard/dist/assets/RoleDetailPage-KCXDqoJz.js +0 -8
  316. package/dashboard/dist/assets/RoleDetailPage-KCXDqoJz.js.map +0 -1
  317. package/dashboard/dist/assets/ScanCodesPage-CUhCz-Yr.js +0 -2
  318. package/dashboard/dist/assets/ScanCodesPage-CUhCz-Yr.js.map +0 -1
  319. package/dashboard/dist/assets/ScanSchemeDetailPage-qzXKNqJK.js +0 -2
  320. package/dashboard/dist/assets/ScanSchemeDetailPage-qzXKNqJK.js.map +0 -1
  321. package/dashboard/dist/assets/ScanStationPage-D8e8cG3t.js +0 -2
  322. package/dashboard/dist/assets/ScanStationPage-D8e8cG3t.js.map +0 -1
  323. package/dashboard/dist/assets/index-CT-FN6CW.js +0 -3
  324. package/dashboard/dist/assets/index-CT-FN6CW.js.map +0 -1
  325. package/dashboard/dist/assets/index-D6pBLZFu.js +0 -2
  326. package/dashboard/dist/assets/index-D6pBLZFu.js.map +0 -1
  327. package/dashboard/dist/assets/index-Dh8MJl3L.css +0 -1
  328. package/dashboard/dist/assets/index-N71QQ3J5.js +0 -67
  329. package/dashboard/dist/assets/index-N71QQ3J5.js.map +0 -1
  330. package/dashboard/dist/assets/metadata-display-COo3mMCr.js +0 -2
  331. package/dashboard/dist/assets/metadata-display-COo3mMCr.js.map +0 -1
@@ -1,10 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.assertValidScheme = assertValidScheme;
4
+ exports.assertSchemesCoexist = assertSchemesCoexist;
4
5
  exports.assertValidIdentityRule = assertValidIdentityRule;
5
6
  exports.assertValidSteps = assertValidSteps;
6
7
  const types_1 = require("../../types");
8
+ const scan_code_1 = require("../../shared/scan-code");
7
9
  const facet_sql_1 = require("../escalation/facet-sql");
10
+ const validate_subject_1 = require("./validate-subject");
11
+ const validate_query_1 = require("./validate-query");
12
+ const validate_facts_1 = require("./validate-facts");
8
13
  const VALID_VERBS = new Set(Object.values(types_1.SCAN_VERBS));
9
14
  /** Double-scan selection tokens — short, label-printable, never scheme-shaped. */
10
15
  const CHOICE_CODE = /^[A-Za-z0-9_-]{1,32}$/;
@@ -22,6 +27,12 @@ function assertValidScheme(scheme) {
22
27
  if (!scheme.target_facet)
23
28
  throw new Error('scheme target_facet is required');
24
29
  const encoding = scheme.encoding ?? types_1.SCAN_ENCODINGS.FIXED;
30
+ if (!Object.values(types_1.SCAN_ENCODINGS).includes(encoding)) {
31
+ throw new Error(`unknown scheme encoding "${encoding}"`);
32
+ }
33
+ if (encoding === types_1.SCAN_ENCODINGS.GTIN && (scheme.kind ?? types_1.SCAN_SCHEME_KINDS.ACTION) !== types_1.SCAN_SCHEME_KINDS.ACTION) {
34
+ throw new Error('gtin encoding applies only to action schemes');
35
+ }
25
36
  if (encoding === types_1.SCAN_ENCODINGS.FIXED) {
26
37
  if (!Number.isInteger(scheme.target_length) || scheme.target_length < 1) {
27
38
  throw new Error('fixed encoding requires a positive integer target_length');
@@ -48,11 +59,50 @@ function assertValidScheme(scheme) {
48
59
  if (!Number.isInteger(scheme.grant_max_uses ?? 0) || (scheme.grant_max_uses ?? 0) < 0) {
49
60
  throw new Error('grant_max_uses must be a non-negative integer');
50
61
  }
62
+ const scope = scheme.grant_scope ?? types_1.SCAN_GRANT_SCOPES.ACTION;
63
+ if (!Object.values(types_1.SCAN_GRANT_SCOPES).includes(scope)) {
64
+ throw new Error(`unknown grant_scope "${scope}"`);
65
+ }
51
66
  }
52
- else if (scheme.grant_ttl_seconds != null || (scheme.grant_max_uses ?? 0) !== 0) {
67
+ else if (scheme.grant_ttl_seconds != null || (scheme.grant_max_uses ?? 0) !== 0
68
+ || (scheme.grant_scope ?? types_1.SCAN_GRANT_SCOPES.ACTION) !== types_1.SCAN_GRANT_SCOPES.ACTION) {
53
69
  throw new Error('grant policy applies only to identity schemes');
54
70
  }
55
71
  }
72
+ /**
73
+ * A scheme must read codes no other scheme reads. Delimited and fixed
74
+ * schemes are told apart by their version prefix; a gtin scheme has none,
75
+ * so there is at most one, and no enabled fixed scheme may accept a GTIN
76
+ * length while it is enabled. Throws naming both schemes.
77
+ */
78
+ function assertSchemesCoexist(candidate, existing) {
79
+ const others = existing.filter((s) => s.version !== candidate.version);
80
+ const encoding = candidate.encoding ?? types_1.SCAN_ENCODINGS.FIXED;
81
+ const enabled = candidate.enabled ?? true;
82
+ if (encoding === types_1.SCAN_ENCODINGS.GTIN) {
83
+ const gtin = others.find((s) => s.encoding === types_1.SCAN_ENCODINGS.GTIN);
84
+ if (gtin) {
85
+ throw new Error(`scheme ${gtin.version} ("${gtin.name}") already reads manufacturer barcodes; only one gtin scheme is allowed`);
86
+ }
87
+ if (!enabled)
88
+ return;
89
+ const clash = others.find((s) => s.enabled && s.encoding === types_1.SCAN_ENCODINGS.FIXED
90
+ && (0, scan_code_1.fixedCodeLengths)(s).some((n) => types_1.GTIN_LENGTHS.includes(n)));
91
+ if (clash) {
92
+ throw new Error(`fixed scheme ${clash.version} ("${clash.name}") accepts ${(0, scan_code_1.fixedCodeLengths)(clash).join(' or ')}-digit codes, which a gtin scheme also reads; change its target_length or leave the gtin scheme disabled`);
93
+ }
94
+ return;
95
+ }
96
+ if (encoding === types_1.SCAN_ENCODINGS.FIXED && enabled) {
97
+ const lengths = (0, scan_code_1.fixedCodeLengths)({ target_length: candidate.target_length ?? null });
98
+ if (!lengths.some((n) => types_1.GTIN_LENGTHS.includes(n)))
99
+ return;
100
+ const gtin = others.find((s) => s.enabled && s.encoding === types_1.SCAN_ENCODINGS.GTIN);
101
+ if (gtin) {
102
+ throw new Error(`a fixed scheme accepting ${lengths.join(' or ')}-digit codes collides with gtin scheme ${gtin.version} ("${gtin.name}"); change target_length or disable the gtin scheme`);
103
+ }
104
+ }
105
+ }
56
106
  /** Identity rules never walk steps — their fallback is the unknown-badge screen. */
57
107
  function assertValidIdentityRule(steps) {
58
108
  if (Array.isArray(steps) && steps.length > 0) {
@@ -73,7 +123,8 @@ function assertValidChoices(choices, at) {
73
123
  throw new Error(`${cat}: label is required`);
74
124
  if (!VALID_VERBS.has(choice.verb))
75
125
  throw new Error(`${cat}: unknown verb "${choice.verb}"`);
76
- if (choice.verb === types_1.SCAN_VERBS.PRESENT || choice.verb === types_1.SCAN_VERBS.SHOW_LIST) {
126
+ if (choice.verb === types_1.SCAN_VERBS.PRESENT || choice.verb === types_1.SCAN_VERBS.SHOW_LIST
127
+ || choice.verb === types_1.SCAN_VERBS.FILL) {
77
128
  throw new Error(`${cat}: ${choice.verb} cannot be a choice verb`);
78
129
  }
79
130
  if (choice.confirm && !choice.confirm.prompt) {
@@ -172,18 +223,29 @@ function assertValidSteps(steps) {
172
223
  && (!container.facets || typeof container.facets !== 'object' || Array.isArray(container.facets))) {
173
224
  throw new Error(`${at}: params.accumulate.container.facets must be an object`);
174
225
  }
175
- if (!options?.containerFacet) {
176
- throw new Error(`${at}: params.accumulate.container requires params.accumulate.containerFacet`);
226
+ if (!options?.containerFacet && options?.from !== 'subject') {
227
+ throw new Error(`${at}: params.accumulate.container requires params.accumulate.containerFacet or from: 'subject'`);
177
228
  }
178
229
  }
179
- if (!options?.containerFacet && !step.params?.itemKey) {
230
+ if (!options?.containerFacet && !options?.into && !step.params?.itemKey) {
180
231
  throw new Error(`${at}: accumulate requires params.itemKey or params.accumulate.containerFacet`);
181
232
  }
182
233
  }
234
+ (0, validate_subject_1.assertValidSubjectStep)(step, at);
235
+ if (step.done !== undefined) {
236
+ if (!step.done || typeof step.done !== 'object' || typeof step.done.markdown !== 'string' || !step.done.markdown) {
237
+ throw new Error(`${at}: done.markdown is required`);
238
+ }
239
+ if (!types_1.SCAN_MUTATING_VERBS.includes(step.verb)) {
240
+ throw new Error(`${at}: done applies only to steps that write`);
241
+ }
242
+ }
183
243
  assertValidTemplateTokens(step, at);
184
244
  if (step.query && step.query.roles && !Array.isArray(step.query.roles)) {
185
245
  throw new Error(`${at}: query.roles must be an array`);
186
246
  }
247
+ (0, validate_query_1.assertValidQueryKinds)(step, at);
248
+ (0, validate_facts_1.assertValidFacts)(step, at);
187
249
  // Claim and cancel lock via claim-by-metadata, whose SQL filter is the
188
250
  // target facet + roles only — extra facet guards would be silently
189
251
  // ignored there, so reject them at write time. (Locate, resolve, and
@@ -198,21 +260,44 @@ function assertValidSteps(steps) {
198
260
  }
199
261
  });
200
262
  }
201
- const BAG_TOKEN = /\{(claim|item)\.([^}]*)\}/g;
263
+ const BAG_TOKEN = /\{(claim|item|subject|container|fill)\.([^}]*)\}/g;
202
264
  /**
203
- * `{claim.<facet>}` and `{item.<facet>}` name facet keys; `{item.…}` reads
204
- * the located row, which only an item-mode accumulate step has.
265
+ * Bag tokens name facet keys and may only read what the step has:
266
+ * `{item.…}` the row an item-mode accumulate, an into-subject accumulate
267
+ * with `item`, or a hold located (and, in a present step's facts, the row it
268
+ * presents),
269
+ * `{subject.…}` the held subject (steps with a subject gate), and
270
+ * `{container.…}` / `{fill.…}` only inside refusal and done copy, where a
271
+ * subject accumulate or a fill has read them (into-subject: the held row).
205
272
  */
206
273
  function assertValidTemplateTokens(step, at) {
207
- const text = JSON.stringify(step.params ?? {});
208
- const itemMode = step.verb === types_1.SCAN_VERBS.ACCUMULATE && !!step.params?.accumulate?.containerFacet;
209
- for (const match of text.matchAll(BAG_TOKEN)) {
210
- const [token, bag, facet] = match;
211
- if (!facet_sql_1.FACET_KEY.test(facet)) {
212
- throw new Error(`${at}: template token ${token} must name a facet key`);
213
- }
214
- if (bag === 'item' && !itemMode) {
215
- throw new Error(`${at}: ${token} reads the located item row, which only an item-mode accumulate step has`);
274
+ const accumulate = step.verb === types_1.SCAN_VERBS.ACCUMULATE ? step.params?.accumulate : undefined;
275
+ const itemRow = !!accumulate?.containerFacet || (accumulate?.into === 'subject' && !!accumulate.item)
276
+ || step.verb === types_1.SCAN_VERBS.HOLD;
277
+ const containerCopy = accumulate?.from === 'subject' || accumulate?.into === 'subject';
278
+ const check = (value, inRefusal, inFacts = false) => {
279
+ for (const match of JSON.stringify(value ?? {}).matchAll(BAG_TOKEN)) {
280
+ const [token, bag, facet] = match;
281
+ if (!facet_sql_1.FACET_KEY.test(facet)) {
282
+ throw new Error(`${at}: template token ${token} must name a facet key`);
283
+ }
284
+ if (bag === 'item' && !itemRow && !inFacts) {
285
+ throw new Error(`${at}: ${token} reads the located item row, which only an item-mode accumulate, an into-subject accumulate with item, or a hold step has`);
286
+ }
287
+ if (bag === 'subject' && !step.subject) {
288
+ throw new Error(`${at}: ${token} reads the held subject, which only a step with a subject gate has`);
289
+ }
290
+ if (bag === 'container' && !(inRefusal && containerCopy)) {
291
+ throw new Error(`${at}: ${token} is readable only in the refusal or done copy of a subject accumulate step`);
292
+ }
293
+ if (bag === 'fill' && !(inRefusal && step.verb === types_1.SCAN_VERBS.FILL)) {
294
+ throw new Error(`${at}: ${token} is readable only in the refusal or done copy of a fill step`);
295
+ }
216
296
  }
217
- }
297
+ };
298
+ check(step.params, false);
299
+ check(step.match, false);
300
+ check(step.refuse, true);
301
+ check(step.done, true);
302
+ check(step.facts, false, true);
218
303
  }
@@ -10,6 +10,7 @@ export interface ScanSchemeInput {
10
10
  kind?: ScanScheme['kind'];
11
11
  grant_ttl_seconds?: number | null;
12
12
  grant_max_uses?: number;
13
+ grant_scope?: ScanScheme['grant_scope'];
13
14
  enabled?: boolean;
14
15
  }
15
16
  export interface ScanRuleInput {
@@ -13,6 +13,11 @@ const types_1 = require("../../types");
13
13
  const sql_1 = require("./sql");
14
14
  const validate_1 = require("./validate");
15
15
  const read_1 = require("./read");
16
+ /** Field validation, then the cross-scheme check against what is stored. */
17
+ async function assertSchemeInput(input) {
18
+ (0, validate_1.assertValidScheme)(input);
19
+ (0, validate_1.assertSchemesCoexist)(input, await (0, read_1.listScanSchemes)());
20
+ }
16
21
  function schemeParams(input) {
17
22
  return [
18
23
  input.version,
@@ -26,6 +31,7 @@ function schemeParams(input) {
26
31
  input.grant_ttl_seconds ?? null,
27
32
  input.grant_max_uses ?? 0,
28
33
  input.enabled ?? true,
34
+ input.grant_scope ?? types_1.SCAN_GRANT_SCOPES.ACTION,
29
35
  ];
30
36
  }
31
37
  function ruleParams(input) {
@@ -49,7 +55,7 @@ async function assertStepsForScheme(input) {
49
55
  (0, validate_1.assertValidSteps)(input.steps);
50
56
  }
51
57
  async function upsertScanScheme(input) {
52
- (0, validate_1.assertValidScheme)(input);
58
+ await assertSchemeInput(input);
53
59
  const { rows } = await (0, db_1.getPool)().query(sql_1.UPSERT_SCHEME, schemeParams(input));
54
60
  return rows[0];
55
61
  }
@@ -80,7 +86,7 @@ async function deleteScanRule(schemeVersion, category) {
80
86
  }
81
87
  /** Insert-if-absent seeding — DB is the source of truth, never overwrite. */
82
88
  async function seedScanScheme(input) {
83
- (0, validate_1.assertValidScheme)(input);
89
+ await assertSchemeInput(input);
84
90
  const { rowCount } = await (0, db_1.getPool)().query(sql_1.SEED_SCHEME, schemeParams(input));
85
91
  return (rowCount ?? 0) > 0;
86
92
  }
@@ -95,7 +101,7 @@ async function seedScanRule(input) {
95
101
  * declaration a zero-row no-op.
96
102
  */
97
103
  async function applyScanScheme(input) {
98
- (0, validate_1.assertValidScheme)(input);
104
+ await assertSchemeInput(input);
99
105
  const { rowCount } = await (0, db_1.getPool)().query(sql_1.APPLY_SCHEME, schemeParams(input));
100
106
  return (rowCount ?? 0) > 0 ? 'applied' : 'unchanged';
101
107
  }
@@ -7,6 +7,7 @@ exports.validateRequireAll = validateRequireAll;
7
7
  exports.validateFieldType = validateFieldType;
8
8
  exports.validateFieldConstraints = validateFieldConstraints;
9
9
  exports.validateField = validateField;
10
+ const x_lt_scan_1 = require("./x-lt-scan");
10
11
  const x_lt_options_1 = require("./x-lt-options");
11
12
  const ctx_path_1 = require("./ctx-path");
12
13
  /**
@@ -160,6 +161,9 @@ function validateFieldConstraints(value, fieldSchema, ctx) {
160
161
  return `Must be one of: ${allowed.map((o) => String(o.value)).join(', ')}`;
161
162
  }
162
163
  }
164
+ const scanError = (0, x_lt_scan_1.scanSinkError)(value, fieldSchema, ctx);
165
+ if (scanError)
166
+ return scanError;
163
167
  if (Array.isArray(value)) {
164
168
  return isEditableList(fieldSchema) ? validateListConstraints(value, fieldSchema, allowed, ctx) : undefined;
165
169
  }
@@ -22,3 +22,4 @@ export * from './validate-resolver-payload';
22
22
  export * from './invoke-context';
23
23
  export * from './display-only-widgets';
24
24
  export * from './x-lt-invoke';
25
+ export * from './x-lt-scan';
@@ -38,3 +38,4 @@ __exportStar(require("./validate-resolver-payload"), exports);
38
38
  __exportStar(require("./invoke-context"), exports);
39
39
  __exportStar(require("./display-only-widgets"), exports);
40
40
  __exportStar(require("./x-lt-invoke"), exports);
41
+ __exportStar(require("./x-lt-scan"), exports);
@@ -0,0 +1,52 @@
1
+ export declare const X_LT_SCAN = "x-lt-scan";
2
+ export declare const X_LT_SCAN_SUBMIT = "x-lt-scan-submit";
3
+ export declare const X_LT_ORDER = "x-lt-order";
4
+ export interface ScanSink {
5
+ schemes: number[];
6
+ /** The scanned target (default) or the code as scanned. */
7
+ value: 'target' | 'code';
8
+ /** Context paths whose values the field accepts. */
9
+ expect?: string[];
10
+ expectError: string;
11
+ /** Array fields: 'count' takes a value as many times as it is expected. */
12
+ multiplicity: 'count' | 'once';
13
+ }
14
+ /** The parts of a parsed scan a sink reads. */
15
+ export interface SinkScan {
16
+ version: number;
17
+ target: string;
18
+ code: string;
19
+ }
20
+ type Schema = Record<string, unknown>;
21
+ /** The field's scan configuration, or null when it takes no scans. */
22
+ export declare function readScanSink(fieldSchema: Schema | undefined): ScanSink | null;
23
+ /** Manufacturer barcodes compare as GTINs, so a UPC-A matches its 14-digit form. */
24
+ export declare function sameScanValue(a: string, b: string): boolean;
25
+ /** The values the field accepts, flattened; null when it declares none. */
26
+ export declare function resolveScanExpected(sink: ScanSink, ctx: Record<string, unknown> | undefined): string[] | null;
27
+ /**
28
+ * The field's error for its current value against what it expects, or
29
+ * undefined. Strings must be one of the expected values; arrays may hold
30
+ * each expected value once (or as many times as expected, with 'count').
31
+ */
32
+ export declare function scanSinkError(value: unknown, fieldSchema: Schema | undefined, ctx: Record<string, unknown> | undefined): string | undefined;
33
+ /** What a scan does to a field: the next value, or the error to show (nothing written). */
34
+ export declare function applyScanToField(current: unknown, scan: SinkScan, fieldSchema: Schema, ctx: Record<string, unknown> | undefined): {
35
+ ok: true;
36
+ value: unknown;
37
+ } | {
38
+ ok: false;
39
+ error: string;
40
+ };
41
+ /**
42
+ * The field a scan from `version` fills: the focused field when it takes
43
+ * that scheme, otherwise the first (in x-lt-order) that takes it and has
44
+ * room, otherwise the first that takes it. Null: no field takes it, so the
45
+ * scan runs globally.
46
+ */
47
+ export declare function pickScanSink(schema: Schema | null | undefined, values: Record<string, unknown>, version: number, focusedField?: string | null): string | null;
48
+ /** True when the form submits on its own once its scan fields are filled. */
49
+ export declare function wantsScanSubmit(schema: Schema | null | undefined): boolean;
50
+ /** True when every required scan field holds a value. */
51
+ export declare function scanFieldsFilled(schema: Schema | null | undefined, values: Record<string, unknown>): boolean;
52
+ export {};
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.X_LT_ORDER = exports.X_LT_SCAN_SUBMIT = exports.X_LT_SCAN = void 0;
4
+ exports.readScanSink = readScanSink;
5
+ exports.sameScanValue = sameScanValue;
6
+ exports.resolveScanExpected = resolveScanExpected;
7
+ exports.scanSinkError = scanSinkError;
8
+ exports.applyScanToField = applyScanToField;
9
+ exports.pickScanSink = pickScanSink;
10
+ exports.wantsScanSubmit = wantsScanSubmit;
11
+ exports.scanFieldsFilled = scanFieldsFilled;
12
+ /**
13
+ * x-lt-scan: a form field that takes a scan.
14
+ *
15
+ * While a form is open and editable, a scan whose scheme a field accepts
16
+ * fills that field instead of running globally. The field may declare what
17
+ * it expects (paths into the escalation context); a scan outside that set
18
+ * is a field error and is not written, and the same check runs server-side
19
+ * at submit, so a typed wrong value is refused there too.
20
+ *
21
+ * "containerCode": { "type": "string", "x-lt-scan": {
22
+ * "schemes": [14], "expect": ["metadata.containerCode"],
23
+ * "expect-error": "This item goes in {{expected}}." } }
24
+ * "parts": { "type": "array", "items": { "type": "string" },
25
+ * "x-lt-scan": { "schemes": [16], "expect": ["envelope.expected_upcs"], "multiplicity": "count" } }
26
+ *
27
+ * Root `x-lt-scan-submit: true` submits once every required scan field is
28
+ * filled and the form validates. A string field is replaced by a scan; an
29
+ * array field appends, and with `multiplicity: "count"` a value expected n
30
+ * times takes n scans.
31
+ */
32
+ const ctx_path_1 = require("./ctx-path");
33
+ exports.X_LT_SCAN = 'x-lt-scan';
34
+ exports.X_LT_SCAN_SUBMIT = 'x-lt-scan-submit';
35
+ exports.X_LT_ORDER = 'x-lt-order';
36
+ const DEFAULT_EXPECT_ERROR = 'Expected {{expected}}';
37
+ /** The field's scan configuration, or null when it takes no scans. */
38
+ function readScanSink(fieldSchema) {
39
+ const raw = fieldSchema?.[exports.X_LT_SCAN];
40
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw))
41
+ return null;
42
+ const cfg = raw;
43
+ const schemes = Array.isArray(cfg.schemes) ? cfg.schemes.filter((v) => Number.isInteger(v)) : [];
44
+ if (schemes.length === 0)
45
+ return null;
46
+ const expect = Array.isArray(cfg.expect) ? cfg.expect.filter((v) => typeof v === 'string') : undefined;
47
+ return {
48
+ schemes,
49
+ value: cfg.value === 'code' ? 'code' : 'target',
50
+ ...(expect?.length ? { expect } : {}),
51
+ expectError: typeof cfg['expect-error'] === 'string' ? cfg['expect-error'] : DEFAULT_EXPECT_ERROR,
52
+ multiplicity: cfg.multiplicity === 'count' ? 'count' : 'once',
53
+ };
54
+ }
55
+ /** Manufacturer barcodes compare as GTINs, so a UPC-A matches its 14-digit form. */
56
+ function sameScanValue(a, b) {
57
+ if (a === b)
58
+ return true;
59
+ const gtin = /^[0-9]{8,14}$/;
60
+ return gtin.test(a) && gtin.test(b) && a.padStart(14, '0') === b.padStart(14, '0');
61
+ }
62
+ /** The values the field accepts, flattened; null when it declares none. */
63
+ function resolveScanExpected(sink, ctx) {
64
+ if (!sink.expect)
65
+ return null;
66
+ const out = [];
67
+ for (const path of sink.expect) {
68
+ const value = (0, ctx_path_1.resolveCtxPath)(path, ctx);
69
+ const list = Array.isArray(value) ? value : [value];
70
+ for (const v of list) {
71
+ if (typeof v === 'string' && v)
72
+ out.push(v);
73
+ else if (typeof v === 'number')
74
+ out.push(String(v));
75
+ }
76
+ }
77
+ return out;
78
+ }
79
+ function expectMessage(sink, expected) {
80
+ return sink.expectError.replace(/\{\{\s*expected\s*\}\}/g, [...new Set(expected)].join(', ') || 'nothing');
81
+ }
82
+ /**
83
+ * The field's error for its current value against what it expects, or
84
+ * undefined. Strings must be one of the expected values; arrays may hold
85
+ * each expected value once (or as many times as expected, with 'count').
86
+ */
87
+ function scanSinkError(value, fieldSchema, ctx) {
88
+ const sink = readScanSink(fieldSchema);
89
+ if (!sink)
90
+ return undefined;
91
+ const expected = resolveScanExpected(sink, ctx);
92
+ if (expected === null)
93
+ return undefined;
94
+ const values = Array.isArray(value) ? value : value === undefined || value === null || value === '' ? [] : [value];
95
+ // Each expected value admits one scan; 'count' keeps repeats as separate admissions.
96
+ const budget = sink.multiplicity === 'count' ? [...expected] : [...new Set(expected)];
97
+ for (const v of values) {
98
+ const at = budget.findIndex((e) => sameScanValue(String(v), e));
99
+ if (at === -1)
100
+ return expectMessage(sink, expected);
101
+ budget.splice(at, 1);
102
+ }
103
+ return undefined;
104
+ }
105
+ /** What a scan does to a field: the next value, or the error to show (nothing written). */
106
+ function applyScanToField(current, scan, fieldSchema, ctx) {
107
+ const sink = readScanSink(fieldSchema);
108
+ if (!sink)
109
+ return { ok: false, error: 'This field takes no scans' };
110
+ const scanned = sink.value === 'code' ? scan.code : scan.target;
111
+ const isArray = fieldSchema.type === 'array';
112
+ const next = isArray ? [...(Array.isArray(current) ? current : []), scanned] : scanned;
113
+ const error = scanSinkError(next, fieldSchema, ctx);
114
+ if (error)
115
+ return { ok: false, error };
116
+ const max = fieldSchema.maxItems;
117
+ if (isArray && typeof max === 'number' && next.length > max) {
118
+ return { ok: false, error: `At most ${max}` };
119
+ }
120
+ return { ok: true, value: next };
121
+ }
122
+ /** True when the field has room for another scan. */
123
+ function hasRoom(value, fieldSchema) {
124
+ if (fieldSchema.type === 'array') {
125
+ const max = fieldSchema.maxItems;
126
+ return typeof max !== 'number' || !Array.isArray(value) || value.length < max;
127
+ }
128
+ return value === undefined || value === null || value === '';
129
+ }
130
+ /**
131
+ * The field a scan from `version` fills: the focused field when it takes
132
+ * that scheme, otherwise the first (in x-lt-order) that takes it and has
133
+ * room, otherwise the first that takes it. Null: no field takes it, so the
134
+ * scan runs globally.
135
+ */
136
+ function pickScanSink(schema, values, version, focusedField) {
137
+ const properties = (schema?.properties ?? {});
138
+ const order = Array.isArray(schema?.[exports.X_LT_ORDER]) ? schema[exports.X_LT_ORDER] : [];
139
+ const names = [...order.filter((n) => n in properties), ...Object.keys(properties).filter((n) => !order.includes(n))];
140
+ const takes = names.filter((n) => readScanSink(properties[n])?.schemes.includes(version));
141
+ if (takes.length === 0)
142
+ return null;
143
+ if (focusedField && takes.includes(focusedField))
144
+ return focusedField;
145
+ return takes.find((n) => hasRoom(values[n], properties[n])) ?? takes[0];
146
+ }
147
+ /** True when the form submits on its own once its scan fields are filled. */
148
+ function wantsScanSubmit(schema) {
149
+ return schema?.[exports.X_LT_SCAN_SUBMIT] === true;
150
+ }
151
+ /** True when every required scan field holds a value. */
152
+ function scanFieldsFilled(schema, values) {
153
+ const properties = (schema?.properties ?? {});
154
+ const required = new Set(schema?.required ?? []);
155
+ const sinks = Object.keys(properties).filter((n) => readScanSink(properties[n]) && required.has(n));
156
+ if (sinks.length === 0)
157
+ return false;
158
+ return sinks.every((n) => {
159
+ const v = values[n];
160
+ if (Array.isArray(v)) {
161
+ const min = properties[n].minItems;
162
+ return v.length >= (typeof min === 'number' ? min : 1);
163
+ }
164
+ return v !== undefined && v !== null && v !== '';
165
+ });
166
+ }
@@ -0,0 +1,11 @@
1
+ export declare const GTIN_CODE_LENGTHS: readonly number[];
2
+ /** True when `code` is all digits, a GTIN length, and its mod-10 check digit holds. */
3
+ export declare function isValidGtin(code: string): boolean;
4
+ /** The 14-digit form of a valid GTIN: UPC-A, EAN-13 and EAN-8 left-padded with zeros. */
5
+ export declare function normalizeGtin(code: string): string;
6
+ /**
7
+ * A stored 14-digit GTIN as the package prints it: EAN-8 when it was padded
8
+ * from eight digits, otherwise EAN-13 (a UPC-A reads as its EAN-13 with a
9
+ * leading zero). Anything else comes back unchanged.
10
+ */
11
+ export declare function displayGtin(code: string): string;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ // GTIN (UPC-A, EAN-13, EAN-8, GTIN-14) check digits and normalization.
3
+ // Pure; shared by the server parser and the dashboard's scan capture.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.GTIN_CODE_LENGTHS = void 0;
6
+ exports.isValidGtin = isValidGtin;
7
+ exports.normalizeGtin = normalizeGtin;
8
+ exports.displayGtin = displayGtin;
9
+ exports.GTIN_CODE_LENGTHS = [8, 12, 13, 14];
10
+ /** True when `code` is all digits, a GTIN length, and its mod-10 check digit holds. */
11
+ function isValidGtin(code) {
12
+ if (!/^[0-9]+$/.test(code) || !exports.GTIN_CODE_LENGTHS.includes(code.length))
13
+ return false;
14
+ const digits = code.split('').map(Number);
15
+ const check = digits.pop();
16
+ let sum = 0;
17
+ // Weights run 3,1,3,1… from the digit nearest the check digit.
18
+ for (let i = digits.length - 1, w = 3; i >= 0; i--, w = w === 3 ? 1 : 3) {
19
+ sum += digits[i] * w;
20
+ }
21
+ return (10 - (sum % 10)) % 10 === check;
22
+ }
23
+ /** The 14-digit form of a valid GTIN: UPC-A, EAN-13 and EAN-8 left-padded with zeros. */
24
+ function normalizeGtin(code) {
25
+ return code.padStart(14, '0');
26
+ }
27
+ /**
28
+ * A stored 14-digit GTIN as the package prints it: EAN-8 when it was padded
29
+ * from eight digits, otherwise EAN-13 (a UPC-A reads as its EAN-13 with a
30
+ * leading zero). Anything else comes back unchanged.
31
+ */
32
+ function displayGtin(code) {
33
+ if (code.length !== 14 || !isValidGtin(code))
34
+ return code;
35
+ if (code.startsWith('000000') && isValidGtin(code.slice(6)))
36
+ return code.slice(6);
37
+ return code.startsWith('0') ? code.slice(1) : code;
38
+ }
@@ -0,0 +1,2 @@
1
+ export { parseScanCode, fixedCodeLengths, type ParseableScheme, type ParsedCode, type ScanParseFailure, type ScanParseResult, } from './parse';
2
+ export { isValidGtin, normalizeGtin, displayGtin, GTIN_CODE_LENGTHS } from './gtin';
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GTIN_CODE_LENGTHS = exports.displayGtin = exports.normalizeGtin = exports.isValidGtin = exports.fixedCodeLengths = exports.parseScanCode = void 0;
4
+ var parse_1 = require("./parse");
5
+ Object.defineProperty(exports, "parseScanCode", { enumerable: true, get: function () { return parse_1.parseScanCode; } });
6
+ Object.defineProperty(exports, "fixedCodeLengths", { enumerable: true, get: function () { return parse_1.fixedCodeLengths; } });
7
+ var gtin_1 = require("./gtin");
8
+ Object.defineProperty(exports, "isValidGtin", { enumerable: true, get: function () { return gtin_1.isValidGtin; } });
9
+ Object.defineProperty(exports, "normalizeGtin", { enumerable: true, get: function () { return gtin_1.normalizeGtin; } });
10
+ Object.defineProperty(exports, "displayGtin", { enumerable: true, get: function () { return gtin_1.displayGtin; } });
11
+ Object.defineProperty(exports, "GTIN_CODE_LENGTHS", { enumerable: true, get: function () { return gtin_1.GTIN_CODE_LENGTHS; } });
@@ -0,0 +1,46 @@
1
+ /** The scheme fields parsing reads. The server's ScanScheme satisfies it. */
2
+ export interface ParseableScheme {
3
+ version: number;
4
+ name: string;
5
+ encoding: 'fixed' | 'delimited' | 'gtin';
6
+ delimiter: string;
7
+ target_length: number | null;
8
+ enabled: boolean;
9
+ }
10
+ export interface ParsedCode {
11
+ version: number;
12
+ category: string;
13
+ target: string;
14
+ /** The code as scanned, when the target was normalized from it (GTIN). */
15
+ raw?: string;
16
+ }
17
+ export interface ScanParseFailure {
18
+ /** Why the code did not parse. */
19
+ reason: 'empty' | 'unknown_version' | 'scheme_disabled' | 'malformed';
20
+ detail: string;
21
+ }
22
+ export type ScanParseResult<S extends ParseableScheme = ParseableScheme> = {
23
+ ok: true;
24
+ parsed: ParsedCode;
25
+ scheme: S;
26
+ } | {
27
+ ok: false;
28
+ failure: ScanParseFailure;
29
+ };
30
+ /**
31
+ * Parse a raw scan string against the configured schemes.
32
+ *
33
+ * The leading TWO digits pick the scheme (10-99, so a code never starts with a
34
+ * leading zero); the scheme then defines how the remainder splits into a
35
+ * single-digit category (0-9) and the target:
36
+ * - delimited: `10:1:ABC-123` (delimiter from the scheme row)
37
+ * - fixed: `1017554332` (one category digit, then target_length digits)
38
+ *
39
+ * A digits-only code that no fixed scheme reads is a manufacturer barcode
40
+ * when a gtin scheme is configured and its check digit holds: the target is
41
+ * the 14-digit GTIN and the category is '0'. Config validation keeps fixed
42
+ * and gtin lengths apart, so the order here never decides a real code.
43
+ */
44
+ export declare function parseScanCode<S extends ParseableScheme>(raw: string, schemes: S[]): ScanParseResult<S>;
45
+ /** The total code lengths a fixed scheme accepts (with and without the check-digit slack). */
46
+ export declare function fixedCodeLengths(scheme: Pick<ParseableScheme, 'target_length'>): number[];