@hotmeshio/long-tail 0.22.1 → 0.22.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/api/escalations/accumulate.js +38 -19
- package/build/api/escalations/lookups.d.ts +9 -2
- package/build/api/escalations/lookups.js +15 -3
- package/build/api/escalations/metadata.d.ts +2 -0
- package/build/api/escalations/metadata.js +9 -0
- 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/locate.js +4 -0
- package/build/api/scan-codes/present.d.ts +1 -1
- package/build/api/scan-codes/present.js +43 -0
- 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 +151 -0
- package/build/api/scan-codes/verb-fill.d.ts +6 -0
- package/build/api/scan-codes/verb-fill.js +155 -0
- package/build/api/scan-codes/verb-into-subject.d.ts +12 -0
- package/build/api/scan-codes/verb-into-subject.js +157 -0
- package/build/api/scan-codes/verbs-subject.d.ts +33 -0
- package/build/api/scan-codes/verbs-subject.js +247 -0
- package/build/api/scan-codes/verbs.d.ts +11 -29
- package/build/api/scan-codes/verbs.js +51 -131
- package/build/index.d.ts +1 -0
- package/build/index.js +9 -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/sdk/index.d.ts +1 -0
- package/build/services/escalation/claim-asserted.d.ts +10 -0
- package/build/services/escalation/claim-asserted.js +64 -0
- package/build/services/escalation/facets.d.ts +3 -1
- package/build/services/escalation/facets.js +7 -3
- package/build/services/escalation/index.d.ts +1 -0
- package/build/services/escalation/index.js +3 -1
- 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/knowledge/lookup-cache.d.ts +16 -4
- package/build/services/knowledge/lookup-cache.js +53 -20
- package/build/services/knowledge/lookup-refs.d.ts +3 -2
- package/build/services/knowledge/lookup-refs.js +6 -4
- package/build/services/knowledge/sql.d.ts +2 -0
- package/build/services/knowledge/sql.js +9 -1
- package/build/services/mcp/server-tools.js +1 -1
- package/build/services/orchestrator/condition.d.ts +13 -10
- package/build/services/orchestrator/condition.js +8 -6
- 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 +8 -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-facts.d.ts +5 -0
- package/build/services/scan-code/validate-facts.js +24 -0
- package/build/services/scan-code/validate-query.d.ts +8 -0
- package/build/services/scan-code/validate-query.js +36 -0
- package/build/services/scan-code/validate-subject.d.ts +7 -0
- package/build/services/scan-code/validate-subject.js +185 -0
- package/build/services/scan-code/validate.d.ts +7 -0
- package/build/services/scan-code/validate.js +103 -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 +11 -0
- package/build/shared/scan-code/gtin.js +38 -0
- package/build/shared/scan-code/index.d.ts +2 -0
- package/build/shared/scan-code/index.js +11 -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 +939 -28
- package/build/system/mcp-servers/admin/schemas.js +72 -6
- package/build/system/mcp-servers/human-queue-schemas.d.ts +6 -6
- package/build/system/seed/tool-manifests-admin.d.ts +202 -1
- package/build/system/seed/tool-manifests-admin.js +2 -2
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/escalation.d.ts +16 -8
- package/build/types/escalation.js +18 -7
- package/build/types/index.d.ts +4 -4
- package/build/types/index.js +10 -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 +145 -0
- package/build/types/scan-code/response.js +2 -0
- package/build/types/scan-code/rule.d.ts +229 -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-hI5-kKpL.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-BbWve-Ax.js.map → AdminDashboard-hI5-kKpL.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-M-9eTKhP.js → AgentConfigPage-DetU4HZe.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-M-9eTKhP.js.map → AgentConfigPage-DetU4HZe.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-CsakSlx5.js → AgentDetailPage-DrGXo8KQ.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-CsakSlx5.js.map → AgentDetailPage-DrGXo8KQ.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-Cj_cRTT1.js → AgentsPage-D4md5BzM.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-Cj_cRTT1.js.map → AgentsPage-D4md5BzM.js.map} +1 -1
- package/dashboard/dist/assets/{AvailableEscalationsPage-BXJmMBM1.js → AvailableEscalationsPage-B2bS2ZJy.js} +2 -2
- package/dashboard/dist/assets/{AvailableEscalationsPage-BXJmMBM1.js.map → AvailableEscalationsPage-B2bS2ZJy.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-CGB16rYU.js → BotPicker-BXtey255.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-CGB16rYU.js.map → BotPicker-BXtey255.js.map} +1 -1
- package/dashboard/dist/assets/{BulkAssignModal-MjxcU7N1.js → BulkAssignModal-CSL_PeZv.js} +2 -2
- package/dashboard/dist/assets/{BulkAssignModal-MjxcU7N1.js.map → BulkAssignModal-CSL_PeZv.js.map} +1 -1
- package/dashboard/dist/assets/CapabilitiesPage-5scufTHW.js +2 -0
- package/dashboard/dist/assets/{CapabilitiesPage-BxadotXn.js.map → CapabilitiesPage-5scufTHW.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-BBNpP-6h.js → CollapsibleSection-DjjDGxP_.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-BBNpP-6h.js.map → CollapsibleSection-DjjDGxP_.js.map} +1 -1
- package/dashboard/dist/assets/{ConfirmDeleteModal-D_kAbT_D.js → ConfirmDeleteModal-DJSmsHQM.js} +2 -2
- package/dashboard/dist/assets/{ConfirmDeleteModal-D_kAbT_D.js.map → ConfirmDeleteModal-DJSmsHQM.js.map} +1 -1
- package/dashboard/dist/assets/CountdownTimer-C5ZRYPfF.js +2 -0
- package/dashboard/dist/assets/{CountdownTimer-CI_JOAvk.js.map → CountdownTimer-C5ZRYPfF.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-C9OA1Q2J.js → CredentialsPage-CV6e60yC.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-C9OA1Q2J.js.map → CredentialsPage-CV6e60yC.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-sxLLBf2I.js → CronLabel-CnqhqW0B.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-sxLLBf2I.js.map → CronLabel-CnqhqW0B.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-jH9m8Dgl.js → ElapsedCell-C1IOn-tj.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-jH9m8Dgl.js.map → ElapsedCell-C1IOn-tj.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-Dl3Nr2kk.js → EntityTimelinePanel-Dz6Liig4.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-Dl3Nr2kk.js.map → EntityTimelinePanel-Dz6Liig4.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-DAK6It5J.js → EscalationListSchemaPage-bgdmLmrh.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-DAK6It5J.js.map → EscalationListSchemaPage-bgdmLmrh.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListView-CAHbdxKR.js → EscalationListView-CrlD3ZGt.js} +2 -2
- package/dashboard/dist/assets/{EscalationListView-CAHbdxKR.js.map → EscalationListView-CrlD3ZGt.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-DotfAMCL.js → EscalationSchemaPage-dxXO_T3t.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-DotfAMCL.js.map → EscalationSchemaPage-dxXO_T3t.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTimeline-DqmFydnU.js → EscalationTimeline-C3WQZQuM.js} +2 -2
- package/dashboard/dist/assets/{EscalationTimeline-DqmFydnU.js.map → EscalationTimeline-C3WQZQuM.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTitleSelect-BpRquguO.js → EscalationTitleSelect-CTtcETUO.js} +2 -2
- package/dashboard/dist/assets/{EscalationTitleSelect-BpRquguO.js.map → EscalationTitleSelect-CTtcETUO.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-DtGOqnP4.js → EscalationsOverview-DAjZ7JY2.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-DtGOqnP4.js.map → EscalationsOverview-DAjZ7JY2.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-DSHqKyX2.js → EventTable-B72DQP_v.js} +2 -2
- package/dashboard/dist/assets/{EventTable-DSHqKyX2.js.map → EventTable-B72DQP_v.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-Dxd0wNSW.js → FilterBar-CCTaA_LH.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-Dxd0wNSW.js.map → FilterBar-CCTaA_LH.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-CAsCgFo3.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-ChqqGkro.js.map → GraphInvokePage-CAsCgFo3.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-ByKesG8w.js → HomePage-DseE_iSr.js} +2 -2
- package/dashboard/dist/assets/{HomePage-ByKesG8w.js.map → HomePage-DseE_iSr.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-Ddz_S2av.js → ListToolbar-1zdqnjW6.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-Ddz_S2av.js.map → ListToolbar-1zdqnjW6.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-CVe13tEv.js → McpOverview-DS_JXDW5.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-CVe13tEv.js.map → McpOverview-DS_JXDW5.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-BQYF2Mjq.js → McpQueryDetailPage-BeMUGcv3.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-BQYF2Mjq.js.map → McpQueryDetailPage-BeMUGcv3.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-DZi5lm7s.js → McpQueryPage-CeiLO_LR.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-DZi5lm7s.js.map → McpQueryPage-CeiLO_LR.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-DreARTE1.js → McpRunDetailPage-DYp1uZK2.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-DreARTE1.js.map → McpRunDetailPage-DYp1uZK2.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-DmO0YVhT.js → McpRunsPage-VeaDzcL4.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-DmO0YVhT.js.map → McpRunsPage-VeaDzcL4.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-DpjCO85T.js → OperationsPage-DK2mgaXf.js} +2 -2
- package/dashboard/dist/assets/{OperationsPage-DpjCO85T.js.map → OperationsPage-DK2mgaXf.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-Vv_MEBkv.js → OperatorDashboard-BNjLF0f7.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-Vv_MEBkv.js.map → OperatorDashboard-BNjLF0f7.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-CW-2uBHY.js → PersonaDetailPage-IQ2fZLa6.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-CW-2uBHY.js.map → PersonaDetailPage-IQ2fZLa6.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-CO6yYQdm.js → PersonasPage-DpGFEcU-.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-CO6yYQdm.js.map → PersonasPage-DpGFEcU-.js.map} +1 -1
- package/dashboard/dist/assets/{PortalPage-DcNqhBlg.js → PortalPage-D07xyvG_.js} +2 -2
- package/dashboard/dist/assets/{PortalPage-DcNqhBlg.js.map → PortalPage-D07xyvG_.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-BuipGZcC.js → ProcessDetailPage-t8EEYSMk.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-BuipGZcC.js.map → ProcessDetailPage-t8EEYSMk.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-D9DYntvl.js → ProcessesListPage-BDUXLFdb.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-D9DYntvl.js.map → ProcessesListPage-BDUXLFdb.js.map} +1 -1
- package/dashboard/dist/assets/ResolverForm-BwWOYv_Z.js +8 -0
- package/dashboard/dist/assets/ResolverForm-BwWOYv_Z.js.map +1 -0
- package/dashboard/dist/assets/RoleDetailPage-zMF3x2xi.js +8 -0
- package/dashboard/dist/assets/RoleDetailPage-zMF3x2xi.js.map +1 -0
- package/dashboard/dist/assets/{RolesPage-0QJOBSzF.js → RolesPage-CEBp_PpL.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-0QJOBSzF.js.map → RolesPage-CEBp_PpL.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-Dh4lyyRo.js → RunAsSelector-CC_EHN3z.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-Dh4lyyRo.js.map → RunAsSelector-CC_EHN3z.js.map} +1 -1
- package/dashboard/dist/assets/ScanCodesPage-DD4uU-jY.js +2 -0
- package/dashboard/dist/assets/ScanCodesPage-DD4uU-jY.js.map +1 -0
- package/dashboard/dist/assets/ScanSchemeDetailPage-CUW8gYFh.js +2 -0
- package/dashboard/dist/assets/ScanSchemeDetailPage-CUW8gYFh.js.map +1 -0
- package/dashboard/dist/assets/ScanStationPage-DpO_ESuf.js +2 -0
- package/dashboard/dist/assets/ScanStationPage-DpO_ESuf.js.map +1 -0
- package/dashboard/dist/assets/{StickyPagination-BSUyf5ja.js → StickyPagination-cNqSDm5f.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-BSUyf5ja.js.map → StickyPagination-cNqSDm5f.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail--tp7l2Sd.js → StreamMessageDetail-C4oZqQdB.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail--tp7l2Sd.js.map → StreamMessageDetail-C4oZqQdB.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-CxBZ2THh.js → SwimlaneTimeline-BjBiV7GT.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-CxBZ2THh.js.map → SwimlaneTimeline-BjBiV7GT.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-BJ1QrmPH.js → TaskDetailPage-pO_AnVS1.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-BJ1QrmPH.js.map → TaskDetailPage-pO_AnVS1.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-5BydGWmt.js → TasksListPage-DKDHlWP7.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-5BydGWmt.js.map → TasksListPage-DKDHlWP7.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-CCnz84Y4.js → TimeAgo-D2qchUuJ.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-CCnz84Y4.js.map → TimeAgo-D2qchUuJ.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-D0ru7Lya.js → TimestampCell-DeswZGGo.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-D0ru7Lya.js.map → TimestampCell-DeswZGGo.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-3Kpofmen.js → ToolTestPanel-DJh7PIUa.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-3Kpofmen.js.map → ToolTestPanel-DJh7PIUa.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-BaBXD_AK.js → TopicDetailPage-CsgDJ4Z4.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-BaBXD_AK.js.map → TopicDetailPage-CsgDJ4Z4.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-Cnm1AAjh.js → TopicsPage-tBRZDVDN.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-Cnm1AAjh.js.map → TopicsPage-tBRZDVDN.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-CXsdPiMZ.js → UserName-B-5JcDck.js} +2 -2
- package/dashboard/dist/assets/{UserName-CXsdPiMZ.js.map → UserName-B-5JcDck.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-zx3AUJFd.js → WorkflowExecutionPage-BPHVnhp6.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-zx3AUJFd.js.map → WorkflowExecutionPage-BPHVnhp6.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-DfAGK1l7.js → WorkflowsDashboard-CxLlfZmY.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-DfAGK1l7.js.map → WorkflowsDashboard-CxLlfZmY.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-QIYvoa13.js → WorkflowsOverview-C4az5rwp.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-QIYvoa13.js.map → WorkflowsOverview-C4az5rwp.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-DGgO3hyB.js → YamlWorkflowDetailPage-BmhlAUFQ.js} +8 -8
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-DGgO3hyB.js.map → YamlWorkflowDetailPage-BmhlAUFQ.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-CEsHm0B9.js → YamlWorkflowsPage-CSbG5o2V.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-CEsHm0B9.js.map → YamlWorkflowsPage-CSbG5o2V.js.map} +1 -1
- package/dashboard/dist/assets/{agents-v_HH3Rji.js → agents-BohEn7vw.js} +2 -2
- package/dashboard/dist/assets/{agents-v_HH3Rji.js.map → agents-BohEn7vw.js.map} +1 -1
- package/dashboard/dist/assets/{bots-bwvWYrXz.js → bots-BG2EO-Wi.js} +2 -2
- package/dashboard/dist/assets/{bots-bwvWYrXz.js.map → bots-BG2EO-Wi.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-D4vaw_nQ.js → capabilities-CeFrBmYX.js} +2 -2
- package/dashboard/dist/assets/{capabilities-D4vaw_nQ.js.map → capabilities-CeFrBmYX.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-CiiZ6LJF.js → controlplane-Dhvt8l8F.js} +2 -2
- package/dashboard/dist/assets/{controlplane-CiiZ6LJF.js.map → controlplane-Dhvt8l8F.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-Dv-MB3eC.js → escalation-columns-BWMNxImp.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-Dv-MB3eC.js.map → escalation-columns-BWMNxImp.js.map} +1 -1
- package/dashboard/dist/assets/{index-CzjUgFt_.js → index-Bd_dgyfJ.js} +2 -2
- package/dashboard/dist/assets/{index-CzjUgFt_.js.map → index-Bd_dgyfJ.js.map} +1 -1
- package/dashboard/dist/assets/{index-IJmtbuLh.js → index-C8VlM2Oe.js} +2 -2
- package/dashboard/dist/assets/{index-IJmtbuLh.js.map → index-C8VlM2Oe.js.map} +1 -1
- package/dashboard/dist/assets/{index-CcuvGdvf.js → index-CiqSVDga.js} +2 -2
- package/dashboard/dist/assets/{index-CcuvGdvf.js.map → index-CiqSVDga.js.map} +1 -1
- package/dashboard/dist/assets/{index-C3WutFpT.js → index-Cl_YXEdp.js} +2 -2
- package/dashboard/dist/assets/{index-C3WutFpT.js.map → index-Cl_YXEdp.js.map} +1 -1
- package/dashboard/dist/assets/index-CtZWpy22.js +2 -0
- package/dashboard/dist/assets/index-CtZWpy22.js.map +1 -0
- package/dashboard/dist/assets/{index-CjenRVX_.js → index-D90D9y0J.js} +2 -2
- package/dashboard/dist/assets/{index-CjenRVX_.js.map → index-D90D9y0J.js.map} +1 -1
- package/dashboard/dist/assets/{index-BLB77tc8.js → index-DABkM7s-.js} +2 -2
- package/dashboard/dist/assets/{index-BLB77tc8.js.map → index-DABkM7s-.js.map} +1 -1
- package/dashboard/dist/assets/index-Dbwu51xm.js +3 -0
- package/dashboard/dist/assets/index-Dbwu51xm.js.map +1 -0
- package/dashboard/dist/assets/{index-2tzsxFat.js → index-Dc3Om6G3.js} +2 -2
- package/dashboard/dist/assets/{index-2tzsxFat.js.map → index-Dc3Om6G3.js.map} +1 -1
- package/dashboard/dist/assets/{index-D2VKBMng.js → index-Dc_zWK23.js} +2 -2
- package/dashboard/dist/assets/{index-D2VKBMng.js.map → index-Dc_zWK23.js.map} +1 -1
- package/dashboard/dist/assets/index-DcppjzP5.css +1 -0
- package/dashboard/dist/assets/{index-C_ISDOWJ.js → index-Y-bdW8vo.js} +2 -2
- package/dashboard/dist/assets/{index-C_ISDOWJ.js.map → index-Y-bdW8vo.js.map} +1 -1
- package/dashboard/dist/assets/{index-C4Lce2ET.js → index-dYKgd06u.js} +3 -3
- package/dashboard/dist/assets/{index-C4Lce2ET.js.map → index-dYKgd06u.js.map} +1 -1
- package/dashboard/dist/assets/index-fUsx_gYx.js +67 -0
- package/dashboard/dist/assets/index-fUsx_gYx.js.map +1 -0
- package/dashboard/dist/assets/{knowledge-D1YP2NzS.js → knowledge-CCcTidNV.js} +2 -2
- package/dashboard/dist/assets/{knowledge-D1YP2NzS.js.map → knowledge-CCcTidNV.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-Bb5psC61.js → mcp-CLA1z7Pg.js} +2 -2
- package/dashboard/dist/assets/{mcp-Bb5psC61.js.map → mcp-CLA1z7Pg.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-D5jUdZwN.js → mcp-query-CWG0WMAs.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-D5jUdZwN.js.map → mcp-query-CWG0WMAs.js.map} +1 -1
- package/dashboard/dist/assets/metadata-display-B7X5hGxG.js +2 -0
- package/dashboard/dist/assets/metadata-display-B7X5hGxG.js.map +1 -0
- package/dashboard/dist/assets/{personas-CDndbkp4.js → personas-8jURIzx6.js} +2 -2
- package/dashboard/dist/assets/{personas-CDndbkp4.js.map → personas-8jURIzx6.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-Dq3kNhKu.js → pipelines-hVVRAXqG.js} +2 -2
- package/dashboard/dist/assets/{pipelines-Dq3kNhKu.js.map → pipelines-hVVRAXqG.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-BlpDsWCy.js → tasks-BE1O57Bf.js} +2 -2
- package/dashboard/dist/assets/{tasks-BlpDsWCy.js.map → tasks-BE1O57Bf.js.map} +1 -1
- package/dashboard/dist/assets/{topics-C0YaR9fu.js → topics-Bg96Wp1r.js} +2 -2
- package/dashboard/dist/assets/{topics-C0YaR9fu.js.map → topics-Bg96Wp1r.js.map} +1 -1
- package/dashboard/dist/assets/{useDebouncedValue-B-KC5ba3.js → useDebouncedValue-DmEveyEy.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-B-KC5ba3.js.map → useDebouncedValue-DmEveyEy.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-Dkr5g2Ac.js → useNamespace-DHgkzIuL.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-Dkr5g2Ac.js.map → useNamespace-DHgkzIuL.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-BANBOshA.js → useYamlActivityEvents-RU0PvU8S.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-BANBOshA.js.map → useYamlActivityEvents-RU0PvU8S.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-BLYoJfmB.js → yaml-workflows-DQWE9ijc.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-BLYoJfmB.js.map → yaml-workflows-DQWE9ijc.js.map} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/docs/dashboard.md +1 -1
- package/docs/hitl/lookups.md +27 -18
- package/docs/hitl/x-lt-scan.md +51 -0
- package/docs/hitl/x-lt-validation.md +1 -1
- package/docs/hitl/x-lt-widget.md +1 -1
- package/docs/hitl-guide.md +3 -1
- package/docs/scan-codes.md +303 -33
- 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-D6pBLZFu.js +0 -2
- package/dashboard/dist/assets/index-D6pBLZFu.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/dashboard/dist/assets/metadata-display-COo3mMCr.js +0 -2
- package/dashboard/dist/assets/metadata-display-COo3mMCr.js.map +0 -1
|
@@ -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 });
|
package/build/sdk/index.d.ts
CHANGED
|
@@ -213,6 +213,7 @@ export declare function createClient(options?: LTClientOptions): {
|
|
|
213
213
|
metadata?: Record<string, any>;
|
|
214
214
|
provisionIfAbsent?: import("../api/escalations/helpers").ProvisionIfAbsent;
|
|
215
215
|
restrictRoles?: string[];
|
|
216
|
+
assertId?: string;
|
|
216
217
|
}, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
|
|
217
218
|
resolveByMetadata: (input: {
|
|
218
219
|
key: string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ClaimResult } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Claims one named row, the same claim `claimByMetadata` makes on the row it
|
|
4
|
+
* picks: pending, the facet still matches, the role is allowed, and no live
|
|
5
|
+
* claim by someone else. One statement; a miss writes nothing.
|
|
6
|
+
* $1=filter $2=assignee $3=minutes $4=roles $5=metadata patch $6=id
|
|
7
|
+
*/
|
|
8
|
+
export declare const CLAIM_ASSERTED = "WITH target AS MATERIALIZED (\n SELECT id, assigned_to AS prior_assigned_to FROM public.hmsh_escalations\n WHERE id = $6\n AND metadata @> $1::jsonb\n AND ($4::text[] IS NULL OR role = ANY($4::text[]))\n AND status = 'pending'\n AND (assigned_to IS NULL OR assigned_until IS NULL OR assigned_until <= NOW() OR assigned_to = $2)\n FOR UPDATE SKIP LOCKED\n)\nUPDATE public.hmsh_escalations e\nSET assigned_to = $2,\n claimed_at = NOW(),\n claim_expires_at = NOW() + ($3 * INTERVAL '1 minute'),\n assigned_until = NOW() + ($3 * INTERVAL '1 minute'),\n metadata = CASE WHEN $5::jsonb IS NOT NULL\n THEN COALESCE(e.metadata, '{}'::jsonb) || $5::jsonb\n ELSE e.metadata END,\n updated_at = NOW()\nFROM target WHERE e.id = target.id\nRETURNING e.*, target.prior_assigned_to\n";
|
|
9
|
+
/** Claim the row `id` when it still carries `key = value`; null when it does not. */
|
|
10
|
+
export declare function claimAssertedByMetadata(id: string, key: string, value: string, userId: string, durationMinutes?: number, metadata?: Record<string, any>, allowedRoles?: string[] | null): Promise<ClaimResult | null>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CLAIM_ASSERTED = void 0;
|
|
4
|
+
exports.claimAssertedByMetadata = claimAssertedByMetadata;
|
|
5
|
+
const db_1 = require("../../lib/db");
|
|
6
|
+
const escalation_wire_1 = require("../../lib/events/escalation-wire");
|
|
7
|
+
const uuid_1 = require("../../lib/uuid");
|
|
8
|
+
const client_1 = require("./client");
|
|
9
|
+
const crud_1 = require("./crud");
|
|
10
|
+
const map_1 = require("./map");
|
|
11
|
+
/**
|
|
12
|
+
* Claims one named row, the same claim `claimByMetadata` makes on the row it
|
|
13
|
+
* picks: pending, the facet still matches, the role is allowed, and no live
|
|
14
|
+
* claim by someone else. One statement; a miss writes nothing.
|
|
15
|
+
* $1=filter $2=assignee $3=minutes $4=roles $5=metadata patch $6=id
|
|
16
|
+
*/
|
|
17
|
+
exports.CLAIM_ASSERTED = `\
|
|
18
|
+
WITH target AS MATERIALIZED (
|
|
19
|
+
SELECT id, assigned_to AS prior_assigned_to FROM public.hmsh_escalations
|
|
20
|
+
WHERE id = $6
|
|
21
|
+
AND metadata @> $1::jsonb
|
|
22
|
+
AND ($4::text[] IS NULL OR role = ANY($4::text[]))
|
|
23
|
+
AND status = 'pending'
|
|
24
|
+
AND (assigned_to IS NULL OR assigned_until IS NULL OR assigned_until <= NOW() OR assigned_to = $2)
|
|
25
|
+
FOR UPDATE SKIP LOCKED
|
|
26
|
+
)
|
|
27
|
+
UPDATE public.hmsh_escalations e
|
|
28
|
+
SET assigned_to = $2,
|
|
29
|
+
claimed_at = NOW(),
|
|
30
|
+
claim_expires_at = NOW() + ($3 * INTERVAL '1 minute'),
|
|
31
|
+
assigned_until = NOW() + ($3 * INTERVAL '1 minute'),
|
|
32
|
+
metadata = CASE WHEN $5::jsonb IS NOT NULL
|
|
33
|
+
THEN COALESCE(e.metadata, '{}'::jsonb) || $5::jsonb
|
|
34
|
+
ELSE e.metadata END,
|
|
35
|
+
updated_at = NOW()
|
|
36
|
+
FROM target WHERE e.id = target.id
|
|
37
|
+
RETURNING e.*, target.prior_assigned_to
|
|
38
|
+
`;
|
|
39
|
+
/** Claim the row `id` when it still carries `key = value`; null when it does not. */
|
|
40
|
+
async function claimAssertedByMetadata(id, key, value, userId, durationMinutes = 30, metadata, allowedRoles) {
|
|
41
|
+
if (!(0, uuid_1.isUuid)(id))
|
|
42
|
+
return null;
|
|
43
|
+
await (0, client_1.ensureEscalationCompatView)();
|
|
44
|
+
const { rows } = await (0, db_1.getPool)().query(exports.CLAIM_ASSERTED, [
|
|
45
|
+
JSON.stringify({ [key]: value }), userId, durationMinutes,
|
|
46
|
+
allowedRoles ?? null, metadata ? JSON.stringify(metadata) : null, id,
|
|
47
|
+
]);
|
|
48
|
+
if (rows.length === 0)
|
|
49
|
+
return null;
|
|
50
|
+
const { prior_assigned_to: prior, ...entry } = rows[0];
|
|
51
|
+
const escalation = (0, map_1.toEscalationRecord)(entry);
|
|
52
|
+
(0, crud_1.publishEscalationChange)({
|
|
53
|
+
type: 'escalation.claimed',
|
|
54
|
+
source: 'service',
|
|
55
|
+
workflowId: escalation.workflow_id || '',
|
|
56
|
+
workflowName: escalation.workflow_type || '',
|
|
57
|
+
taskQueue: escalation.task_queue || '',
|
|
58
|
+
escalationId: escalation.id,
|
|
59
|
+
role: escalation.role,
|
|
60
|
+
status: 'claimed',
|
|
61
|
+
data: (0, escalation_wire_1.escalationEventData)(escalation),
|
|
62
|
+
});
|
|
63
|
+
return { escalation, isExtension: prior === userId };
|
|
64
|
+
}
|
|
@@ -2,7 +2,9 @@ import type { ClaimedGroup, FacetQuery, GroupSummary, LTEscalationRecord } from
|
|
|
2
2
|
/** Ensure the compat view + the origin_id index exist before the first query. */
|
|
3
3
|
export declare function ensureFacetReady(): Promise<void>;
|
|
4
4
|
/** Item-level faceted search — filter/sort over top-level columns and metadata facets. */
|
|
5
|
-
export declare function searchByFacets(query: FacetQuery
|
|
5
|
+
export declare function searchByFacets(query: FacetQuery, opts?: {
|
|
6
|
+
total?: boolean;
|
|
7
|
+
}): Promise<{
|
|
6
8
|
escalations: LTEscalationRecord[];
|
|
7
9
|
total: number;
|
|
8
10
|
}>;
|
|
@@ -45,7 +45,7 @@ function ensureFacetReady() {
|
|
|
45
45
|
}
|
|
46
46
|
// ── Reads ────────────────────────────────────────────────────────────────────
|
|
47
47
|
/** Item-level faceted search — filter/sort over top-level columns and metadata facets. */
|
|
48
|
-
async function searchByFacets(query) {
|
|
48
|
+
async function searchByFacets(query, opts = {}) {
|
|
49
49
|
await ensureFacetReady();
|
|
50
50
|
const pool = (0, db_1.getPool)();
|
|
51
51
|
const params = [];
|
|
@@ -55,9 +55,13 @@ async function searchByFacets(query) {
|
|
|
55
55
|
const offset = query.offset ?? 0;
|
|
56
56
|
const [rows, count] = await Promise.all([
|
|
57
57
|
pool.query(`SELECT * FROM public.lt_escalations WHERE ${where} ORDER BY ${order} LIMIT $${params.length + 1} OFFSET $${params.length + 2}`, [...params, limit, offset]),
|
|
58
|
-
|
|
58
|
+
// A caller that only picks among a few rows skips the count.
|
|
59
|
+
opts.total === false
|
|
60
|
+
? null
|
|
61
|
+
: pool.query(`SELECT count(*)::int AS total FROM public.lt_escalations WHERE ${where}`, params),
|
|
59
62
|
]);
|
|
60
|
-
|
|
63
|
+
const escalations = (0, map_1.toEscalationRecords)(rows.rows);
|
|
64
|
+
return { escalations, total: count ? count.rows[0]?.total ?? 0 : escalations.length };
|
|
61
65
|
}
|
|
62
66
|
/**
|
|
63
67
|
* Order-level view of the pond — what a batched dispatcher reads to page by
|
|
@@ -14,9 +14,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.AnalyticsInputError = exports.resetAnalyticsCaches = exports.resolveEntitySystem = exports.timelineByFacet = exports.aggregateByFacets = exports.claimByFacets = exports.claimGroups = exports.countByFacets = exports.searchGroups = exports.searchByFacets = exports.ensureFacetReady = exports.ensureEscalationCompatView = void 0;
|
|
17
|
+
exports.AnalyticsInputError = exports.resetAnalyticsCaches = exports.resolveEntitySystem = exports.timelineByFacet = exports.aggregateByFacets = exports.claimByFacets = exports.claimGroups = exports.countByFacets = exports.searchGroups = exports.searchByFacets = exports.ensureFacetReady = exports.ensureEscalationCompatView = exports.claimAssertedByMetadata = void 0;
|
|
18
18
|
__exportStar(require("./types"), exports);
|
|
19
19
|
__exportStar(require("./crud"), exports);
|
|
20
|
+
var claim_asserted_1 = require("./claim-asserted");
|
|
21
|
+
Object.defineProperty(exports, "claimAssertedByMetadata", { enumerable: true, get: function () { return claim_asserted_1.claimAssertedByMetadata; } });
|
|
20
22
|
__exportStar(require("./batch"), exports);
|
|
21
23
|
__exportStar(require("./accumulate"), exports);
|
|
22
24
|
__exportStar(require("./bulk"), exports);
|
|
@@ -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 = `
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type EscalationLookupRef } from '../../types/escalation';
|
|
2
2
|
interface KnowledgeSnapshot {
|
|
3
3
|
data: Record<string, unknown>;
|
|
4
4
|
tags: string[];
|
|
@@ -6,24 +6,36 @@ interface KnowledgeSnapshot {
|
|
|
6
6
|
export interface ResolvedLookup {
|
|
7
7
|
domain: string;
|
|
8
8
|
key: string;
|
|
9
|
-
|
|
9
|
+
/** The edition served; null when a current ref found no edition. */
|
|
10
|
+
version: number | null;
|
|
11
|
+
/** The ref follows the newest edition rather than pinning one. */
|
|
12
|
+
current?: true;
|
|
10
13
|
as?: string;
|
|
11
14
|
data: Record<string, unknown> | null;
|
|
12
15
|
missing?: boolean;
|
|
13
16
|
}
|
|
14
17
|
/** The immutable snapshot at (domain, key, version), or null when absent. */
|
|
15
18
|
export declare function getKnowledgeSnapshot(domain: string, key: string, version: number): Promise<KnowledgeSnapshot | null>;
|
|
19
|
+
/**
|
|
20
|
+
* The edition a ref names: its pin, or for a current ref the newest edition
|
|
21
|
+
* (the newest at `asOf` when given, so a closed row reads what was current
|
|
22
|
+
* when it closed). Null when there is none.
|
|
23
|
+
*/
|
|
24
|
+
export declare function resolveRefEdition(ref: EscalationLookupRef, asOf?: string | null): Promise<{
|
|
25
|
+
version: number;
|
|
26
|
+
snapshot: KnowledgeSnapshot;
|
|
27
|
+
} | null>;
|
|
16
28
|
/**
|
|
17
29
|
* Resolve a metadata `lookups` array into the form-context `lookup` domain:
|
|
18
30
|
* { [as ?? key]: data }. Returns null when there is nothing to resolve, so
|
|
19
31
|
* escalations without refs cost zero SQL. Missing snapshots are omitted —
|
|
20
32
|
* interpolated selects then fail closed rather than render the wrong list.
|
|
21
33
|
*/
|
|
22
|
-
export declare function resolveLookupContext(refs: unknown): Promise<Record<string, unknown> | null>;
|
|
34
|
+
export declare function resolveLookupContext(refs: unknown, asOf?: string | null): Promise<Record<string, unknown> | null>;
|
|
23
35
|
/**
|
|
24
36
|
* Full per-ref resolution for the lookups endpoint: every ref answers, with
|
|
25
37
|
* `missing: true` marking a pin that has no snapshot — fail-visible per ref
|
|
26
38
|
* without failing the batch.
|
|
27
39
|
*/
|
|
28
|
-
export declare function resolveLookupRefs(refs: EscalationLookupRef[]): Promise<ResolvedLookup[]>;
|
|
40
|
+
export declare function resolveLookupRefs(refs: EscalationLookupRef[], asOf?: string | null): Promise<ResolvedLookup[]>;
|
|
29
41
|
export {};
|