@hotmeshio/long-tail 0.22.0 → 0.22.2
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.
- package/build/api/escalations/accumulate.d.ts +10 -1
- package/build/api/escalations/accumulate.js +121 -34
- package/build/api/escalations/metadata.d.ts +5 -0
- package/build/api/escalations/metadata.js +6 -2
- package/build/api/escalations/resolve-batch.js +18 -11
- package/build/api/roles.js +4 -0
- package/build/api/scan-codes/badge-policy.d.ts +10 -0
- package/build/api/scan-codes/badge-policy.js +72 -0
- package/build/api/scan-codes/choice.js +18 -11
- package/build/api/scan-codes/context.d.ts +45 -1
- package/build/api/scan-codes/context.js +51 -3
- package/build/api/scan-codes/execute.js +73 -35
- package/build/api/scan-codes/grant.d.ts +27 -0
- package/build/api/scan-codes/grant.js +67 -0
- package/build/api/scan-codes/hold.d.ts +10 -0
- package/build/api/scan-codes/hold.js +98 -0
- package/build/api/scan-codes/identity.d.ts +5 -2
- package/build/api/scan-codes/identity.js +26 -8
- package/build/api/scan-codes/subject.d.ts +15 -0
- package/build/api/scan-codes/subject.js +68 -0
- package/build/api/scan-codes/verb-accumulate.d.ts +24 -0
- package/build/api/scan-codes/verb-accumulate.js +147 -0
- package/build/api/scan-codes/verb-fill.d.ts +6 -0
- package/build/api/scan-codes/verb-fill.js +152 -0
- package/build/api/scan-codes/verbs-subject.d.ts +14 -0
- package/build/api/scan-codes/verbs-subject.js +270 -0
- package/build/api/scan-codes/verbs.d.ts +7 -22
- package/build/api/scan-codes/verbs.js +35 -114
- package/build/api/workflows/invocation.d.ts +8 -4
- package/build/api/workflows/invocation.js +26 -9
- package/build/index.d.ts +1 -0
- package/build/index.js +8 -2
- package/build/lib/cli/commands/workflows.js +9 -4
- package/build/lib/db/schemas/037_scan_gtin_and_subject_grants.sql +27 -0
- package/build/routes/escalations/accumulate.js +13 -6
- package/build/routes/escalations/acting.d.ts +5 -0
- package/build/routes/escalations/acting.js +8 -1
- package/build/routes/scan-codes.js +3 -0
- package/build/sdk/index.d.ts +3 -0
- package/build/services/escalation/crud.d.ts +2 -2
- package/build/services/escalation/crud.js +4 -2
- package/build/services/escalation/facet-sql.js +8 -0
- package/build/services/escalation/sql.d.ts +4 -2
- package/build/services/escalation/sql.js +10 -2
- package/build/services/export/index.d.ts +8 -3
- package/build/services/export/index.js +15 -21
- package/build/services/iam/acting-identity.d.ts +29 -4
- package/build/services/iam/acting-identity.js +60 -17
- package/build/services/iam/ephemeral.d.ts +21 -0
- package/build/services/iam/ephemeral.js +32 -1
- package/build/services/iam/sql.d.ts +10 -0
- package/build/services/iam/sql.js +32 -3
- package/build/services/pipelines/events.js +2 -1
- package/build/services/pipelines/execution-builder.js +2 -1
- package/build/services/pipelines/queries.js +2 -1
- package/build/services/role/badge-grant.d.ts +5 -0
- package/build/services/role/badge-grant.js +36 -0
- package/build/services/role/seed.js +5 -0
- package/build/services/role/types.d.ts +14 -0
- package/build/services/role/types.js +5 -0
- package/build/services/scan-code/index.d.ts +3 -2
- package/build/services/scan-code/index.js +7 -1
- package/build/services/scan-code/parse.d.ts +23 -20
- package/build/services/scan-code/parse.js +45 -90
- package/build/services/scan-code/read.js +1 -0
- package/build/services/scan-code/sql.d.ts +3 -3
- package/build/services/scan-code/sql.js +11 -8
- package/build/services/scan-code/validate-subject.d.ts +7 -0
- package/build/services/scan-code/validate-subject.js +158 -0
- package/build/services/scan-code/validate.d.ts +7 -0
- package/build/services/scan-code/validate.js +111 -16
- package/build/services/scan-code/write.d.ts +1 -0
- package/build/services/scan-code/write.js +9 -3
- package/build/services/workflow-state.d.ts +21 -0
- package/build/services/workflow-state.js +39 -0
- package/build/shared/form-validation/field-validator.js +4 -0
- package/build/shared/form-validation/index.d.ts +1 -0
- package/build/shared/form-validation/index.js +1 -0
- package/build/shared/form-validation/x-lt-scan.d.ts +52 -0
- package/build/shared/form-validation/x-lt-scan.js +166 -0
- package/build/shared/scan-code/gtin.d.ts +5 -0
- package/build/shared/scan-code/gtin.js +25 -0
- package/build/shared/scan-code/index.d.ts +2 -0
- package/build/shared/scan-code/index.js +10 -0
- package/build/shared/scan-code/parse.d.ts +46 -0
- package/build/shared/scan-code/parse.js +133 -0
- package/build/shared/workflow-state.d.ts +17 -0
- package/build/shared/workflow-state.js +29 -0
- package/build/system/mcp-servers/admin/escalations.js +8 -4
- package/build/system/mcp-servers/admin/scan-codes.js +10 -4
- package/build/system/mcp-servers/admin/schemas.d.ts +792 -23
- package/build/system/mcp-servers/admin/schemas.js +61 -4
- package/build/system/mcp-servers/admin/workflows.js +20 -31
- package/build/system/mcp-servers/human-queue-schemas.d.ts +6 -6
- package/build/system/seed/tool-manifests-admin.d.ts +94 -0
- package/build/system/seed/tool-manifests-admin.js +3 -3
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/escalation.d.ts +2 -0
- package/build/types/escalation.js +3 -1
- package/build/types/facets.d.ts +14 -0
- package/build/types/index.d.ts +3 -3
- package/build/types/index.js +8 -1
- package/build/types/scan-code/constants.d.ts +182 -0
- package/build/types/{scan-code.js → scan-code/constants.js} +62 -12
- package/build/types/scan-code/index.d.ts +3 -0
- package/build/types/scan-code/index.js +17 -0
- package/build/types/scan-code/response.d.ts +140 -0
- package/build/types/scan-code/response.js +2 -0
- package/build/types/scan-code/rule.d.ts +199 -0
- package/build/types/scan-code/rule.js +2 -0
- package/build/types/startup.d.ts +3 -1
- package/dashboard/dist/assets/{AdminDashboard-Covdam48.js → AdminDashboard-DBW12qQt.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-Covdam48.js.map → AdminDashboard-DBW12qQt.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-CE1k6J5r.js → AgentConfigPage-CmHv8U9M.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-CE1k6J5r.js.map → AgentConfigPage-CmHv8U9M.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-CWJZIZP1.js → AgentDetailPage-D1scIbz-.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-CWJZIZP1.js.map → AgentDetailPage-D1scIbz-.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage---Dg5ufF.js → AgentsPage-BA_ai9HJ.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage---Dg5ufF.js.map → AgentsPage-BA_ai9HJ.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-C2_5aEFW.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-C2_5aEFW.js.map +1 -0
- package/dashboard/dist/assets/{BotPicker-D3drO3-T.js → BotPicker-BZo4Kp4a.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-D3drO3-T.js.map → BotPicker-BZo4Kp4a.js.map} +1 -1
- package/dashboard/dist/assets/{BulkAssignModal-BOAWsViq.js → BulkAssignModal-BFhyxY2T.js} +2 -2
- package/dashboard/dist/assets/{BulkAssignModal-BOAWsViq.js.map → BulkAssignModal-BFhyxY2T.js.map} +1 -1
- package/dashboard/dist/assets/CapabilitiesPage-CvOX6vAc.js +2 -0
- package/dashboard/dist/assets/{CapabilitiesPage-RGgD3YZO.js.map → CapabilitiesPage-CvOX6vAc.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-DNkZn87n.js → CollapsibleSection-GCJsV9Oq.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-DNkZn87n.js.map → CollapsibleSection-GCJsV9Oq.js.map} +1 -1
- package/dashboard/dist/assets/{ConfirmDeleteModal-BqzOwhPr.js → ConfirmDeleteModal-CAgYLcef.js} +2 -2
- package/dashboard/dist/assets/{ConfirmDeleteModal-BqzOwhPr.js.map → ConfirmDeleteModal-CAgYLcef.js.map} +1 -1
- package/dashboard/dist/assets/CountdownTimer-Dik2z0M_.js +2 -0
- package/dashboard/dist/assets/{CountdownTimer-BaexQMK6.js.map → CountdownTimer-Dik2z0M_.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-D7abp0aS.js → CredentialsPage-twd2xCOW.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-D7abp0aS.js.map → CredentialsPage-twd2xCOW.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-DZiWmTwJ.js → CronLabel-DdnIuudX.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-DZiWmTwJ.js.map → CronLabel-DdnIuudX.js.map} +1 -1
- package/dashboard/dist/assets/{DropZone-f1o-GLM8.js → DropZone-B1Tdfddc.js} +2 -2
- package/dashboard/dist/assets/{DropZone-f1o-GLM8.js.map → DropZone-B1Tdfddc.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-BdGO_w4v.js → ElapsedCell-DCctVv5R.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-BdGO_w4v.js.map → ElapsedCell-DCctVv5R.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-DIDcF5Yu.js → EntityTimelinePanel-CMnskyWv.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-DIDcF5Yu.js.map → EntityTimelinePanel-CMnskyWv.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-C28rn9XC.js → EscalationListSchemaPage-VfCn6WDb.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-C28rn9XC.js.map → EscalationListSchemaPage-VfCn6WDb.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListView-CkBnkpDJ.js → EscalationListView-CGQZxcC-.js} +2 -2
- package/dashboard/dist/assets/{EscalationListView-CkBnkpDJ.js.map → EscalationListView-CGQZxcC-.js.map} +1 -1
- package/dashboard/dist/assets/EscalationSchemaPage-BX0tx-PM.js +9 -0
- package/dashboard/dist/assets/EscalationSchemaPage-BX0tx-PM.js.map +1 -0
- package/dashboard/dist/assets/EscalationTimeline-DKoSM56J.js +2 -0
- package/dashboard/dist/assets/EscalationTimeline-DKoSM56J.js.map +1 -0
- package/dashboard/dist/assets/{EscalationTitleSelect-CzKfavri.js → EscalationTitleSelect-DWGLBOmS.js} +2 -2
- package/dashboard/dist/assets/{EscalationTitleSelect-CzKfavri.js.map → EscalationTitleSelect-DWGLBOmS.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-Tdu3Yx2c.js → EscalationsOverview-C2XoguaA.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-Tdu3Yx2c.js.map → EscalationsOverview-C2XoguaA.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-DiIxOJwO.js → EventTable-CBUWq7--.js} +2 -2
- package/dashboard/dist/assets/{EventTable-DiIxOJwO.js.map → EventTable-CBUWq7--.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-CvMBCVIo.js → FilterBar-8IdbleZ9.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-CvMBCVIo.js.map → FilterBar-8IdbleZ9.js.map} +1 -1
- package/dashboard/dist/assets/GrantScopeField-BzWGzBfA.js +2 -0
- package/dashboard/dist/assets/GrantScopeField-BzWGzBfA.js.map +1 -0
- package/dashboard/dist/assets/{GraphInvokePage-DO-yyhi6.js → GraphInvokePage-CUvoPzsW.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-DO-yyhi6.js.map → GraphInvokePage-CUvoPzsW.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-DSS3eHR2.js → HomePage-BP7v9GLJ.js} +2 -2
- package/dashboard/dist/assets/{HomePage-DSS3eHR2.js.map → HomePage-BP7v9GLJ.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-C3-Tqqub.js → ListToolbar-Cnacuwoy.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-C3-Tqqub.js.map → ListToolbar-Cnacuwoy.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-DEJmsdVi.js → McpOverview-C2JoNoDA.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-DEJmsdVi.js.map → McpOverview-C2JoNoDA.js.map} +1 -1
- package/dashboard/dist/assets/McpQueryDetailPage-C_nih0w-.js +5 -0
- package/dashboard/dist/assets/McpQueryDetailPage-C_nih0w-.js.map +1 -0
- package/dashboard/dist/assets/{McpQueryPage-BBcG_UuU.js → McpQueryPage-U_wNXow2.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-BBcG_UuU.js.map → McpQueryPage-U_wNXow2.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-C6xw0kBg.js → McpRunDetailPage-DtKoJq6J.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-C6xw0kBg.js.map → McpRunDetailPage-DtKoJq6J.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-CRQqrF4Q.js → McpRunsPage-CnYtfGhf.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-CRQqrF4Q.js.map → McpRunsPage-CnYtfGhf.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-DADRJOUl.js → NamespacePill-DwM5pNA4.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-DADRJOUl.js.map → NamespacePill-DwM5pNA4.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-Dlfwzf-0.js → OperationsPage-C7hupIer.js} +2 -2
- package/dashboard/dist/assets/{OperationsPage-Dlfwzf-0.js.map → OperationsPage-C7hupIer.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-DoiDGZ9R.js → OperatorDashboard-fVuLn2D5.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-DoiDGZ9R.js.map → OperatorDashboard-fVuLn2D5.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-Csq434-v.js → PageHeader-CMd3f4bz.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-Csq434-v.js.map → PageHeader-CMd3f4bz.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-CSnk1p5A.js → PageHeaderWithStats-DHj8Mqox.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-CSnk1p5A.js.map → PageHeaderWithStats-DHj8Mqox.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-BzbA4Prr.js → PersonaDetailPage-C-4o8lPw.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-BzbA4Prr.js.map → PersonaDetailPage-C-4o8lPw.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-B36yn4hU.js → PersonasPage-BL1FwLmv.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-B36yn4hU.js.map → PersonasPage-BL1FwLmv.js.map} +1 -1
- package/dashboard/dist/assets/{PortalPage-BkD4YfDf.js → PortalPage-tJG5sgb1.js} +2 -2
- package/dashboard/dist/assets/{PortalPage-BkD4YfDf.js.map → PortalPage-tJG5sgb1.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-BT0eiBWY.js → ProcessDetailPage-Dz_jY4Yt.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-BT0eiBWY.js.map → ProcessDetailPage-Dz_jY4Yt.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-BEqeeNae.js → ProcessesListPage-Cbn9cter.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-BEqeeNae.js.map → ProcessesListPage-Cbn9cter.js.map} +1 -1
- package/dashboard/dist/assets/ResolverForm-Bk8iXQ6-.js +8 -0
- package/dashboard/dist/assets/ResolverForm-Bk8iXQ6-.js.map +1 -0
- package/dashboard/dist/assets/RoleDetailPage-owPi6gI9.js +8 -0
- package/dashboard/dist/assets/RoleDetailPage-owPi6gI9.js.map +1 -0
- package/dashboard/dist/assets/{RolePill-BafrASDX.js → RolePill-Di2CAHuD.js} +2 -2
- package/dashboard/dist/assets/{RolePill-BafrASDX.js.map → RolePill-Di2CAHuD.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-80quJU5-.js → RolesPage-NwmMvZFa.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-80quJU5-.js.map → RolesPage-NwmMvZFa.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-BoePhWVD.js → RunAsSelector-tgEooTyU.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-BoePhWVD.js.map → RunAsSelector-tgEooTyU.js.map} +1 -1
- package/dashboard/dist/assets/ScanCodesPage-CUv_8ic6.js +2 -0
- package/dashboard/dist/assets/ScanCodesPage-CUv_8ic6.js.map +1 -0
- package/dashboard/dist/assets/ScanSchemeDetailPage-YHqbu7oK.js +2 -0
- package/dashboard/dist/assets/ScanSchemeDetailPage-YHqbu7oK.js.map +1 -0
- package/dashboard/dist/assets/ScanStationPage-B275l6r_.js +2 -0
- package/dashboard/dist/assets/ScanStationPage-B275l6r_.js.map +1 -0
- package/dashboard/dist/assets/{ScopeBadge-b6MIBiYD.js → ScopeBadge-CSItPVOH.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-b6MIBiYD.js.map → ScopeBadge-CSItPVOH.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-9ITrei_d.js → StickyPagination-CsTI_gvJ.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-9ITrei_d.js.map → StickyPagination-CsTI_gvJ.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-BkYvEHFY.js → StreamMessageDetail-auRlvjTh.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-BkYvEHFY.js.map → StreamMessageDetail-auRlvjTh.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-B1rotFix.js → SwimlaneTimeline-BLoVHYAd.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-B1rotFix.js.map → SwimlaneTimeline-BLoVHYAd.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-ZrIIrEUP.js → TagInput-CAgdLN_b.js} +2 -2
- package/dashboard/dist/assets/{TagInput-ZrIIrEUP.js.map → TagInput-CAgdLN_b.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-zhn_U_eC.js → TaskDetailPage-BPsZ1bK_.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-zhn_U_eC.js.map → TaskDetailPage-BPsZ1bK_.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-DkQ1uc6y.js → TaskQueuePill-h0oorVMe.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-DkQ1uc6y.js.map → TaskQueuePill-h0oorVMe.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-CNbNeagx.js → TasksListPage-BNGM74yT.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-CNbNeagx.js.map → TasksListPage-BNGM74yT.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-0YVMBwls.js → TimeAgo-BnAHXGK7.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-0YVMBwls.js.map → TimeAgo-BnAHXGK7.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-DB7r3np8.js → TimestampCell-J4yae6mc.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-DB7r3np8.js.map → TimestampCell-J4yae6mc.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-Baxm02L6.js → ToolPill-CQCsVdzD.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-Baxm02L6.js.map → ToolPill-CQCsVdzD.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-BLfA02wv.js → ToolTestPanel-BdzzgXDu.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-BLfA02wv.js.map → ToolTestPanel-BdzzgXDu.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-eAqPKShq.js → TopicDetailPage-DJKg8lb7.js} +4 -4
- package/dashboard/dist/assets/{TopicDetailPage-eAqPKShq.js.map → TopicDetailPage-DJKg8lb7.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-BNNWD-zl.js → TopicsPage-DQV0WxG6.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-BNNWD-zl.js.map → TopicsPage-DQV0WxG6.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-Pw46tO_k.js → UserName-Ct09nGh5.js} +2 -2
- package/dashboard/dist/assets/{UserName-Pw46tO_k.js.map → UserName-Ct09nGh5.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-DvA51lT3.js → WorkflowExecutionPage-B5WJOsee.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-DvA51lT3.js.map → WorkflowExecutionPage-B5WJOsee.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill-ZepbO_ny.js → WorkflowPill-Dg7BDTyM.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-ZepbO_ny.js.map → WorkflowPill-Dg7BDTyM.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-DFDTwnhn.js → WorkflowsDashboard-Hc87TRgD.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-DFDTwnhn.js.map → WorkflowsDashboard-Hc87TRgD.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-5i2Tcy-p.js → WorkflowsOverview-CJQbyOj-.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-5i2Tcy-p.js.map → WorkflowsOverview-CJQbyOj-.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-p4VEYZS0.js → YamlWorkflowDetailPage-BMeED677.js} +8 -8
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-p4VEYZS0.js.map → YamlWorkflowDetailPage-BMeED677.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-Cq-hMVxl.js → YamlWorkflowsPage-BMMg0Id6.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-Cq-hMVxl.js.map → YamlWorkflowsPage-BMMg0Id6.js.map} +1 -1
- package/dashboard/dist/assets/{agents-EyBPJMYa.js → agents-CdFkgFvg.js} +2 -2
- package/dashboard/dist/assets/{agents-EyBPJMYa.js.map → agents-CdFkgFvg.js.map} +1 -1
- package/dashboard/dist/assets/{bots-DX6jjqtF.js → bots-Mj3LHWWg.js} +2 -2
- package/dashboard/dist/assets/{bots-DX6jjqtF.js.map → bots-Mj3LHWWg.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-ZdLv9xBQ.js → capabilities-Dw1ObK2-.js} +2 -2
- package/dashboard/dist/assets/{capabilities-ZdLv9xBQ.js.map → capabilities-Dw1ObK2-.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-CpvZaJuw.js → controlplane-DcNE1APv.js} +2 -2
- package/dashboard/dist/assets/{controlplane-CpvZaJuw.js.map → controlplane-DcNE1APv.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-Mvsze5eV.js → escalation-columns-D364Trpy.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-Mvsze5eV.js.map → escalation-columns-D364Trpy.js.map} +1 -1
- package/dashboard/dist/assets/{index-Cn8uJsd7.js → index-B3veJ698.js} +2 -2
- package/dashboard/dist/assets/{index-Cn8uJsd7.js.map → index-B3veJ698.js.map} +1 -1
- package/dashboard/dist/assets/index-BQeHJHYN.js +67 -0
- package/dashboard/dist/assets/index-BQeHJHYN.js.map +1 -0
- package/dashboard/dist/assets/{index-D-Xs4rAW.js → index-BRGTmoYY.js} +2 -2
- package/dashboard/dist/assets/{index-D-Xs4rAW.js.map → index-BRGTmoYY.js.map} +1 -1
- package/dashboard/dist/assets/{index-DkrBFFSO.js → index-Bd6-KmBE.js} +3 -3
- package/dashboard/dist/assets/{index-DkrBFFSO.js.map → index-Bd6-KmBE.js.map} +1 -1
- package/dashboard/dist/assets/{index-Bhb89oHH.js → index-BiVce3n0.js} +2 -2
- package/dashboard/dist/assets/{index-Bhb89oHH.js.map → index-BiVce3n0.js.map} +1 -1
- package/dashboard/dist/assets/{index-z5Hpeidu.js → index-BmNAVd4s.js} +2 -2
- package/dashboard/dist/assets/{index-z5Hpeidu.js.map → index-BmNAVd4s.js.map} +1 -1
- package/dashboard/dist/assets/{index-BbCjGO3M.js → index-Bq5XNEzD.js} +2 -2
- package/dashboard/dist/assets/{index-BbCjGO3M.js.map → index-Bq5XNEzD.js.map} +1 -1
- package/dashboard/dist/assets/{index-DGmzBY9D.js → index-DPStdq4T.js} +2 -2
- package/dashboard/dist/assets/{index-DGmzBY9D.js.map → index-DPStdq4T.js.map} +1 -1
- package/dashboard/dist/assets/index-DcppjzP5.css +1 -0
- package/dashboard/dist/assets/{index-PfSRKerc.js → index-DkcI4V_H.js} +2 -2
- package/dashboard/dist/assets/{index-PfSRKerc.js.map → index-DkcI4V_H.js.map} +1 -1
- package/dashboard/dist/assets/{index-oFKUFGQL.js → index-Dyotfa_k.js} +2 -2
- package/dashboard/dist/assets/{index-oFKUFGQL.js.map → index-Dyotfa_k.js.map} +1 -1
- package/dashboard/dist/assets/{index-Eo-l3Lqo.js → index-MDD4JYtu.js} +2 -2
- package/dashboard/dist/assets/{index-Eo-l3Lqo.js.map → index-MDD4JYtu.js.map} +1 -1
- package/dashboard/dist/assets/index-WSm8bgE7.js +3 -0
- package/dashboard/dist/assets/index-WSm8bgE7.js.map +1 -0
- package/dashboard/dist/assets/{index-DZhtP2Ok.js → index-eDm6cz0F.js} +2 -2
- package/dashboard/dist/assets/{index-DZhtP2Ok.js.map → index-eDm6cz0F.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-CgloEkaf.js → knowledge-Bafewjxk.js} +2 -2
- package/dashboard/dist/assets/{knowledge-CgloEkaf.js.map → knowledge-Bafewjxk.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-o-sGX2ST.js → mcp-query-BzTtIG90.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-o-sGX2ST.js.map → mcp-query-BzTtIG90.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-Bix7QYO7.js → mcp-vLIutbnc.js} +2 -2
- package/dashboard/dist/assets/{mcp-Bix7QYO7.js.map → mcp-vLIutbnc.js.map} +1 -1
- package/dashboard/dist/assets/{personas-30azkJ_s.js → personas-WD40EDS_.js} +2 -2
- package/dashboard/dist/assets/{personas-30azkJ_s.js.map → personas-WD40EDS_.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-Bfk2GFK7.js → pipelines-DFwULWs3.js} +2 -2
- package/dashboard/dist/assets/{pipelines-Bfk2GFK7.js.map → pipelines-DFwULWs3.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-CpdopewW.js → tasks-La_-WAUn.js} +2 -2
- package/dashboard/dist/assets/{tasks-CpdopewW.js.map → tasks-La_-WAUn.js.map} +1 -1
- package/dashboard/dist/assets/{topics--bvCV9Yp.js → topics-CzYMlvqm.js} +2 -2
- package/dashboard/dist/assets/{topics--bvCV9Yp.js.map → topics-CzYMlvqm.js.map} +1 -1
- package/dashboard/dist/assets/{useDebouncedValue-Da0lPmj3.js → useDebouncedValue-C0FQyANW.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-Da0lPmj3.js.map → useDebouncedValue-C0FQyANW.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-DD_Esl6n.js → useNamespace-WW_XjAb3.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-DD_Esl6n.js.map → useNamespace-WW_XjAb3.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-AeAhZJJk.js → useYamlActivityEvents-B3YxPeFt.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-AeAhZJJk.js.map → useYamlActivityEvents-B3YxPeFt.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-B7OcUM6b.js → vendor-icons-CeVtUKyP.js} +2 -2
- package/dashboard/dist/assets/{vendor-icons-B7OcUM6b.js.map → vendor-icons-CeVtUKyP.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-BHAOOGvn.js → yaml-workflows-COHOjdhF.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-BHAOOGvn.js.map → yaml-workflows-COHOjdhF.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/accumulator.md +37 -1
- package/docs/api/mcp/admin.md +3 -2
- package/docs/api/sdk/escalations.md +6 -0
- package/docs/api/sdk/exports.md +1 -1
- package/docs/api/sdk/workflows.md +23 -4
- package/docs/cli.md +1 -1
- package/docs/dashboard.md +2 -2
- package/docs/faceted-routing.md +2 -0
- package/docs/hitl/x-lt-scan.md +51 -0
- package/docs/hitl/x-lt-widget.md +5 -0
- package/docs/hitl-guide.md +2 -0
- package/docs/scan-codes.md +252 -19
- package/package.json +1 -1
- package/build/types/scan-code.d.ts +0 -308
- package/dashboard/dist/assets/AvailableEscalationsPage-CpbC8oTN.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-CpbC8oTN.js.map +0 -1
- package/dashboard/dist/assets/CapabilitiesPage-RGgD3YZO.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-BaexQMK6.js +0 -2
- package/dashboard/dist/assets/EscalationSchemaPage-W5r0A1kj.js +0 -9
- package/dashboard/dist/assets/EscalationSchemaPage-W5r0A1kj.js.map +0 -1
- package/dashboard/dist/assets/EscalationTimeline-DKyTz6sM.js +0 -2
- package/dashboard/dist/assets/EscalationTimeline-DKyTz6sM.js.map +0 -1
- package/dashboard/dist/assets/McpQueryDetailPage-DYJr16l7.js +0 -5
- package/dashboard/dist/assets/McpQueryDetailPage-DYJr16l7.js.map +0 -1
- package/dashboard/dist/assets/ResolverForm-BwgjIX97.js +0 -7
- package/dashboard/dist/assets/ResolverForm-BwgjIX97.js.map +0 -1
- package/dashboard/dist/assets/RoleDetailPage-BFuLNJXa.js +0 -8
- package/dashboard/dist/assets/RoleDetailPage-BFuLNJXa.js.map +0 -1
- package/dashboard/dist/assets/ScanCodesPage-Cu1bKEix.js +0 -2
- package/dashboard/dist/assets/ScanCodesPage-Cu1bKEix.js.map +0 -1
- package/dashboard/dist/assets/ScanSchemeDetailPage-D9AbS6UY.js +0 -2
- package/dashboard/dist/assets/ScanSchemeDetailPage-D9AbS6UY.js.map +0 -1
- package/dashboard/dist/assets/ScanStationPage-gcZGefvT.js +0 -2
- package/dashboard/dist/assets/ScanStationPage-gcZGefvT.js.map +0 -1
- package/dashboard/dist/assets/index-B_GT23TE.js +0 -3
- package/dashboard/dist/assets/index-B_GT23TE.js.map +0 -1
- package/dashboard/dist/assets/index-CgUcYveM.js +0 -67
- package/dashboard/dist/assets/index-CgUcYveM.js.map +0 -1
- package/dashboard/dist/assets/index-Dh8MJl3L.css +0 -1
package/docs/scan-codes.md
CHANGED
|
@@ -23,6 +23,7 @@ canonical action surface. A scan is an **ECA rule** over that surface:
|
|
|
23
23
|
- [Rules and steps](#rules-and-steps)
|
|
24
24
|
- [Confirmation](#confirmation)
|
|
25
25
|
- [Info-choice screens](#info-choice-screens)
|
|
26
|
+
- [Holding an item: the bench motion](#holding-an-item-the-bench-motion)
|
|
26
27
|
- [Identity schemes and acting identity](#identity-schemes-and-acting-identity)
|
|
27
28
|
- [Station deployments](#station-deployments)
|
|
28
29
|
- [The fallback screen](#the-fallback-screen)
|
|
@@ -31,6 +32,7 @@ canonical action surface. A scan is an **ECA rule** over that surface:
|
|
|
31
32
|
- [Scanner setup](#scanner-setup)
|
|
32
33
|
- [Admin configuration](#admin-configuration)
|
|
33
34
|
- [The printer demo](#the-printer-demo)
|
|
35
|
+
- [The bag and bin demo](#the-bag-and-bin-demo)
|
|
34
36
|
|
|
35
37
|
## The code
|
|
36
38
|
|
|
@@ -62,6 +64,14 @@ A scheme (`lt_config_scan_schemes`, indexed 10–99) declares:
|
|
|
62
64
|
`1015949975930`. Fits UPC-A/EAN/ITF labels; a trailing check digit is
|
|
63
65
|
accepted. Two digits of version + one of category + `target_length`
|
|
64
66
|
digits of target.
|
|
67
|
+
- `gtin` — manufacturer barcodes: UPC-A, EAN-13, EAN-8 and GTIN-14, as
|
|
68
|
+
printed on products. The code carries no version or category; a valid
|
|
69
|
+
check digit identifies it. The target is the 14-digit GTIN (a UPC-A
|
|
70
|
+
`036000291452` targets `00036000291452`), `{scan.code}` keeps the code as
|
|
71
|
+
scanned, and the scheme's one rule is category `0`. A deployment has at
|
|
72
|
+
most one gtin scheme, and while it is enabled no enabled fixed scheme may
|
|
73
|
+
accept an 8, 12, 13 or 14 digit code: the scheme write is refused, naming
|
|
74
|
+
both schemes, so a digits-only code always has exactly one reading.
|
|
65
75
|
|
|
66
76
|
## Rules and steps
|
|
67
77
|
|
|
@@ -98,7 +108,21 @@ Verbs are the canonical escalation actions:
|
|
|
98
108
|
| `resolve` | Atomic claim + resolve with a canned payload | `resolverPayload`, `metadata` |
|
|
99
109
|
| `escalate` | Create an escalation in another queue, optionally closing the located one | `targetRole`, `closeCurrent`, `escalationType`, `description`, `metadata` |
|
|
100
110
|
| `cancel` | Claim-as-lock, then cancel | — |
|
|
101
|
-
| `accumulate` | Add the scanned item to an open accumulator escalation | `itemKey` (template), `resolverPayload`, `metadata`, `accumulate: { containerFacet, containerRoles, reciprocal }` |
|
|
111
|
+
| `accumulate` | Add the scanned item to an open accumulator escalation | `itemKey` (template), `resolverPayload`, `metadata`, `accumulate: { containerFacet, container, containerRoles, reciprocal }` |
|
|
112
|
+
|
|
113
|
+
`availability` names the claim state a step's row must be in:
|
|
114
|
+
|
|
115
|
+
| `availability` | Matches |
|
|
116
|
+
|---|---|
|
|
117
|
+
| `mine` | a row under a live claim held by the acting identity (the badged user, else the session user) |
|
|
118
|
+
| `available` | an unclaimed row, or one whose claim has lapsed |
|
|
119
|
+
| `claimed` | a row under anyone's live claim |
|
|
120
|
+
| `any` (default) | every row the rest of the query matches |
|
|
121
|
+
|
|
122
|
+
A `resolve` step applies it inside the atomic resolve: `mine` resolves the
|
|
123
|
+
actor's own claim, the most recently claimed first when there are several,
|
|
124
|
+
so a container scan places the item in the associate's hand even when
|
|
125
|
+
another item for the same container is waiting. With no matching row the step falls through.
|
|
102
126
|
|
|
103
127
|
String values inside `itemKey`, `resolverPayload`, and `metadata` interpolate
|
|
104
128
|
`{scan.target}`, `{scan.category}`, and `{scan.scannedAt}`. Two facet bags
|
|
@@ -107,27 +131,44 @@ extend them: `{claim.<facet>}` reads the acting user's single live claim
|
|
|
107
131
|
make the step fall through), and `{item.<facet>}` reads the row an item-mode
|
|
108
132
|
`accumulate` step located. A token that cannot resolve falls through instead
|
|
109
133
|
of writing the literal, and the rule editor rejects `{item.…}` on any other
|
|
110
|
-
step.
|
|
111
|
-
`"itemKey": "{claim.
|
|
134
|
+
step. An item-first ladder therefore names the item from the claim:
|
|
135
|
+
`"itemKey": "{claim.itemId}"` on the container scan. Every mutating verb stamps
|
|
112
136
|
provenance facets onto the row it touches — `scanScheme`, `scanCategory`,
|
|
113
137
|
`scanActionName`, `scannedAt` — so scan-driven transitions stay queryable.
|
|
114
138
|
|
|
115
139
|
`accumulate` has two modes. With `params.accumulate.containerFacet` the
|
|
116
140
|
scanned target is the ITEM: the step locates the item's own pending row
|
|
117
|
-
through the scheme facet, reads that facet from the row (
|
|
118
|
-
`
|
|
141
|
+
through the scheme facet, reads that facet from the row (an item row carrying
|
|
142
|
+
`containerKey: "C-7"`), and adds the target to the pending accumulator whose
|
|
119
143
|
metadata carries the same value, writing the item's row as the reciprocal in
|
|
120
|
-
the same statement (`reciprocal: false` skips it
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
144
|
+
the same statement (`reciprocal: false` skips it). The container pick
|
|
145
|
+
considers only pending rows that carry the accumulator declaration, so a
|
|
146
|
+
release row sharing the facet during a pack-out is never the target.
|
|
147
|
+
`container` narrows the pick further:
|
|
148
|
+
|
|
149
|
+
```jsonc
|
|
150
|
+
"accumulate": {
|
|
151
|
+
"containerFacet": "containerKey",
|
|
152
|
+
"container": {
|
|
153
|
+
"roles": ["packing"], // container queues (containerRoles is an alias)
|
|
154
|
+
"types": ["container"], // escalation type
|
|
155
|
+
"subtypes": ["open"], // escalation subtype
|
|
156
|
+
"facets": { "open": true } // extra metadata guards
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
A design that parks each item as its own accumulator in the same queue as
|
|
162
|
+
its container (an item's slot beside its container, both carrying
|
|
163
|
+
`containerKey`) declares the container's type or subtype, so the add lands in
|
|
164
|
+
the container and never in a sibling's slot. The item's own row is never its container. Without it the scanned target is the CONTAINER and the step
|
|
124
165
|
adds `params.itemKey` (a template) to it. An item with no row or no container
|
|
125
166
|
facet falls through to the next step; a container already holding the item
|
|
126
167
|
reports a conflict. When the item's row exists but no pending container
|
|
127
168
|
carries its facet (the previous container closed and its successor has not
|
|
128
169
|
parked yet), the step answers `no_open_container` with the item row, the
|
|
129
170
|
facet, and the rule's fallback markdown, so the station reads "Container
|
|
130
|
-
closing, scan again" instead of the
|
|
171
|
+
closing, scan again" instead of the item with no hint.
|
|
131
172
|
|
|
132
173
|
Ordering is the power move: put the expected state first and a broad
|
|
133
174
|
`show-detail` last. A machine whose twin is in the wrong queue still answers
|
|
@@ -151,7 +192,7 @@ guarded call every other surface uses.
|
|
|
151
192
|
|
|
152
193
|
## Info-choice screens
|
|
153
194
|
|
|
154
|
-
Some objects carry one code for their whole life — an item tag,
|
|
195
|
+
Some objects carry one code for their whole life — an item tag, a record
|
|
155
196
|
label. One code, many possible intents, and the right one depends on where
|
|
156
197
|
the object is in its journey. The `present` verb closes that gap: the step
|
|
157
198
|
locates the row, states its reality, and returns a configured, labeled
|
|
@@ -178,8 +219,10 @@ unsatisfied. Picking one calls `POST /api/scan-codes/execute-choice` with a
|
|
|
178
219
|
pointer (scheme, category, step index, choice index, escalation id) — and a
|
|
179
220
|
pointer is never authority: the server re-reads live config, re-locates the
|
|
180
221
|
row under the step's query, re-applies the identity gate, and runs the verb
|
|
181
|
-
through the same atomic executors a direct scan uses. A
|
|
182
|
-
|
|
222
|
+
through the same atomic executors a direct scan uses. A resolve choice
|
|
223
|
+
resolves the exact row the screen presented, re-checked under the step's
|
|
224
|
+
query in the same statement. A row that moved on between render and tap
|
|
225
|
+
answers `conflict`, exactly as a lost double-scan.
|
|
183
226
|
|
|
184
227
|
A choice's `code` is a short printable token (letters, digits, underscore,
|
|
185
228
|
dash) enabling double-scan selection: scan the object, then scan an action
|
|
@@ -198,6 +241,121 @@ duration, form on screen. An unsatisfied identity requirement never
|
|
|
198
241
|
auto-fires as the wrong actor — the scan stops over at the badge screen and
|
|
199
242
|
completes on its own once a badge primes.
|
|
200
243
|
|
|
244
|
+
## Holding an item: the bench motion
|
|
245
|
+
|
|
246
|
+
At a bench where items go into containers, every act is one item going into
|
|
247
|
+
one container, or one expected item checked off a record. The motion is three scans with nothing in between: **the item, your badge, the
|
|
248
|
+
container**. The container scan is the act. The item scan only says which
|
|
249
|
+
item; the badge says who.
|
|
250
|
+
|
|
251
|
+
**`hold`** is the item scan. The step locates the row and answers `held`
|
|
252
|
+
with a **subject**: the code that held it, the row id, a label, an expiry,
|
|
253
|
+
and what to scan next. It writes nothing and spends no badge use. The
|
|
254
|
+
station keeps the subject (device-local, in memory) and sends it back with
|
|
255
|
+
the next scans as `subject: { code, escalationId }`. Scanning another item
|
|
256
|
+
replaces it; it lapses on its own after `ttlSeconds` (default 45).
|
|
257
|
+
|
|
258
|
+
```jsonc
|
|
259
|
+
{ "query": { "roles": ["packing"] }, "verb": "hold",
|
|
260
|
+
"params": { "hold": { "ttlSeconds": 300, "label": "{scan.target}",
|
|
261
|
+
"headline": "{item.containerCode}", "subline": "{item.locationName}",
|
|
262
|
+
"expect": { "schemes": [14], "prompt": "Walk to this container and scan it.\n\n{item.labelNote}" } } } }
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**What the station shows.** With `hold.headline` the destination leads the
|
|
266
|
+
screen: the headline (e.g. `{item.containerCode}`) in very large type, `hold.subline`
|
|
267
|
+
under it (e.g. `{item.locationName}`), the held item itself as a quieter line
|
|
268
|
+
above, then the `expect.prompt`. A template that renders empty drops its line,
|
|
269
|
+
so a row-level note such as `{item.labelNote}` appears only when the workflow
|
|
270
|
+
set one ("Take the new label from the printer and stick it on C-12").
|
|
271
|
+
Any step that writes may carry `done: { markdown }`: the copy the station shows,
|
|
272
|
+
large, once the write lands and until the next scan ("Place it in
|
|
273
|
+
**{container.containerCode}**. All good."). It reads the same bags its refusal copy
|
|
274
|
+
reads. A fill that leaves items to scan shows its done copy as the progress
|
|
275
|
+
line under the hold.
|
|
276
|
+
|
|
277
|
+
The server trusts nothing about the subject. Each request re-parses its
|
|
278
|
+
code, re-reads the row under the station's read scope, requires the row to
|
|
279
|
+
still carry the code's target and to be pending. A subject that fails is
|
|
280
|
+
stale: steps that need one are skipped, and when nothing else matches the
|
|
281
|
+
answer is `subject_stale` with `clearSubject: true`.
|
|
282
|
+
|
|
283
|
+
**Subject steps** run only while a subject from one of `subject.schemes` is
|
|
284
|
+
held, and act on it. The `{subject.<facet>}` template bag reads the held
|
|
285
|
+
row.
|
|
286
|
+
|
|
287
|
+
| Step | What the container scan does |
|
|
288
|
+
|---|---|
|
|
289
|
+
| `accumulate` with `accumulate.from: "subject"` | The held item joins the accumulator the scan names (found by the scheme facet, narrowed by `accumulate.container`). The held row is written as the reciprocal in the same statement, so a held row parked as a one-slot accumulator completes and its workflow wakes. `params.itemKey` names the item, e.g. `{subject.itemId}`. |
|
|
290
|
+
| `accumulate` with `accumulate.into: "subject"` | The held row collects the scanned code (`itemKey` defaults to `{scan.target}`). Use it when the container has no row yet: the first item for a container tells the workflow which container was scanned. |
|
|
291
|
+
| `fill` with `fill.into: "subject"` | One expected item is checked off: the held row is a batch whose keys are codes, and the scan fills the first open key for its code. A code expected twice is declared `<code>#1`, `<code>#2` and takes two scans; a third is refused. The answer carries `progress: { filled, total, remaining }`, the subject stays held while items remain, and the last fill completes the row. `fill.into: "scanned"` fills the row the scan itself names. |
|
|
292
|
+
|
|
293
|
+
**`match` and `refuse`** check the pairing before anything is written.
|
|
294
|
+
`match.target` lists templates the scanned target must equal (e.g.
|
|
295
|
+
`["{subject.containerCode}"]`); `match.facets` lists facets the located container
|
|
296
|
+
must share with the held row (e.g. `["containerKey"]`). A miss answers `refused`
|
|
297
|
+
with `refuse.markdown` rendered, and nothing is written. The copy may read
|
|
298
|
+
`{container.<facet>}` (the container the scan named) and `{fill.pending}`
|
|
299
|
+
(what a fill still expects), so the station says what is wrong and where the
|
|
300
|
+
item goes: "That's Acme West's container. This one goes in **C-12**." When the
|
|
301
|
+
write itself loses a race (the container closed, another bench took the free
|
|
302
|
+
container), the answer is `refused` with `refuse.conflict`, and a step that
|
|
303
|
+
declares `refuse.conflict` also clears the subject so the next item scan
|
|
304
|
+
reads fresh state. Exactly one of two racing acts wins whenever both name
|
|
305
|
+
the same row: the reciprocal statement writes both rows or neither.
|
|
306
|
+
|
|
307
|
+
**One rule, several kinds of held item.** `subject.facets` makes a step
|
|
308
|
+
apply only while the held row carries those facet values; otherwise the step
|
|
309
|
+
is skipped and the next one runs. A placing bench uses it to tell an item
|
|
310
|
+
whose destination already has a container from one that needs a free
|
|
311
|
+
container: the item row carries `placement: 'assigned'` or `'unassigned'`, and
|
|
312
|
+
the container label's rule has one step for each.
|
|
313
|
+
|
|
314
|
+
```jsonc
|
|
315
|
+
// 14:0, container label
|
|
316
|
+
[
|
|
317
|
+
{ "verb": "accumulate", "requireActingIdentity": true,
|
|
318
|
+
"subject": { "schemes": [11], "facets": { "placement": "assigned" } },
|
|
319
|
+
"match": { "target": ["{subject.containerCode}"] },
|
|
320
|
+
"refuse": { "markdown": "That's {container.locationName}'s container. This one goes in **{subject.containerCode}**." },
|
|
321
|
+
"params": { "itemKey": "{subject.itemId}",
|
|
322
|
+
"accumulate": { "from": "subject", "container": { "types": ["container"], "subtypes": ["open"] } } } },
|
|
323
|
+
{ "verb": "accumulate", "requireActingIdentity": true,
|
|
324
|
+
"subject": { "schemes": [11], "facets": { "placement": "unassigned" } },
|
|
325
|
+
"match": { "target": ["{subject.offeredContainers}"] },
|
|
326
|
+
"refuse": { "markdown": "Choose a free container: {subject.offeredContainers}.",
|
|
327
|
+
"conflict": "That container was just taken. Scan the item again.",
|
|
328
|
+
"missing": "That container was just taken. Scan the item again." },
|
|
329
|
+
"params": { "itemKey": "{subject.itemId}",
|
|
330
|
+
"accumulate": { "from": "subject", "container": { "types": ["container"], "subtypes": ["free"] } } } },
|
|
331
|
+
{ "query": { "roles": ["packing"] }, "verb": "present", "choices": [ /* Close this container, View container */ ] }
|
|
332
|
+
]
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
The workflow stamps the containers it offers on the item row (`offeredContainers`). A
|
|
336
|
+
`match.target` entry that is a lone token naming a list facet allows every
|
|
337
|
+
entry, so any offered container takes the item and any other is refused with
|
|
338
|
+
the offer listed. A free container is a `max: 1` accumulator row, so of two
|
|
339
|
+
items racing for one free container exactly one lands; the other is refused with the
|
|
340
|
+
conflict copy. `refuse.missing` covers an offered container with no open row (taken
|
|
341
|
+
a moment ago): the scan is refused instead of falling through to the next
|
|
342
|
+
step. The third step has no subject gate: scanning a container with no item
|
|
343
|
+
held offers to close it.
|
|
344
|
+
|
|
345
|
+
Someone else's live claim on the held row refuses the act with their name
|
|
346
|
+
(`subject.claimedByOther: "allow"` lifts this). An item already in the
|
|
347
|
+
scanned container answers `executed` with `already: true`, and nothing is
|
|
348
|
+
written twice.
|
|
349
|
+
|
|
350
|
+
The badge can come before the item or between the item and the container. A
|
|
351
|
+
container scan that needs a badge answers `not_primed` with
|
|
352
|
+
`replayable: true`; the station keeps the subject, asks for the badge, and
|
|
353
|
+
replays the container scan once the badge primes.
|
|
354
|
+
|
|
355
|
+
Subject steps sit beside the steps a rule already has: with no subject held
|
|
356
|
+
they are skipped, so the same rule keeps working for scans made without the
|
|
357
|
+
item scan first.
|
|
358
|
+
|
|
201
359
|
## Identity schemes and acting identity
|
|
202
360
|
|
|
203
361
|
A scheme with `kind: "identity"` is the badge layer. Its `target_facet`
|
|
@@ -214,7 +372,39 @@ scheme's policy:
|
|
|
214
372
|
| Scheme field | Meaning |
|
|
215
373
|
|---|---|
|
|
216
374
|
| `grant_ttl_seconds` | How long the grant lives (1–86400). |
|
|
217
|
-
| `grant_max_uses` | `0` = TTL-bound; `n` = the grant covers n
|
|
375
|
+
| `grant_max_uses` | `0` = TTL-bound; `n` = the grant covers n acts (a strict one-act policy is `1`). |
|
|
376
|
+
| `grant_scope` | `action` (default): each act spends one use. `subject`: the first act binds the grant to the held subject; further acts on that subject spend nothing, and the grant acts on no other subject. One badge then covers one item's whole motion (every part checked off one record) and never carries to the next item. |
|
|
377
|
+
|
|
378
|
+
**The station decides the policy.** One printed badge works at every bench,
|
|
379
|
+
but benches want different policies: a workstation grants one act per badge
|
|
380
|
+
scan (claim, then submit, takes two scans), a high-volume placing bench grants
|
|
381
|
+
ten minutes of acts. A role may declare its stations' policy in `properties.badge_grant`:
|
|
382
|
+
|
|
383
|
+
```jsonc
|
|
384
|
+
"properties": { "kiosk": true, "badge_grant": { "ttl_seconds": 600, "max_uses": 0 } }
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
A badge scanned on a device signed in as a member of that role mints under
|
|
388
|
+
it; fields left out keep the badge scheme's values (`scope` is the role's
|
|
389
|
+
`grant_scope`). A device that belongs to several roles with different
|
|
390
|
+
policies uses the role it is locked to (the dashboard sends its kiosk role as
|
|
391
|
+
`stationRole` with every scan); with no role policy, or no way to choose
|
|
392
|
+
between several, the badge scheme's own policy applies. The policy is
|
|
393
|
+
validated where the role is written: an unusable `badge_grant` is a 400 from
|
|
394
|
+
the role API and fails a code-owned role's startup apply. The role page edits
|
|
395
|
+
it under **Members → Badge at this station**.
|
|
396
|
+
|
|
397
|
+
A grant is spent by **acts**, not by looking. A scan that shows, presents,
|
|
398
|
+
holds, or refuses reads the grant without spending it; a mutating verb spends
|
|
399
|
+
one use just before it writes, and a write that does not land (the step
|
|
400
|
+
falls through, the scan is refused) gives the use back. Every scan response
|
|
401
|
+
that carried a grant reports `acting: { consumed, remaining, bound }`, and
|
|
402
|
+
the escalation work routes report the uses left in the
|
|
403
|
+
`X-LT-Acting-Remaining` header. The device retires its copy of the grant when
|
|
404
|
+
the server reports none left, or when a subject-bound grant's subject is
|
|
405
|
+
done; reads never carry the grant at all. A scan that comes back
|
|
406
|
+
`not_primed` while a grant is held drops that grant, so the next scan runs
|
|
407
|
+
unprimed instead of repeating the badge screen.
|
|
218
408
|
|
|
219
409
|
The grant rides subsequent scans as `actingToken`. Verbs then run **as the
|
|
220
410
|
badged person under their own live RBAC** — the grant confers attribution,
|
|
@@ -300,6 +490,12 @@ to continue. The badge scan primes the session and the pending action
|
|
|
300
490
|
completes on its own. With a live grant the stop-over never appears — the
|
|
301
491
|
identity layer is invisible when all is well.
|
|
302
492
|
|
|
493
|
+
A field can take a scan while the form is open: with
|
|
494
|
+
[`x-lt-scan`](hitl/x-lt-scan.md), scanning a container into a claimed form
|
|
495
|
+
fills its container field (checked against what the record expects), and
|
|
496
|
+
`x-lt-scan-submit` submits once the scan fields are filled, which raises the
|
|
497
|
+
badge prompt. A scan no field accepts runs globally as usual.
|
|
498
|
+
|
|
303
499
|
Badge tokens are printed credentials: seed them as long random strings,
|
|
304
500
|
bind them server-side (`lt_users.metadata`), and treat badge possession
|
|
305
501
|
with the same physical policy as any badge system. Unknown badges answer
|
|
@@ -314,9 +510,10 @@ renders the markdown; a configured route navigates.
|
|
|
314
510
|
|
|
315
511
|
## Executing a scan
|
|
316
512
|
|
|
317
|
-
`POST /api/scan-codes/execute` takes `{ "code": "10:1:SN-123" }`
|
|
318
|
-
|
|
319
|
-
200
|
|
513
|
+
`POST /api/scan-codes/execute` takes `{ "code": "10:1:SN-123" }` (plus
|
|
514
|
+
`actingToken` and `subject` when the station holds them) and runs as the
|
|
515
|
+
calling user under normal RBAC. Every terminal state is a structured 200
|
|
516
|
+
outcome:
|
|
320
517
|
|
|
321
518
|
| Outcome | Meaning |
|
|
322
519
|
|---------|---------|
|
|
@@ -329,6 +526,15 @@ as the calling user under normal RBAC. Every terminal state is a structured
|
|
|
329
526
|
| `invalid_code` | The string parses under no enabled scheme |
|
|
330
527
|
| `forbidden` | The caller's roles bar the matched action |
|
|
331
528
|
| `conflict` | A concurrent actor won the row |
|
|
529
|
+
| `choices` | A `present` step located its row; `escalation` + `choices` included |
|
|
530
|
+
| `held` | A `hold` step located its row; `subject` included |
|
|
531
|
+
| `refused` | The scan was understood and not acted on; nothing written; `refusal.markdown` (and `refusal.expected`) included |
|
|
532
|
+
| `subject_stale` | The held subject moved on; `clearSubject: true` |
|
|
533
|
+
| `not_primed` | The act needs a badge; `notPrimed` included, `replayable: true` when the scan may run again once one primes |
|
|
534
|
+
| `identity_primed` / `identity_unknown` | A badge scan matched a person, or did not |
|
|
535
|
+
|
|
536
|
+
A step's payload rejected by the role's form schema answers `refused` with
|
|
537
|
+
the reason, never a raw 422.
|
|
332
538
|
|
|
333
539
|
The endpoint is source-agnostic — anything that produces a string can drive
|
|
334
540
|
it: a barcode scanner, an RFID reader, a camera decode, an MCP tool
|
|
@@ -348,8 +554,18 @@ When enabled, the dashboard listens for scans globally — any page, any focus
|
|
|
348
554
|
state. A scanner paired as an HID keyboard "types" its decode and finishes
|
|
349
555
|
with Enter; capture is **pattern-anchored**: a capture-phase window listener
|
|
350
556
|
accumulates keystrokes freely, and when the terminator arrives it checks
|
|
351
|
-
whether the recent keys end with a scan-code shape
|
|
352
|
-
|
|
557
|
+
whether the recent keys end with a scan-code shape. The shapes come from the
|
|
558
|
+
configured schemes: each delimited version's `VV:C:target`, each fixed
|
|
559
|
+
scheme's exact digit lengths, and for a gtin scheme a whole 8, 12, 13 or 14
|
|
560
|
+
digit run whose check digit holds (a leading zero is part of the code). A
|
|
561
|
+
code never starts inside a longer run of digits.
|
|
562
|
+
|
|
563
|
+
- **Digits-only codes fire only at scanner speed** (avg ≤ 50 ms/key). A
|
|
564
|
+
typed PO number or count followed by Enter stays in its field, even when
|
|
565
|
+
its digits happen to form a valid barcode.
|
|
566
|
+
- **An open form can take the scan first.** A field with
|
|
567
|
+
[`x-lt-scan`](hitl/x-lt-scan.md) that accepts the scan's scheme is filled
|
|
568
|
+
instead; every other scan, and every badge, runs globally.
|
|
353
569
|
|
|
354
570
|
- On a match, the terminator is swallowed, the code's characters are
|
|
355
571
|
stripped back out of whatever editable held focus (byte-exact, at the
|
|
@@ -454,3 +670,20 @@ of each machine:
|
|
|
454
670
|
Each rule ends on a broad `show-detail` and the "no twin found" fallback.
|
|
455
671
|
Walk it hardware-free: run the twin farm, open the scan panel, and paste
|
|
456
672
|
`10:1:<a-printing-serial>`.
|
|
673
|
+
|
|
674
|
+
## The bag and bin demo
|
|
675
|
+
|
|
676
|
+
`examples/seed-scan-bins.ts` puts the bench motion on the
|
|
677
|
+
[rollup-bin](../examples/workflows/rollup-bin/) example. Start a `rollupBin`
|
|
678
|
+
with a `binKey` and a few `rollupMember` bags carrying the same `binKey`,
|
|
679
|
+
then at the scan station:
|
|
680
|
+
|
|
681
|
+
| Scan | Code | What happens |
|
|
682
|
+
|---|---|---|
|
|
683
|
+
| Bag | `12:0:<orderId>` | The station holds the bag and shows its bin, large |
|
|
684
|
+
| Badge | `11:0:<badge>` | Primes the person (before the bag works too) |
|
|
685
|
+
| Bin | `13:0:<binKey>` | The bag joins the bin and its own row completes; the station shows "Drop it in **bin-7**. All good." until the next scan |
|
|
686
|
+
|
|
687
|
+
Scan a different bin's label instead and the station refuses with the bag's
|
|
688
|
+
bin named, and nothing is written. Scan the bin before the badge and the
|
|
689
|
+
station asks for the badge, then places the bag on its own.
|
package/package.json
CHANGED