@hotmeshio/long-tail 0.22.1 → 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.js +38 -19
- 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 +16 -10
- 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 +1 -21
- package/build/api/scan-codes/verbs.js +26 -115
- package/build/index.d.ts +1 -0
- package/build/index.js +8 -2
- package/build/lib/db/schemas/037_scan_gtin_and_subject_grants.sql +27 -0
- 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/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/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 +94 -18
- package/build/services/scan-code/write.d.ts +1 -0
- package/build/services/scan-code/write.js +9 -3
- 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/system/mcp-servers/admin/scan-codes.js +10 -4
- package/build/system/mcp-servers/admin/schemas.d.ts +754 -23
- package/build/system/mcp-servers/admin/schemas.js +57 -4
- package/build/system/mcp-servers/human-queue-schemas.d.ts +6 -6
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/escalation.d.ts +2 -0
- package/build/types/escalation.js +3 -1
- package/build/types/index.d.ts +2 -2
- 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} +72 -11
- 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-BbWve-Ax.js → AdminDashboard-DBW12qQt.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-BbWve-Ax.js.map → AdminDashboard-DBW12qQt.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-M-9eTKhP.js → AgentConfigPage-CmHv8U9M.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-M-9eTKhP.js.map → AgentConfigPage-CmHv8U9M.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-CsakSlx5.js → AgentDetailPage-D1scIbz-.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-CsakSlx5.js.map → AgentDetailPage-D1scIbz-.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-Cj_cRTT1.js → AgentsPage-BA_ai9HJ.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-Cj_cRTT1.js.map → AgentsPage-BA_ai9HJ.js.map} +1 -1
- package/dashboard/dist/assets/{AvailableEscalationsPage-BXJmMBM1.js → AvailableEscalationsPage-C2_5aEFW.js} +2 -2
- package/dashboard/dist/assets/{AvailableEscalationsPage-BXJmMBM1.js.map → AvailableEscalationsPage-C2_5aEFW.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-CGB16rYU.js → BotPicker-BZo4Kp4a.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-CGB16rYU.js.map → BotPicker-BZo4Kp4a.js.map} +1 -1
- package/dashboard/dist/assets/{BulkAssignModal-MjxcU7N1.js → BulkAssignModal-BFhyxY2T.js} +2 -2
- package/dashboard/dist/assets/{BulkAssignModal-MjxcU7N1.js.map → BulkAssignModal-BFhyxY2T.js.map} +1 -1
- package/dashboard/dist/assets/CapabilitiesPage-CvOX6vAc.js +2 -0
- package/dashboard/dist/assets/{CapabilitiesPage-BxadotXn.js.map → CapabilitiesPage-CvOX6vAc.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-BBNpP-6h.js → CollapsibleSection-GCJsV9Oq.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-BBNpP-6h.js.map → CollapsibleSection-GCJsV9Oq.js.map} +1 -1
- package/dashboard/dist/assets/{ConfirmDeleteModal-D_kAbT_D.js → ConfirmDeleteModal-CAgYLcef.js} +2 -2
- package/dashboard/dist/assets/{ConfirmDeleteModal-D_kAbT_D.js.map → ConfirmDeleteModal-CAgYLcef.js.map} +1 -1
- package/dashboard/dist/assets/CountdownTimer-Dik2z0M_.js +2 -0
- package/dashboard/dist/assets/{CountdownTimer-CI_JOAvk.js.map → CountdownTimer-Dik2z0M_.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-C9OA1Q2J.js → CredentialsPage-twd2xCOW.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-C9OA1Q2J.js.map → CredentialsPage-twd2xCOW.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-sxLLBf2I.js → CronLabel-DdnIuudX.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-sxLLBf2I.js.map → CronLabel-DdnIuudX.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-jH9m8Dgl.js → ElapsedCell-DCctVv5R.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-jH9m8Dgl.js.map → ElapsedCell-DCctVv5R.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-Dl3Nr2kk.js → EntityTimelinePanel-CMnskyWv.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-Dl3Nr2kk.js.map → EntityTimelinePanel-CMnskyWv.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-DAK6It5J.js → EscalationListSchemaPage-VfCn6WDb.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-DAK6It5J.js.map → EscalationListSchemaPage-VfCn6WDb.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListView-CAHbdxKR.js → EscalationListView-CGQZxcC-.js} +2 -2
- package/dashboard/dist/assets/{EscalationListView-CAHbdxKR.js.map → EscalationListView-CGQZxcC-.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-DotfAMCL.js → EscalationSchemaPage-BX0tx-PM.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-DotfAMCL.js.map → EscalationSchemaPage-BX0tx-PM.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTimeline-DqmFydnU.js → EscalationTimeline-DKoSM56J.js} +2 -2
- package/dashboard/dist/assets/{EscalationTimeline-DqmFydnU.js.map → EscalationTimeline-DKoSM56J.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTitleSelect-BpRquguO.js → EscalationTitleSelect-DWGLBOmS.js} +2 -2
- package/dashboard/dist/assets/{EscalationTitleSelect-BpRquguO.js.map → EscalationTitleSelect-DWGLBOmS.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-DtGOqnP4.js → EscalationsOverview-C2XoguaA.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-DtGOqnP4.js.map → EscalationsOverview-C2XoguaA.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-DSHqKyX2.js → EventTable-CBUWq7--.js} +2 -2
- package/dashboard/dist/assets/{EventTable-DSHqKyX2.js.map → EventTable-CBUWq7--.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-Dxd0wNSW.js → FilterBar-8IdbleZ9.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-Dxd0wNSW.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-ChqqGkro.js → GraphInvokePage-CUvoPzsW.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-ChqqGkro.js.map → GraphInvokePage-CUvoPzsW.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-ByKesG8w.js → HomePage-BP7v9GLJ.js} +2 -2
- package/dashboard/dist/assets/{HomePage-ByKesG8w.js.map → HomePage-BP7v9GLJ.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-Ddz_S2av.js → ListToolbar-Cnacuwoy.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-Ddz_S2av.js.map → ListToolbar-Cnacuwoy.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-CVe13tEv.js → McpOverview-C2JoNoDA.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-CVe13tEv.js.map → McpOverview-C2JoNoDA.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-BQYF2Mjq.js → McpQueryDetailPage-C_nih0w-.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-BQYF2Mjq.js.map → McpQueryDetailPage-C_nih0w-.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-DZi5lm7s.js → McpQueryPage-U_wNXow2.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-DZi5lm7s.js.map → McpQueryPage-U_wNXow2.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-DreARTE1.js → McpRunDetailPage-DtKoJq6J.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-DreARTE1.js.map → McpRunDetailPage-DtKoJq6J.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-DmO0YVhT.js → McpRunsPage-CnYtfGhf.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-DmO0YVhT.js.map → McpRunsPage-CnYtfGhf.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-DpjCO85T.js → OperationsPage-C7hupIer.js} +2 -2
- package/dashboard/dist/assets/{OperationsPage-DpjCO85T.js.map → OperationsPage-C7hupIer.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-Vv_MEBkv.js → OperatorDashboard-fVuLn2D5.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-Vv_MEBkv.js.map → OperatorDashboard-fVuLn2D5.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-CW-2uBHY.js → PersonaDetailPage-C-4o8lPw.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-CW-2uBHY.js.map → PersonaDetailPage-C-4o8lPw.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-CO6yYQdm.js → PersonasPage-BL1FwLmv.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-CO6yYQdm.js.map → PersonasPage-BL1FwLmv.js.map} +1 -1
- package/dashboard/dist/assets/{PortalPage-DcNqhBlg.js → PortalPage-tJG5sgb1.js} +2 -2
- package/dashboard/dist/assets/{PortalPage-DcNqhBlg.js.map → PortalPage-tJG5sgb1.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-BuipGZcC.js → ProcessDetailPage-Dz_jY4Yt.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-BuipGZcC.js.map → ProcessDetailPage-Dz_jY4Yt.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-D9DYntvl.js → ProcessesListPage-Cbn9cter.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-D9DYntvl.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/{RolesPage-0QJOBSzF.js → RolesPage-NwmMvZFa.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-0QJOBSzF.js.map → RolesPage-NwmMvZFa.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-Dh4lyyRo.js → RunAsSelector-tgEooTyU.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-Dh4lyyRo.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/{StickyPagination-BSUyf5ja.js → StickyPagination-CsTI_gvJ.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-BSUyf5ja.js.map → StickyPagination-CsTI_gvJ.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail--tp7l2Sd.js → StreamMessageDetail-auRlvjTh.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail--tp7l2Sd.js.map → StreamMessageDetail-auRlvjTh.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-CxBZ2THh.js → SwimlaneTimeline-BLoVHYAd.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-CxBZ2THh.js.map → SwimlaneTimeline-BLoVHYAd.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-BJ1QrmPH.js → TaskDetailPage-BPsZ1bK_.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-BJ1QrmPH.js.map → TaskDetailPage-BPsZ1bK_.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-5BydGWmt.js → TasksListPage-BNGM74yT.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-5BydGWmt.js.map → TasksListPage-BNGM74yT.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-CCnz84Y4.js → TimeAgo-BnAHXGK7.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-CCnz84Y4.js.map → TimeAgo-BnAHXGK7.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-D0ru7Lya.js → TimestampCell-J4yae6mc.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-D0ru7Lya.js.map → TimestampCell-J4yae6mc.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-3Kpofmen.js → ToolTestPanel-BdzzgXDu.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-3Kpofmen.js.map → ToolTestPanel-BdzzgXDu.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-BaBXD_AK.js → TopicDetailPage-DJKg8lb7.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-BaBXD_AK.js.map → TopicDetailPage-DJKg8lb7.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-Cnm1AAjh.js → TopicsPage-DQV0WxG6.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-Cnm1AAjh.js.map → TopicsPage-DQV0WxG6.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-CXsdPiMZ.js → UserName-Ct09nGh5.js} +2 -2
- package/dashboard/dist/assets/{UserName-CXsdPiMZ.js.map → UserName-Ct09nGh5.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-zx3AUJFd.js → WorkflowExecutionPage-B5WJOsee.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-zx3AUJFd.js.map → WorkflowExecutionPage-B5WJOsee.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-DfAGK1l7.js → WorkflowsDashboard-Hc87TRgD.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-DfAGK1l7.js.map → WorkflowsDashboard-Hc87TRgD.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-QIYvoa13.js → WorkflowsOverview-CJQbyOj-.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-QIYvoa13.js.map → WorkflowsOverview-CJQbyOj-.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-DGgO3hyB.js → YamlWorkflowDetailPage-BMeED677.js} +8 -8
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-DGgO3hyB.js.map → YamlWorkflowDetailPage-BMeED677.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-CEsHm0B9.js → YamlWorkflowsPage-BMMg0Id6.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-CEsHm0B9.js.map → YamlWorkflowsPage-BMMg0Id6.js.map} +1 -1
- package/dashboard/dist/assets/{agents-v_HH3Rji.js → agents-CdFkgFvg.js} +2 -2
- package/dashboard/dist/assets/{agents-v_HH3Rji.js.map → agents-CdFkgFvg.js.map} +1 -1
- package/dashboard/dist/assets/{bots-bwvWYrXz.js → bots-Mj3LHWWg.js} +2 -2
- package/dashboard/dist/assets/{bots-bwvWYrXz.js.map → bots-Mj3LHWWg.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-D4vaw_nQ.js → capabilities-Dw1ObK2-.js} +2 -2
- package/dashboard/dist/assets/{capabilities-D4vaw_nQ.js.map → capabilities-Dw1ObK2-.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-CiiZ6LJF.js → controlplane-DcNE1APv.js} +2 -2
- package/dashboard/dist/assets/{controlplane-CiiZ6LJF.js.map → controlplane-DcNE1APv.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-Dv-MB3eC.js → escalation-columns-D364Trpy.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-Dv-MB3eC.js.map → escalation-columns-D364Trpy.js.map} +1 -1
- package/dashboard/dist/assets/{index-IJmtbuLh.js → index-B3veJ698.js} +2 -2
- package/dashboard/dist/assets/{index-IJmtbuLh.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-D2VKBMng.js → index-BRGTmoYY.js} +2 -2
- package/dashboard/dist/assets/{index-D2VKBMng.js.map → index-BRGTmoYY.js.map} +1 -1
- package/dashboard/dist/assets/{index-C4Lce2ET.js → index-Bd6-KmBE.js} +3 -3
- package/dashboard/dist/assets/{index-C4Lce2ET.js.map → index-Bd6-KmBE.js.map} +1 -1
- package/dashboard/dist/assets/{index-CcuvGdvf.js → index-BiVce3n0.js} +2 -2
- package/dashboard/dist/assets/{index-CcuvGdvf.js.map → index-BiVce3n0.js.map} +1 -1
- package/dashboard/dist/assets/{index-D6pBLZFu.js → index-BmNAVd4s.js} +2 -2
- package/dashboard/dist/assets/{index-D6pBLZFu.js.map → index-BmNAVd4s.js.map} +1 -1
- package/dashboard/dist/assets/{index-CjenRVX_.js → index-Bq5XNEzD.js} +2 -2
- package/dashboard/dist/assets/{index-CjenRVX_.js.map → index-Bq5XNEzD.js.map} +1 -1
- package/dashboard/dist/assets/{index-CzjUgFt_.js → index-DPStdq4T.js} +2 -2
- package/dashboard/dist/assets/{index-CzjUgFt_.js.map → index-DPStdq4T.js.map} +1 -1
- package/dashboard/dist/assets/index-DcppjzP5.css +1 -0
- package/dashboard/dist/assets/{index-C3WutFpT.js → index-DkcI4V_H.js} +2 -2
- package/dashboard/dist/assets/{index-C3WutFpT.js.map → index-DkcI4V_H.js.map} +1 -1
- package/dashboard/dist/assets/{index-2tzsxFat.js → index-Dyotfa_k.js} +2 -2
- package/dashboard/dist/assets/{index-2tzsxFat.js.map → index-Dyotfa_k.js.map} +1 -1
- package/dashboard/dist/assets/{index-C_ISDOWJ.js → index-MDD4JYtu.js} +2 -2
- package/dashboard/dist/assets/{index-C_ISDOWJ.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-BLB77tc8.js → index-eDm6cz0F.js} +2 -2
- package/dashboard/dist/assets/{index-BLB77tc8.js.map → index-eDm6cz0F.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-D1YP2NzS.js → knowledge-Bafewjxk.js} +2 -2
- package/dashboard/dist/assets/{knowledge-D1YP2NzS.js.map → knowledge-Bafewjxk.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-D5jUdZwN.js → mcp-query-BzTtIG90.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-D5jUdZwN.js.map → mcp-query-BzTtIG90.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-Bb5psC61.js → mcp-vLIutbnc.js} +2 -2
- package/dashboard/dist/assets/{mcp-Bb5psC61.js.map → mcp-vLIutbnc.js.map} +1 -1
- package/dashboard/dist/assets/{personas-CDndbkp4.js → personas-WD40EDS_.js} +2 -2
- package/dashboard/dist/assets/{personas-CDndbkp4.js.map → personas-WD40EDS_.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-Dq3kNhKu.js → pipelines-DFwULWs3.js} +2 -2
- package/dashboard/dist/assets/{pipelines-Dq3kNhKu.js.map → pipelines-DFwULWs3.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-BlpDsWCy.js → tasks-La_-WAUn.js} +2 -2
- package/dashboard/dist/assets/{tasks-BlpDsWCy.js.map → tasks-La_-WAUn.js.map} +1 -1
- package/dashboard/dist/assets/{topics-C0YaR9fu.js → topics-CzYMlvqm.js} +2 -2
- package/dashboard/dist/assets/{topics-C0YaR9fu.js.map → topics-CzYMlvqm.js.map} +1 -1
- package/dashboard/dist/assets/{useDebouncedValue-B-KC5ba3.js → useDebouncedValue-C0FQyANW.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-B-KC5ba3.js.map → useDebouncedValue-C0FQyANW.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-Dkr5g2Ac.js → useNamespace-WW_XjAb3.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-Dkr5g2Ac.js.map → useNamespace-WW_XjAb3.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-BANBOshA.js → useYamlActivityEvents-B3YxPeFt.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-BANBOshA.js.map → useYamlActivityEvents-B3YxPeFt.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-BLYoJfmB.js → yaml-workflows-COHOjdhF.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-BLYoJfmB.js.map → yaml-workflows-COHOjdhF.js.map} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/docs/dashboard.md +1 -1
- package/docs/hitl/x-lt-scan.md +51 -0
- package/docs/hitl-guide.md +2 -0
- package/docs/scan-codes.md +221 -21
- package/package.json +1 -1
- package/build/types/scan-code.d.ts +0 -317
- package/dashboard/dist/assets/CapabilitiesPage-BxadotXn.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-CI_JOAvk.js +0 -2
- package/dashboard/dist/assets/ResolverForm-BVG8X0sS.js +0 -8
- package/dashboard/dist/assets/ResolverForm-BVG8X0sS.js.map +0 -1
- package/dashboard/dist/assets/RoleDetailPage-KCXDqoJz.js +0 -8
- package/dashboard/dist/assets/RoleDetailPage-KCXDqoJz.js.map +0 -1
- package/dashboard/dist/assets/ScanCodesPage-CUhCz-Yr.js +0 -2
- package/dashboard/dist/assets/ScanCodesPage-CUhCz-Yr.js.map +0 -1
- package/dashboard/dist/assets/ScanSchemeDetailPage-qzXKNqJK.js +0 -2
- package/dashboard/dist/assets/ScanSchemeDetailPage-qzXKNqJK.js.map +0 -1
- package/dashboard/dist/assets/ScanStationPage-D8e8cG3t.js +0 -2
- package/dashboard/dist/assets/ScanStationPage-D8e8cG3t.js.map +0 -1
- package/dashboard/dist/assets/index-CT-FN6CW.js +0 -3
- package/dashboard/dist/assets/index-CT-FN6CW.js.map +0 -1
- package/dashboard/dist/assets/index-Dh8MJl3L.css +0 -1
- package/dashboard/dist/assets/index-N71QQ3J5.js +0 -67
- package/dashboard/dist/assets/index-N71QQ3J5.js.map +0 -1
package/build/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export * as TaskService from './services/task';
|
|
|
12
12
|
export * as EscalationService from './services/escalation';
|
|
13
13
|
export * as ConfigService from './services/config';
|
|
14
14
|
export * as UserService from './services/user';
|
|
15
|
+
export { assertValidScheme as assertValidScanScheme, assertValidSteps as assertValidScanSteps, assertValidIdentityRule as assertValidScanIdentityRule, isValidGtin, normalizeGtin, type ScanSchemeInput, type ScanRuleInput, } from './services/scan-code';
|
|
15
16
|
export * as TopicService from './services/topics';
|
|
16
17
|
export { seedSystemTopics, seedConfigTopics } from './services/topics/system-topics';
|
|
17
18
|
export { ltConfig } from './modules/ltconfig';
|
package/build/index.js
CHANGED
|
@@ -36,8 +36,8 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
36
36
|
};
|
|
37
37
|
})();
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.
|
|
40
|
-
exports.LTExpressAdapter = exports.api = exports.KnowledgeApi = exports.resolveCredential = exports.mimeFromPath = exports.getStorageBackend = exports.listOAuthConnections = exports.getFreshAccessToken = exports.createClient = exports.CallbackEventAdapter = exports.builtinMcpServerFactories = exports.getSystemAgents = exports.getSystemWorkers = exports.registerMcpTool = exports.getToolContext = exports.getActivityIdentity = void 0;
|
|
39
|
+
exports.McpServer = exports.McpClient = exports.McpService = exports.BuiltInMcpAdapter = exports.mcpRegistry = exports.defaultMaintenanceConfig = exports.maintenanceRegistry = exports.PinoLoggerAdapter = exports.loggerRegistry = exports.HoneycombTelemetryAdapter = exports.telemetryRegistry = exports.publishKnowledgeEvent = exports.publishAgentEvent = exports.publishWorkflowEvent = exports.publishActivityEvent = exports.publishEscalationEvent = exports.publishTaskEvent = exports.publishMilestoneEvent = exports.SocketIOEventAdapter = exports.InMemoryEventAdapter = exports.NatsEventAdapter = exports.eventRegistry = exports.ltConfig = exports.seedConfigTopics = exports.seedSystemTopics = exports.TopicService = exports.normalizeGtin = exports.isValidGtin = exports.assertValidScanIdentityRule = exports.assertValidScanSteps = exports.assertValidScanScheme = exports.UserService = exports.ConfigService = exports.EscalationService = exports.TaskService = exports.setAuthAdapter = exports.signToken = exports.requireAdmin = exports.requireAuth = exports.createAuthMiddleware = exports.JwtAuthAdapter = exports.conditionalAccumulator = exports.conditionLT = exports.conditional = exports.executeLT = exports.createLTActivityInterceptor = exports.createLTInterceptor = exports.registerLT = exports.midnightTheme = exports.start = void 0;
|
|
40
|
+
exports.LTExpressAdapter = exports.api = exports.KnowledgeApi = exports.resolveCredential = exports.mimeFromPath = exports.getStorageBackend = exports.listOAuthConnections = exports.getFreshAccessToken = exports.createClient = exports.CallbackEventAdapter = exports.builtinMcpServerFactories = exports.getSystemAgents = exports.getSystemWorkers = exports.registerMcpTool = exports.getToolContext = exports.getActivityIdentity = exports.McpEscalationStrategy = exports.DefaultEscalationStrategy = exports.escalationStrategyRegistry = exports.McpVisionServer = exports.McpTranslationServer = void 0;
|
|
41
41
|
const config_1 = require("./modules/config");
|
|
42
42
|
const logger_1 = require("./lib/logger");
|
|
43
43
|
const midnight_1 = require("./themes/midnight");
|
|
@@ -70,6 +70,12 @@ exports.TaskService = __importStar(require("./services/task"));
|
|
|
70
70
|
exports.EscalationService = __importStar(require("./services/escalation"));
|
|
71
71
|
exports.ConfigService = __importStar(require("./services/config"));
|
|
72
72
|
exports.UserService = __importStar(require("./services/user"));
|
|
73
|
+
var scan_code_1 = require("./services/scan-code");
|
|
74
|
+
Object.defineProperty(exports, "assertValidScanScheme", { enumerable: true, get: function () { return scan_code_1.assertValidScheme; } });
|
|
75
|
+
Object.defineProperty(exports, "assertValidScanSteps", { enumerable: true, get: function () { return scan_code_1.assertValidSteps; } });
|
|
76
|
+
Object.defineProperty(exports, "assertValidScanIdentityRule", { enumerable: true, get: function () { return scan_code_1.assertValidIdentityRule; } });
|
|
77
|
+
Object.defineProperty(exports, "isValidGtin", { enumerable: true, get: function () { return scan_code_1.isValidGtin; } });
|
|
78
|
+
Object.defineProperty(exports, "normalizeGtin", { enumerable: true, get: function () { return scan_code_1.normalizeGtin; } });
|
|
73
79
|
exports.TopicService = __importStar(require("./services/topics"));
|
|
74
80
|
var system_topics_1 = require("./services/topics/system-topics");
|
|
75
81
|
Object.defineProperty(exports, "seedSystemTopics", { enumerable: true, get: function () { return system_topics_1.seedSystemTopics; } });
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
-- Migration 037: GTIN scan schemes and subject-bound acting grants
|
|
2
|
+
--
|
|
3
|
+
-- encoding 'gtin': a scheme whose codes are manufacturer barcodes (UPC-A,
|
|
4
|
+
-- EAN-13, EAN-8, GTIN-14). The code carries no scheme or category; the
|
|
5
|
+
-- check digit identifies it, and the scheme's single rule is category '0'.
|
|
6
|
+
--
|
|
7
|
+
-- grant_scope (identity kind only):
|
|
8
|
+
-- 'action' each mutating act spends one use of the grant.
|
|
9
|
+
-- 'subject' the first act binds the grant to the held subject (the item
|
|
10
|
+
-- the station is holding); further acts on that same subject do
|
|
11
|
+
-- not count, and the grant cannot act on any other subject.
|
|
12
|
+
--
|
|
13
|
+
-- lt_ephemeral_credentials.bind_on_use / bound_ref carry that binding.
|
|
14
|
+
|
|
15
|
+
ALTER TABLE lt_config_scan_schemes
|
|
16
|
+
DROP CONSTRAINT IF EXISTS lt_config_scan_schemes_encoding_check;
|
|
17
|
+
ALTER TABLE lt_config_scan_schemes
|
|
18
|
+
ADD CONSTRAINT lt_config_scan_schemes_encoding_check
|
|
19
|
+
CHECK (encoding IN ('fixed', 'delimited', 'gtin'));
|
|
20
|
+
|
|
21
|
+
ALTER TABLE lt_config_scan_schemes
|
|
22
|
+
ADD COLUMN IF NOT EXISTS grant_scope TEXT NOT NULL DEFAULT 'action'
|
|
23
|
+
CHECK (grant_scope IN ('action', 'subject'));
|
|
24
|
+
|
|
25
|
+
ALTER TABLE lt_ephemeral_credentials
|
|
26
|
+
ADD COLUMN IF NOT EXISTS bind_on_use BOOLEAN NOT NULL DEFAULT FALSE,
|
|
27
|
+
ADD COLUMN IF NOT EXISTS bound_ref TEXT;
|
|
@@ -2,6 +2,11 @@ import type { Request, Response } from 'express';
|
|
|
2
2
|
import type { LTApiAuth } from '../../types/sdk';
|
|
3
3
|
/** The header a shared station device rides its badge grant on. */
|
|
4
4
|
export declare const ACTING_TOKEN_HEADER = "x-lt-acting-token";
|
|
5
|
+
/**
|
|
6
|
+
* Uses the grant has left after this request spent one: a count, or
|
|
7
|
+
* `unbounded` while only the TTL limits it. The client retires its grant on 0.
|
|
8
|
+
*/
|
|
9
|
+
export declare const ACTING_REMAINING_HEADER = "x-lt-acting-remaining";
|
|
5
10
|
/**
|
|
6
11
|
* The effective actor for an escalation WORK verb (claim, release, resolve):
|
|
7
12
|
* the badged person when an acting grant rides the request, otherwise the
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ACTING_TOKEN_HEADER = void 0;
|
|
3
|
+
exports.ACTING_REMAINING_HEADER = exports.ACTING_TOKEN_HEADER = void 0;
|
|
4
4
|
exports.effectiveWorkAuth = effectiveWorkAuth;
|
|
5
5
|
const acting_identity_1 = require("../../services/iam/acting-identity");
|
|
6
6
|
/** The header a shared station device rides its badge grant on. */
|
|
7
7
|
exports.ACTING_TOKEN_HEADER = 'x-lt-acting-token';
|
|
8
|
+
/**
|
|
9
|
+
* Uses the grant has left after this request spent one: a count, or
|
|
10
|
+
* `unbounded` while only the TTL limits it. The client retires its grant on 0.
|
|
11
|
+
*/
|
|
12
|
+
exports.ACTING_REMAINING_HEADER = 'x-lt-acting-remaining';
|
|
8
13
|
/**
|
|
9
14
|
* The effective actor for an escalation WORK verb (claim, release, resolve):
|
|
10
15
|
* the badged person when an acting grant rides the request, otherwise the
|
|
@@ -21,5 +26,7 @@ async function effectiveWorkAuth(req, res) {
|
|
|
21
26
|
res.status(401).json({ error: resolved.error });
|
|
22
27
|
return null;
|
|
23
28
|
}
|
|
29
|
+
const { remaining } = resolved.grant;
|
|
30
|
+
res.setHeader(exports.ACTING_REMAINING_HEADER, remaining === null ? 'unbounded' : String(remaining));
|
|
24
31
|
return resolved.auth;
|
|
25
32
|
}
|
|
@@ -49,6 +49,8 @@ router.post('/execute', async (req, res) => {
|
|
|
49
49
|
code: req.body.code,
|
|
50
50
|
actingToken: req.body.actingToken,
|
|
51
51
|
previousActingToken: req.body.previousActingToken,
|
|
52
|
+
subject: req.body.subject,
|
|
53
|
+
stationRole: req.body.stationRole,
|
|
52
54
|
}, req.auth);
|
|
53
55
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
54
56
|
});
|
|
@@ -102,6 +104,7 @@ router.put('/schemes/:version', auth_1.requireRoleManager, async (req, res) => {
|
|
|
102
104
|
kind: req.body.kind,
|
|
103
105
|
grant_ttl_seconds: req.body.grant_ttl_seconds,
|
|
104
106
|
grant_max_uses: req.body.grant_max_uses,
|
|
107
|
+
grant_scope: req.body.grant_scope,
|
|
105
108
|
enabled: req.body.enabled,
|
|
106
109
|
});
|
|
107
110
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
@@ -1,16 +1,41 @@
|
|
|
1
1
|
import type { LTApiAuth } from '../../types/sdk';
|
|
2
|
+
/** What the client needs to know about a grant after a request touched it. */
|
|
3
|
+
export interface ActingGrantState {
|
|
4
|
+
/** True when this request spent a use. */
|
|
5
|
+
consumed: boolean;
|
|
6
|
+
/** Uses left; null = bounded only by TTL (or bound to one subject). */
|
|
7
|
+
remaining: number | null;
|
|
8
|
+
/** True once the grant is bound to one subject. */
|
|
9
|
+
bound: boolean;
|
|
10
|
+
}
|
|
2
11
|
/** The acting-auth resolution result: an auth to act as, or the loud reason not to. */
|
|
3
12
|
export type ActingAuthResult = {
|
|
4
13
|
ok: true;
|
|
5
14
|
auth: LTApiAuth;
|
|
15
|
+
grant: ActingGrantState;
|
|
6
16
|
} | {
|
|
7
17
|
ok: false;
|
|
8
18
|
error: string;
|
|
9
19
|
};
|
|
20
|
+
export declare const ACTING_ERRORS: {
|
|
21
|
+
readonly NOT_A_GRANT: "actingToken is not an acting-identity grant";
|
|
22
|
+
readonly EXPIRED: "acting identity expired — scan your badge again";
|
|
23
|
+
readonly INACTIVE: "acting identity is no longer an active user";
|
|
24
|
+
readonly OTHER_SUBJECT: "this badge already acted on another item; scan your badge again";
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Read a supplied acting grant without spending it. A token that fails
|
|
28
|
+
* (wrong label, expired, exhausted, or a vanished user) is a terminal error,
|
|
29
|
+
* never a silent fall-back to the session identity: that would misattribute
|
|
30
|
+
* whatever follows.
|
|
31
|
+
*/
|
|
32
|
+
export declare function peekActingAuth(actingToken: string): Promise<ActingAuthResult>;
|
|
10
33
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* terminal error, never a silent fall-back to the session identity: that
|
|
14
|
-
* would misattribute whatever follows.
|
|
34
|
+
* Spend one use of the grant for an act. `ref` names the subject the act
|
|
35
|
+
* lands on; a subject-scoped grant binds to it on first spend.
|
|
15
36
|
*/
|
|
37
|
+
export declare function consumeActingGrant(actingToken: string, ref?: string | null): Promise<ActingAuthResult>;
|
|
38
|
+
/** Return a use whose act missed. `unbind` when that spend bound the grant. */
|
|
39
|
+
export declare function refundActingGrant(actingToken: string, unbind: boolean): Promise<void>;
|
|
40
|
+
/** Spend the grant up front: the escalation work routes always act. */
|
|
16
41
|
export declare function resolveActingAuth(actingToken: string): Promise<ActingAuthResult>;
|
|
@@ -33,28 +33,71 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ACTING_ERRORS = void 0;
|
|
37
|
+
exports.peekActingAuth = peekActingAuth;
|
|
38
|
+
exports.consumeActingGrant = consumeActingGrant;
|
|
39
|
+
exports.refundActingGrant = refundActingGrant;
|
|
36
40
|
exports.resolveActingAuth = resolveActingAuth;
|
|
37
41
|
const userService = __importStar(require("../user"));
|
|
38
42
|
const ephemeral_1 = require("./ephemeral");
|
|
39
43
|
const types_1 = require("../../types");
|
|
44
|
+
exports.ACTING_ERRORS = {
|
|
45
|
+
NOT_A_GRANT: 'actingToken is not an acting-identity grant',
|
|
46
|
+
EXPIRED: 'acting identity expired — scan your badge again',
|
|
47
|
+
INACTIVE: 'acting identity is no longer an active user',
|
|
48
|
+
OTHER_SUBJECT: 'this badge already acted on another item; scan your badge again',
|
|
49
|
+
};
|
|
50
|
+
function isActingGrant(actingToken) {
|
|
51
|
+
const parsed = (0, ephemeral_1.parseEphemeralToken)(actingToken);
|
|
52
|
+
return parsed && parsed.label === types_1.ACTING_IDENTITY_LABEL ? parsed.uuid : null;
|
|
53
|
+
}
|
|
54
|
+
async function toAuth(grant, consumed) {
|
|
55
|
+
const user = await userService.getUser(grant.value);
|
|
56
|
+
if (!user || user.status !== 'active')
|
|
57
|
+
return { ok: false, error: exports.ACTING_ERRORS.INACTIVE };
|
|
58
|
+
return {
|
|
59
|
+
ok: true,
|
|
60
|
+
auth: { userId: user.id },
|
|
61
|
+
grant: { consumed, remaining: grant.remaining, bound: grant.bound },
|
|
62
|
+
};
|
|
63
|
+
}
|
|
40
64
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
65
|
+
* Read a supplied acting grant without spending it. A token that fails
|
|
66
|
+
* (wrong label, expired, exhausted, or a vanished user) is a terminal error,
|
|
67
|
+
* never a silent fall-back to the session identity: that would misattribute
|
|
68
|
+
* whatever follows.
|
|
45
69
|
*/
|
|
46
|
-
async function
|
|
47
|
-
const
|
|
48
|
-
if (!
|
|
49
|
-
return { ok: false, error:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
70
|
+
async function peekActingAuth(actingToken) {
|
|
71
|
+
const uuid = isActingGrant(actingToken);
|
|
72
|
+
if (!uuid)
|
|
73
|
+
return { ok: false, error: exports.ACTING_ERRORS.NOT_A_GRANT };
|
|
74
|
+
const grant = await (0, ephemeral_1.peekEphemeral)(uuid);
|
|
75
|
+
if (!grant)
|
|
76
|
+
return { ok: false, error: exports.ACTING_ERRORS.EXPIRED };
|
|
77
|
+
return toAuth(grant, false);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Spend one use of the grant for an act. `ref` names the subject the act
|
|
81
|
+
* lands on; a subject-scoped grant binds to it on first spend.
|
|
82
|
+
*/
|
|
83
|
+
async function consumeActingGrant(actingToken, ref = null) {
|
|
84
|
+
const uuid = isActingGrant(actingToken);
|
|
85
|
+
if (!uuid)
|
|
86
|
+
return { ok: false, error: exports.ACTING_ERRORS.NOT_A_GRANT };
|
|
87
|
+
const grant = await (0, ephemeral_1.consumeEphemeral)(uuid, ref);
|
|
88
|
+
if (!grant) {
|
|
89
|
+
const live = ref ? await (0, ephemeral_1.peekEphemeral)(uuid) : null;
|
|
90
|
+
return { ok: false, error: live?.bound ? exports.ACTING_ERRORS.OTHER_SUBJECT : exports.ACTING_ERRORS.EXPIRED };
|
|
58
91
|
}
|
|
59
|
-
return
|
|
92
|
+
return toAuth(grant, true);
|
|
93
|
+
}
|
|
94
|
+
/** Return a use whose act missed. `unbind` when that spend bound the grant. */
|
|
95
|
+
async function refundActingGrant(actingToken, unbind) {
|
|
96
|
+
const uuid = isActingGrant(actingToken);
|
|
97
|
+
if (uuid)
|
|
98
|
+
await (0, ephemeral_1.refundEphemeral)(uuid, unbind);
|
|
99
|
+
}
|
|
100
|
+
/** Spend the grant up front: the escalation work routes always act. */
|
|
101
|
+
async function resolveActingAuth(actingToken) {
|
|
102
|
+
return consumeActingGrant(actingToken);
|
|
60
103
|
}
|
|
@@ -21,6 +21,8 @@ export interface StoreEphemeralOptions {
|
|
|
21
21
|
ttlSeconds?: number;
|
|
22
22
|
/** Human-readable label for debugging. */
|
|
23
23
|
label?: string;
|
|
24
|
+
/** The first ref-carrying spend binds the token to that ref (see consumeEphemeral). */
|
|
25
|
+
bindOnUse?: boolean;
|
|
24
26
|
}
|
|
25
27
|
/**
|
|
26
28
|
* Store a sensitive value. Returns the raw token UUID.
|
|
@@ -40,6 +42,25 @@ export declare function storeEphemeral(value: string, opts?: StoreEphemeralOptio
|
|
|
40
42
|
* - Row is deleted when use_count reaches max_uses (if max_uses > 0)
|
|
41
43
|
*/
|
|
42
44
|
export declare function exchangeEphemeral(token: string): Promise<string | null>;
|
|
45
|
+
/** A live token's value and how many uses it has left (null = unbounded). */
|
|
46
|
+
export interface EphemeralGrant {
|
|
47
|
+
value: string;
|
|
48
|
+
remaining: number | null;
|
|
49
|
+
/** True once the token is bound to a ref; it then acts only on that ref. */
|
|
50
|
+
bound: boolean;
|
|
51
|
+
}
|
|
52
|
+
/** Read a live token without spending a use. */
|
|
53
|
+
export declare function peekEphemeral(token: string): Promise<EphemeralGrant | null>;
|
|
54
|
+
/**
|
|
55
|
+
* Spend one use of a token. A token stored with `bindOnUse` binds to `ref`
|
|
56
|
+
* on its first ref-carrying spend; after that it spends freely on that ref
|
|
57
|
+
* and never on another. Returns null when expired, exhausted, or bound
|
|
58
|
+
* elsewhere. An exhausted row stays until its TTL so a spend whose act
|
|
59
|
+
* missed can be refunded.
|
|
60
|
+
*/
|
|
61
|
+
export declare function consumeEphemeral(token: string, ref?: string | null): Promise<EphemeralGrant | null>;
|
|
62
|
+
/** Undo one spend whose act did not land. `unbind` undoes the binding that spend made. */
|
|
63
|
+
export declare function refundEphemeral(token: string, unbind: boolean): Promise<void>;
|
|
43
64
|
/**
|
|
44
65
|
* Explicitly revoke a token before expiry/exhaustion.
|
|
45
66
|
*/
|
|
@@ -7,6 +7,9 @@ exports.exchangeEphemeralToken = exchangeEphemeralToken;
|
|
|
7
7
|
exports.exchangeTokensInArgs = exchangeTokensInArgs;
|
|
8
8
|
exports.storeEphemeral = storeEphemeral;
|
|
9
9
|
exports.exchangeEphemeral = exchangeEphemeral;
|
|
10
|
+
exports.peekEphemeral = peekEphemeral;
|
|
11
|
+
exports.consumeEphemeral = consumeEphemeral;
|
|
12
|
+
exports.refundEphemeral = refundEphemeral;
|
|
10
13
|
exports.revokeEphemeral = revokeEphemeral;
|
|
11
14
|
exports.cleanupExpired = cleanupExpired;
|
|
12
15
|
const db_1 = require("../../lib/db");
|
|
@@ -81,7 +84,7 @@ async function storeEphemeral(value, opts = {}) {
|
|
|
81
84
|
const expiresAt = opts.ttlSeconds
|
|
82
85
|
? `NOW() + ${opts.ttlSeconds} * INTERVAL '1 second'`
|
|
83
86
|
: 'NULL';
|
|
84
|
-
const { rows } = await pool.query((0, sql_1.INSERT_EPHEMERAL)(expiresAt), [Buffer.from(encrypted, 'base64'), opts.label || null, maxUses]);
|
|
87
|
+
const { rows } = await pool.query((0, sql_1.INSERT_EPHEMERAL)(expiresAt), [Buffer.from(encrypted, 'base64'), opts.label || null, maxUses, opts.bindOnUse ?? false]);
|
|
85
88
|
return rows[0].token;
|
|
86
89
|
}
|
|
87
90
|
/**
|
|
@@ -106,6 +109,34 @@ async function exchangeEphemeral(token) {
|
|
|
106
109
|
}
|
|
107
110
|
return (0, crypto_1.decrypt)(buf.toString('base64'));
|
|
108
111
|
}
|
|
112
|
+
function toGrant(row) {
|
|
113
|
+
const bound = row.bound_ref !== null;
|
|
114
|
+
return {
|
|
115
|
+
value: (0, crypto_1.decrypt)(row.value.toString('base64')),
|
|
116
|
+
remaining: bound || row.max_uses === 0 ? null : Math.max(0, row.max_uses - row.use_count),
|
|
117
|
+
bound,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/** Read a live token without spending a use. */
|
|
121
|
+
async function peekEphemeral(token) {
|
|
122
|
+
const { rows } = await (0, db_1.getPool)().query(sql_1.PEEK_EPHEMERAL, [token]);
|
|
123
|
+
return rows.length ? toGrant(rows[0]) : null;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Spend one use of a token. A token stored with `bindOnUse` binds to `ref`
|
|
127
|
+
* on its first ref-carrying spend; after that it spends freely on that ref
|
|
128
|
+
* and never on another. Returns null when expired, exhausted, or bound
|
|
129
|
+
* elsewhere. An exhausted row stays until its TTL so a spend whose act
|
|
130
|
+
* missed can be refunded.
|
|
131
|
+
*/
|
|
132
|
+
async function consumeEphemeral(token, ref = null) {
|
|
133
|
+
const { rows } = await (0, db_1.getPool)().query(sql_1.CONSUME_EPHEMERAL, [token, ref]);
|
|
134
|
+
return rows.length ? toGrant(rows[0]) : null;
|
|
135
|
+
}
|
|
136
|
+
/** Undo one spend whose act did not land. `unbind` undoes the binding that spend made. */
|
|
137
|
+
async function refundEphemeral(token, unbind) {
|
|
138
|
+
await (0, db_1.getPool)().query(sql_1.REFUND_EPHEMERAL, [token, unbind]);
|
|
139
|
+
}
|
|
109
140
|
/**
|
|
110
141
|
* Explicitly revoke a token before expiry/exhaustion.
|
|
111
142
|
*/
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
/** Build INSERT for ephemeral credentials. expiresExpr is a SQL expression like 'NULL' or "NOW() + N * INTERVAL '1 second'". */
|
|
2
2
|
export declare const INSERT_EPHEMERAL: (expiresExpr: string) => string;
|
|
3
3
|
export declare const EXCHANGE_EPHEMERAL = "\n UPDATE lt_ephemeral_credentials\n SET use_count = use_count + 1\n WHERE token = $1\n AND (expires_at IS NULL OR expires_at > NOW())\n AND (max_uses = 0 OR use_count < max_uses)\n RETURNING value, use_count, max_uses";
|
|
4
|
+
/** Validity check without spending a use. A bound grant stays live until its TTL. */
|
|
5
|
+
export declare const PEEK_EPHEMERAL = "\n SELECT value, use_count, max_uses, bound_ref\n FROM lt_ephemeral_credentials\n WHERE token = $1\n AND (expires_at IS NULL OR expires_at > NOW())\n AND (bound_ref IS NOT NULL OR max_uses = 0 OR use_count < max_uses)";
|
|
6
|
+
/**
|
|
7
|
+
* Spend one use, binding a bind_on_use grant to $2 on its first spend.
|
|
8
|
+
* A bound grant acts again on its own ref without counting, and never on
|
|
9
|
+
* another ref. Without a ref ($2 NULL) the grant counts like any other.
|
|
10
|
+
*/
|
|
11
|
+
export declare const CONSUME_EPHEMERAL = "\n UPDATE lt_ephemeral_credentials\n SET use_count = CASE WHEN bound_ref IS NOT NULL THEN use_count ELSE use_count + 1 END,\n bound_ref = CASE WHEN bind_on_use AND bound_ref IS NULL THEN $2::text ELSE bound_ref END\n WHERE token = $1\n AND (expires_at IS NULL OR expires_at > NOW())\n AND (\n (bound_ref IS NOT NULL AND bound_ref = $2::text)\n OR (bound_ref IS NULL AND (max_uses = 0 OR use_count < max_uses))\n )\n RETURNING value, use_count, max_uses, bound_ref";
|
|
12
|
+
/** Return a use an act spent but did not land; $2 also undoes the binding that spend made. */
|
|
13
|
+
export declare const REFUND_EPHEMERAL = "\n UPDATE lt_ephemeral_credentials\n SET use_count = GREATEST(use_count - 1, 0),\n bound_ref = CASE WHEN $2::boolean THEN NULL ELSE bound_ref END\n WHERE token = $1";
|
|
4
14
|
export declare const DELETE_EPHEMERAL = "\n DELETE FROM lt_ephemeral_credentials WHERE token = $1";
|
|
5
15
|
export declare const CLEANUP_EXPIRED_EPHEMERAL = "\n DELETE FROM lt_ephemeral_credentials\n WHERE expires_at IS NOT NULL AND expires_at < NOW()";
|
|
6
16
|
export declare const LIST_BOTS = "\n SELECT * FROM lt_users\n WHERE account_type = 'bot'\n AND ($3::text IS NULL OR status = $3)\n AND ($4::text IS NULL\n OR display_name ILIKE '%' || $4 || '%'\n OR external_id ILIKE '%' || $4 || '%'\n OR metadata->>'description' ILIKE '%' || $4 || '%')\n ORDER BY created_at DESC\n LIMIT $1 OFFSET $2";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// ─── Ephemeral credentials ──────────────────────────────────────────────────
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.GET_USER_WITH_ROLES_FLEXIBLE = exports.GET_USER_BY_EXTERNAL_ID = exports.SET_ACCOUNT_TYPE_BOT = exports.COUNT_BOTS = exports.LIST_BOTS = exports.CLEANUP_EXPIRED_EPHEMERAL = exports.DELETE_EPHEMERAL = exports.EXCHANGE_EPHEMERAL = exports.INSERT_EPHEMERAL = void 0;
|
|
4
|
+
exports.GET_USER_WITH_ROLES_FLEXIBLE = exports.GET_USER_BY_EXTERNAL_ID = exports.SET_ACCOUNT_TYPE_BOT = exports.COUNT_BOTS = exports.LIST_BOTS = exports.CLEANUP_EXPIRED_EPHEMERAL = exports.DELETE_EPHEMERAL = exports.REFUND_EPHEMERAL = exports.CONSUME_EPHEMERAL = exports.PEEK_EPHEMERAL = exports.EXCHANGE_EPHEMERAL = exports.INSERT_EPHEMERAL = void 0;
|
|
5
5
|
/** Build INSERT for ephemeral credentials. expiresExpr is a SQL expression like 'NULL' or "NOW() + N * INTERVAL '1 second'". */
|
|
6
6
|
const INSERT_EPHEMERAL = (expiresExpr) => `
|
|
7
|
-
INSERT INTO lt_ephemeral_credentials (value, label, max_uses, expires_at)
|
|
8
|
-
VALUES ($1, $2, $3, ${expiresExpr})
|
|
7
|
+
INSERT INTO lt_ephemeral_credentials (value, label, max_uses, bind_on_use, expires_at)
|
|
8
|
+
VALUES ($1, $2, $3, $4, ${expiresExpr})
|
|
9
9
|
RETURNING token`;
|
|
10
10
|
exports.INSERT_EPHEMERAL = INSERT_EPHEMERAL;
|
|
11
11
|
exports.EXCHANGE_EPHEMERAL = `
|
|
@@ -15,6 +15,35 @@ exports.EXCHANGE_EPHEMERAL = `
|
|
|
15
15
|
AND (expires_at IS NULL OR expires_at > NOW())
|
|
16
16
|
AND (max_uses = 0 OR use_count < max_uses)
|
|
17
17
|
RETURNING value, use_count, max_uses`;
|
|
18
|
+
/** Validity check without spending a use. A bound grant stays live until its TTL. */
|
|
19
|
+
exports.PEEK_EPHEMERAL = `
|
|
20
|
+
SELECT value, use_count, max_uses, bound_ref
|
|
21
|
+
FROM lt_ephemeral_credentials
|
|
22
|
+
WHERE token = $1
|
|
23
|
+
AND (expires_at IS NULL OR expires_at > NOW())
|
|
24
|
+
AND (bound_ref IS NOT NULL OR max_uses = 0 OR use_count < max_uses)`;
|
|
25
|
+
/**
|
|
26
|
+
* Spend one use, binding a bind_on_use grant to $2 on its first spend.
|
|
27
|
+
* A bound grant acts again on its own ref without counting, and never on
|
|
28
|
+
* another ref. Without a ref ($2 NULL) the grant counts like any other.
|
|
29
|
+
*/
|
|
30
|
+
exports.CONSUME_EPHEMERAL = `
|
|
31
|
+
UPDATE lt_ephemeral_credentials
|
|
32
|
+
SET use_count = CASE WHEN bound_ref IS NOT NULL THEN use_count ELSE use_count + 1 END,
|
|
33
|
+
bound_ref = CASE WHEN bind_on_use AND bound_ref IS NULL THEN $2::text ELSE bound_ref END
|
|
34
|
+
WHERE token = $1
|
|
35
|
+
AND (expires_at IS NULL OR expires_at > NOW())
|
|
36
|
+
AND (
|
|
37
|
+
(bound_ref IS NOT NULL AND bound_ref = $2::text)
|
|
38
|
+
OR (bound_ref IS NULL AND (max_uses = 0 OR use_count < max_uses))
|
|
39
|
+
)
|
|
40
|
+
RETURNING value, use_count, max_uses, bound_ref`;
|
|
41
|
+
/** Return a use an act spent but did not land; $2 also undoes the binding that spend made. */
|
|
42
|
+
exports.REFUND_EPHEMERAL = `
|
|
43
|
+
UPDATE lt_ephemeral_credentials
|
|
44
|
+
SET use_count = GREATEST(use_count - 1, 0),
|
|
45
|
+
bound_ref = CASE WHEN $2::boolean THEN NULL ELSE bound_ref END
|
|
46
|
+
WHERE token = $1`;
|
|
18
47
|
exports.DELETE_EPHEMERAL = `
|
|
19
48
|
DELETE FROM lt_ephemeral_credentials WHERE token = $1`;
|
|
20
49
|
exports.CLEANUP_EXPIRED_EPHEMERAL = `
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type RoleBadgeGrant } from './types';
|
|
2
|
+
/** The problem with a `properties.badge_grant` value, or null when it is usable (or absent). */
|
|
3
|
+
export declare function badgeGrantError(value: unknown): string | null;
|
|
4
|
+
/** The role's badge policy from its properties bag, or null when it declares none (or an unusable one). */
|
|
5
|
+
export declare function readBadgeGrant(properties: Record<string, unknown> | null | undefined): RoleBadgeGrant | null;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.badgeGrantError = badgeGrantError;
|
|
4
|
+
exports.readBadgeGrant = readBadgeGrant;
|
|
5
|
+
const types_1 = require("./types");
|
|
6
|
+
const SCOPES = ['action', 'subject'];
|
|
7
|
+
/** The problem with a `properties.badge_grant` value, or null when it is usable (or absent). */
|
|
8
|
+
function badgeGrantError(value) {
|
|
9
|
+
if (value === undefined || value === null)
|
|
10
|
+
return null;
|
|
11
|
+
if (typeof value !== 'object' || Array.isArray(value))
|
|
12
|
+
return 'properties.badge_grant must be an object';
|
|
13
|
+
const grant = value;
|
|
14
|
+
const known = new Set(['ttl_seconds', 'max_uses', 'scope']);
|
|
15
|
+
const extra = Object.keys(grant).filter((k) => !known.has(k));
|
|
16
|
+
if (extra.length)
|
|
17
|
+
return `properties.badge_grant has unknown key(s): ${extra.join(', ')}`;
|
|
18
|
+
if (grant.ttl_seconds !== undefined
|
|
19
|
+
&& (!Number.isInteger(grant.ttl_seconds) || grant.ttl_seconds < 1 || grant.ttl_seconds > 86_400)) {
|
|
20
|
+
return 'properties.badge_grant.ttl_seconds must be an integer from 1 to 86400';
|
|
21
|
+
}
|
|
22
|
+
if (grant.max_uses !== undefined && (!Number.isInteger(grant.max_uses) || grant.max_uses < 0)) {
|
|
23
|
+
return 'properties.badge_grant.max_uses must be a non-negative integer';
|
|
24
|
+
}
|
|
25
|
+
if (grant.scope !== undefined && !SCOPES.includes(grant.scope)) {
|
|
26
|
+
return `properties.badge_grant.scope must be one of ${SCOPES.join(', ')}`;
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
/** The role's badge policy from its properties bag, or null when it declares none (or an unusable one). */
|
|
31
|
+
function readBadgeGrant(properties) {
|
|
32
|
+
const value = properties?.[types_1.ROLE_PROPERTY_KEYS.BADGE_GRANT];
|
|
33
|
+
if (value === undefined || value === null || badgeGrantError(value))
|
|
34
|
+
return null;
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
@@ -8,6 +8,8 @@ const db_1 = require("../../lib/db");
|
|
|
8
8
|
const logger_1 = require("../../lib/logger");
|
|
9
9
|
const index_1 = require("./index");
|
|
10
10
|
const sql_1 = require("./sql");
|
|
11
|
+
const badge_grant_1 = require("./badge-grant");
|
|
12
|
+
const types_1 = require("./types");
|
|
11
13
|
/** Recorded on schema snapshots written by the startup apply. */
|
|
12
14
|
exports.STARTUP_CHANGE_SUMMARY = 'startup apply (code)';
|
|
13
15
|
/** Metadata fields shared 1:1 between LTRoleConfig and UpdateRoleInput. */
|
|
@@ -79,6 +81,9 @@ async function listConfiguredRoles() {
|
|
|
79
81
|
* Escalation targets use replace semantics when declared.
|
|
80
82
|
*/
|
|
81
83
|
async function applyRoleConfig(cfg, codeOwned) {
|
|
84
|
+
const grantError = (0, badge_grant_1.badgeGrantError)(cfg.properties?.[types_1.ROLE_PROPERTY_KEYS.BADGE_GRANT]);
|
|
85
|
+
if (grantError)
|
|
86
|
+
throw new Error(`role ${cfg.role}: ${grantError}`);
|
|
82
87
|
const created = await (0, index_1.createRole)(cfg.role);
|
|
83
88
|
const pool = (0, db_1.getPool)();
|
|
84
89
|
const { rows } = await pool.query(sql_1.GET_ROLE_ROW, [cfg.role]);
|
|
@@ -15,6 +15,10 @@ export interface EscalationChain {
|
|
|
15
15
|
* MEMBER of exactly this one role, the dashboard drops the left nav, the
|
|
16
16
|
* role's escalation list becomes home, and navigation is held to the list,
|
|
17
17
|
* the detail page, and the scan screens. Multi-role users get full chrome.
|
|
18
|
+
* - BADGE_GRANT: RoleBadgeGrant — the badge policy at this role's stations.
|
|
19
|
+
* A badge scanned on a device signed in as a member of this role mints
|
|
20
|
+
* its acting grant under this policy instead of the badge scheme's own
|
|
21
|
+
* (see api/scan-codes/badge-policy.ts).
|
|
18
22
|
* - LINK_VARIABLES: RoleLinkVariable[] — metadata facet names members bind
|
|
19
23
|
* per device. Pins may reference `{lt:name}` as a whole facet value
|
|
20
24
|
* (e.g. `facets={"region":"{lt:region}"}`); the dashboard substitutes
|
|
@@ -27,7 +31,17 @@ export declare const ROLE_PROPERTY_KEYS: {
|
|
|
27
31
|
readonly WORKED_BY: "worked_by";
|
|
28
32
|
readonly KIOSK: "kiosk";
|
|
29
33
|
readonly LINK_VARIABLES: "link_variables";
|
|
34
|
+
readonly BADGE_GRANT: "badge_grant";
|
|
30
35
|
};
|
|
36
|
+
/** A station role's badge policy. Absent fields keep the badge scheme's value. */
|
|
37
|
+
export interface RoleBadgeGrant {
|
|
38
|
+
/** How long a badge scan stays primed (1-86400 s). */
|
|
39
|
+
ttl_seconds?: number;
|
|
40
|
+
/** 0 = TTL-bound; n = the grant covers n acts. */
|
|
41
|
+
max_uses?: number;
|
|
42
|
+
/** 'action' spends a use per act; 'subject' binds to one held item. */
|
|
43
|
+
scope?: 'action' | 'subject';
|
|
44
|
+
}
|
|
31
45
|
/**
|
|
32
46
|
* One link-variable declaration inside `properties.link_variables`. `name` is
|
|
33
47
|
* the metadata facet key (facet-key charset); `label` is the human annotation
|
|
@@ -14,6 +14,10 @@ exports.PORTAL_KEY = exports.PORTAL_LIMITS = exports.ROLE_PROPERTY_KEYS = void 0
|
|
|
14
14
|
* MEMBER of exactly this one role, the dashboard drops the left nav, the
|
|
15
15
|
* role's escalation list becomes home, and navigation is held to the list,
|
|
16
16
|
* the detail page, and the scan screens. Multi-role users get full chrome.
|
|
17
|
+
* - BADGE_GRANT: RoleBadgeGrant — the badge policy at this role's stations.
|
|
18
|
+
* A badge scanned on a device signed in as a member of this role mints
|
|
19
|
+
* its acting grant under this policy instead of the badge scheme's own
|
|
20
|
+
* (see api/scan-codes/badge-policy.ts).
|
|
17
21
|
* - LINK_VARIABLES: RoleLinkVariable[] — metadata facet names members bind
|
|
18
22
|
* per device. Pins may reference `{lt:name}` as a whole facet value
|
|
19
23
|
* (e.g. `facets={"region":"{lt:region}"}`); the dashboard substitutes
|
|
@@ -26,6 +30,7 @@ exports.ROLE_PROPERTY_KEYS = {
|
|
|
26
30
|
WORKED_BY: 'worked_by',
|
|
27
31
|
KIOSK: 'kiosk',
|
|
28
32
|
LINK_VARIABLES: 'link_variables',
|
|
33
|
+
BADGE_GRANT: 'badge_grant',
|
|
29
34
|
};
|
|
30
35
|
/** Bounds for a role's portals: how many, and the matrix of each (rows of cells, each cell a pin). */
|
|
31
36
|
exports.PORTAL_LIMITS = {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { listScanSchemes, getScanScheme, listScanRules, getScanRule, } from './read';
|
|
2
2
|
export { upsertScanScheme, deleteScanScheme, upsertScanRule, deleteScanRule, seedScanScheme, seedScanRule, applyScanScheme, applyScanRule, type ScanSchemeInput, type ScanRuleInput, } from './write';
|
|
3
|
-
export { parseScanCode, interpolateScanTemplate, mentionsClaimToken, ScanTemplateError, type ScanParseResult, type ScanParseFailure, type ScanTemplateContext, } from './parse';
|
|
4
|
-
export { assertValidScheme, assertValidSteps } from './validate';
|
|
3
|
+
export { parseScanCode, interpolateScanTemplate, mentionsClaimToken, renderScanCopy, ScanTemplateError, type ScanParseResult, type ScanParseFailure, type ScanTemplateContext, } from './parse';
|
|
4
|
+
export { assertValidScheme, assertValidSteps, assertValidIdentityRule, assertSchemesCoexist, } from './validate';
|
|
5
|
+
export { isValidGtin, normalizeGtin } from '../../shared/scan-code';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.assertValidSteps = exports.assertValidScheme = exports.ScanTemplateError = exports.mentionsClaimToken = exports.interpolateScanTemplate = exports.parseScanCode = exports.applyScanRule = exports.applyScanScheme = exports.seedScanRule = exports.seedScanScheme = exports.deleteScanRule = exports.upsertScanRule = exports.deleteScanScheme = exports.upsertScanScheme = exports.getScanRule = exports.listScanRules = exports.getScanScheme = exports.listScanSchemes = void 0;
|
|
3
|
+
exports.normalizeGtin = exports.isValidGtin = exports.assertSchemesCoexist = exports.assertValidIdentityRule = exports.assertValidSteps = exports.assertValidScheme = exports.ScanTemplateError = exports.renderScanCopy = exports.mentionsClaimToken = exports.interpolateScanTemplate = exports.parseScanCode = exports.applyScanRule = exports.applyScanScheme = exports.seedScanRule = exports.seedScanScheme = exports.deleteScanRule = exports.upsertScanRule = exports.deleteScanScheme = exports.upsertScanScheme = exports.getScanRule = exports.listScanRules = exports.getScanScheme = exports.listScanSchemes = void 0;
|
|
4
4
|
var read_1 = require("./read");
|
|
5
5
|
Object.defineProperty(exports, "listScanSchemes", { enumerable: true, get: function () { return read_1.listScanSchemes; } });
|
|
6
6
|
Object.defineProperty(exports, "getScanScheme", { enumerable: true, get: function () { return read_1.getScanScheme; } });
|
|
@@ -19,7 +19,13 @@ var parse_1 = require("./parse");
|
|
|
19
19
|
Object.defineProperty(exports, "parseScanCode", { enumerable: true, get: function () { return parse_1.parseScanCode; } });
|
|
20
20
|
Object.defineProperty(exports, "interpolateScanTemplate", { enumerable: true, get: function () { return parse_1.interpolateScanTemplate; } });
|
|
21
21
|
Object.defineProperty(exports, "mentionsClaimToken", { enumerable: true, get: function () { return parse_1.mentionsClaimToken; } });
|
|
22
|
+
Object.defineProperty(exports, "renderScanCopy", { enumerable: true, get: function () { return parse_1.renderScanCopy; } });
|
|
22
23
|
Object.defineProperty(exports, "ScanTemplateError", { enumerable: true, get: function () { return parse_1.ScanTemplateError; } });
|
|
23
24
|
var validate_1 = require("./validate");
|
|
24
25
|
Object.defineProperty(exports, "assertValidScheme", { enumerable: true, get: function () { return validate_1.assertValidScheme; } });
|
|
25
26
|
Object.defineProperty(exports, "assertValidSteps", { enumerable: true, get: function () { return validate_1.assertValidSteps; } });
|
|
27
|
+
Object.defineProperty(exports, "assertValidIdentityRule", { enumerable: true, get: function () { return validate_1.assertValidIdentityRule; } });
|
|
28
|
+
Object.defineProperty(exports, "assertSchemesCoexist", { enumerable: true, get: function () { return validate_1.assertSchemesCoexist; } });
|
|
29
|
+
var scan_code_1 = require("../../shared/scan-code");
|
|
30
|
+
Object.defineProperty(exports, "isValidGtin", { enumerable: true, get: function () { return scan_code_1.isValidGtin; } });
|
|
31
|
+
Object.defineProperty(exports, "normalizeGtin", { enumerable: true, get: function () { return scan_code_1.normalizeGtin; } });
|