@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
|
@@ -68,6 +68,15 @@ function isBatch(escalation) {
|
|
|
68
68
|
return Array.isArray(escalation.metadata?.[escalation_1.ESCALATION_BATCH_KEYS.PENDING]);
|
|
69
69
|
}
|
|
70
70
|
const NO_ACCUMULATOR_FOR_FACET = 'No pending accumulator found for this metadata';
|
|
71
|
+
/** The add's item-key error, or null when the key is usable. */
|
|
72
|
+
function itemKeyError(itemKey) {
|
|
73
|
+
if (!itemKey)
|
|
74
|
+
return { status: 400, error: 'itemKey is required' };
|
|
75
|
+
if (typeof itemKey !== 'string' || itemKey.length > escalation_1.ESCALATION_ITEM_KEY_MAX_LENGTH) {
|
|
76
|
+
return { status: 400, error: `itemKey must be a string of at most ${escalation_1.ESCALATION_ITEM_KEY_MAX_LENGTH} characters` };
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
71
80
|
/**
|
|
72
81
|
* The container a facet names: the highest priority pending row that carries
|
|
73
82
|
* the facet AND the accumulator declaration, within the given roles (null =
|
|
@@ -199,18 +208,22 @@ async function gatePayload(escalation, payload, userId) {
|
|
|
199
208
|
async function accumulateItem(input, auth) {
|
|
200
209
|
try {
|
|
201
210
|
const { id, itemKey, metadata } = input;
|
|
202
|
-
|
|
203
|
-
|
|
211
|
+
const keyError = itemKeyError(itemKey);
|
|
212
|
+
if (keyError)
|
|
213
|
+
return keyError;
|
|
204
214
|
const initiator = await resolveActor(input.initiatedBy, auth);
|
|
205
215
|
if ('error' in initiator)
|
|
206
216
|
return initiator.error;
|
|
207
217
|
const escalation = await escalationService.getEscalation(id);
|
|
208
218
|
if (!escalation)
|
|
209
219
|
return { status: 404, error: 'Escalation not found' };
|
|
210
|
-
if (escalation.status === 'cancelled')
|
|
211
|
-
return { status: 409, error: 'Escalation is cancelled' };
|
|
212
|
-
|
|
213
|
-
|
|
220
|
+
if (escalation.status === 'cancelled') {
|
|
221
|
+
return { status: 409, error: 'Escalation is cancelled', data: { error: 'Escalation is cancelled', outcome: 'already-cancelled' } };
|
|
222
|
+
}
|
|
223
|
+
if (escalation.status !== 'pending') {
|
|
224
|
+
const error = 'Escalation not available for accumulation';
|
|
225
|
+
return { status: 409, error, data: { error, outcome: `already-${escalation.status}` } };
|
|
226
|
+
}
|
|
214
227
|
if (!isAccumulator(escalation))
|
|
215
228
|
return { status: 400, error: 'Escalation is not an accumulator' };
|
|
216
229
|
if (await (0, helpers_1.assertReadAccess)(auth.userId, escalation)) {
|
|
@@ -250,8 +263,9 @@ async function accumulateItemBySignalKey(input, auth) {
|
|
|
250
263
|
const { signalKey, itemKey, metadata } = input;
|
|
251
264
|
if (!signalKey)
|
|
252
265
|
return { status: 400, error: 'signalKey is required' };
|
|
253
|
-
|
|
254
|
-
|
|
266
|
+
const keyError = itemKeyError(itemKey);
|
|
267
|
+
if (keyError)
|
|
268
|
+
return keyError;
|
|
255
269
|
const initiator = await resolveActor(input.initiatedBy, auth);
|
|
256
270
|
if ('error' in initiator)
|
|
257
271
|
return initiator.error;
|
|
@@ -301,8 +315,9 @@ async function accumulateItemByMetadata(input, auth) {
|
|
|
301
315
|
const { key, value, itemKey, metadata } = input;
|
|
302
316
|
if (!key || !value)
|
|
303
317
|
return { status: 400, error: 'key and value are required' };
|
|
304
|
-
|
|
305
|
-
|
|
318
|
+
const keyError = itemKeyError(itemKey);
|
|
319
|
+
if (keyError)
|
|
320
|
+
return keyError;
|
|
306
321
|
const initiator = await resolveActor(input.initiatedBy, auth);
|
|
307
322
|
if ('error' in initiator)
|
|
308
323
|
return initiator.error;
|
|
@@ -574,21 +589,21 @@ function accumulateOutcomeResult(result, itemKey, workflowId) {
|
|
|
574
589
|
},
|
|
575
590
|
};
|
|
576
591
|
case 'duplicate-item':
|
|
577
|
-
return { status: 409, error: 'Item already held', data: { error: 'Item already held', itemKey } };
|
|
592
|
+
return { status: 409, error: 'Item already held', data: { error: 'Item already held', itemKey, outcome: 'duplicate-item' } };
|
|
578
593
|
case 'full':
|
|
579
|
-
return { status: 409, error: 'Accumulator is full', data: { error: 'Accumulator is full', itemKey } };
|
|
594
|
+
return { status: 409, error: 'Accumulator is full', data: { error: 'Accumulator is full', itemKey, outcome: 'full' } };
|
|
580
595
|
case 'claimed-by-other':
|
|
581
|
-
return { status: 409, error: 'Escalation is claimed by another user' };
|
|
596
|
+
return { status: 409, error: 'Escalation is claimed by another user', data: { error: 'Escalation is claimed by another user', outcome: 'claimed-by-other' } };
|
|
582
597
|
case 'claim-expired':
|
|
583
|
-
return { status: 409, error: 'Your claim has expired; re-claim this escalation to add to it' };
|
|
598
|
+
return { status: 409, error: 'Your claim has expired; re-claim this escalation to add to it', data: { error: 'Your claim has expired; re-claim this escalation to add to it', outcome: 'claim-expired' } };
|
|
584
599
|
case 'not-found':
|
|
585
|
-
return { status: 404, error: 'Escalation not found' };
|
|
600
|
+
return { status: 404, error: 'Escalation not found', data: { error: 'Escalation not found', outcome: 'not-found' } };
|
|
586
601
|
case 'not-accumulator':
|
|
587
|
-
return { status: 400, error: 'Escalation is not an accumulator' };
|
|
602
|
+
return { status: 400, error: 'Escalation is not an accumulator', data: { error: 'Escalation is not an accumulator', outcome: 'not-accumulator' } };
|
|
588
603
|
case 'reciprocal-not-found':
|
|
589
|
-
return { status: 404, error: 'Reciprocal escalation not found' };
|
|
604
|
+
return { status: 404, error: 'Reciprocal escalation not found', data: { error: 'Reciprocal escalation not found', outcome: 'reciprocal-not-found' } };
|
|
590
605
|
case 'reciprocal-not-accumulator':
|
|
591
|
-
return { status: 400, error: 'Reciprocal escalation is not an accumulator' };
|
|
606
|
+
return { status: 400, error: 'Reciprocal escalation is not an accumulator', data: { error: 'Reciprocal escalation is not an accumulator', outcome: 'reciprocal-not-accumulator' } };
|
|
592
607
|
case 'reciprocal-duplicate':
|
|
593
608
|
return { status: 409, error: 'Reciprocal escalation already holds this container', data: { error: 'Reciprocal escalation already holds this container', outcome: result.outcome } };
|
|
594
609
|
case 'reciprocal-full':
|
|
@@ -596,7 +611,11 @@ function accumulateOutcomeResult(result, itemKey, workflowId) {
|
|
|
596
611
|
case 'reciprocal-terminal':
|
|
597
612
|
return { status: 409, error: 'Reciprocal escalation is no longer pending', data: { error: 'Reciprocal escalation is no longer pending', outcome: result.outcome } };
|
|
598
613
|
default:
|
|
599
|
-
return {
|
|
614
|
+
return {
|
|
615
|
+
status: 409,
|
|
616
|
+
error: 'Escalation not available for accumulation',
|
|
617
|
+
data: { error: 'Escalation not available for accumulation', outcome: result.outcome },
|
|
618
|
+
};
|
|
600
619
|
}
|
|
601
620
|
}
|
|
602
621
|
function removeOutcomeResult(result, itemKey) {
|
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
import { type EscalationLookupRef } from '../../types/escalation';
|
|
2
|
+
import type { LTEscalationRecord } from '../../types';
|
|
2
3
|
import type { LTApiResult, LTApiAuth } from '../../types/sdk';
|
|
3
4
|
/** The refs riding the row's envelope under the reserved key, or []. */
|
|
4
5
|
export declare function readLookupRefs(envelope: string | null | undefined): EscalationLookupRef[];
|
|
6
|
+
/**
|
|
7
|
+
* When a current ref is read: now for a pending row, the moment it closed
|
|
8
|
+
* otherwise, so a closed row shows the edition its work was done against.
|
|
9
|
+
*/
|
|
10
|
+
export declare function lookupAsOf(escalation: Pick<LTEscalationRecord, 'status' | 'resolved_at' | 'updated_at'>): string | null;
|
|
5
11
|
/**
|
|
6
12
|
* Resolve an escalation's versioned knowledge lookups.
|
|
7
13
|
*
|
|
8
14
|
* The refs on `envelope.lookups` ARE the grant: any user who may read the
|
|
9
15
|
* escalation may read exactly the pinned editions it names — nothing else in
|
|
10
16
|
* the knowledge store. Snapshots are immutable, so responses are served from
|
|
11
|
-
* an in-process cache after the first read; a ref
|
|
12
|
-
*
|
|
17
|
+
* an in-process cache after the first read; a current ref reads the newest
|
|
18
|
+
* edition (as of the close, for a closed row). A ref with no edition answers
|
|
19
|
+
* with `missing: true` rather than failing the batch.
|
|
13
20
|
*
|
|
14
21
|
* @param input.id — escalation UUID
|
|
15
22
|
* @param auth — authenticated user context (must hold the escalation's role)
|
|
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.readLookupRefs = readLookupRefs;
|
|
37
|
+
exports.lookupAsOf = lookupAsOf;
|
|
37
38
|
exports.getEscalationLookups = getEscalationLookups;
|
|
38
39
|
const escalationService = __importStar(require("../../services/escalation"));
|
|
39
40
|
const knowledge_1 = require("../../services/knowledge");
|
|
@@ -55,14 +56,25 @@ function readLookupRefs(envelope) {
|
|
|
55
56
|
return [];
|
|
56
57
|
}
|
|
57
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* When a current ref is read: now for a pending row, the moment it closed
|
|
61
|
+
* otherwise, so a closed row shows the edition its work was done against.
|
|
62
|
+
*/
|
|
63
|
+
function lookupAsOf(escalation) {
|
|
64
|
+
if (escalation.status === 'pending')
|
|
65
|
+
return null;
|
|
66
|
+
const closed = escalation.resolved_at ?? escalation.updated_at;
|
|
67
|
+
return closed ? new Date(closed).toISOString() : null;
|
|
68
|
+
}
|
|
58
69
|
/**
|
|
59
70
|
* Resolve an escalation's versioned knowledge lookups.
|
|
60
71
|
*
|
|
61
72
|
* The refs on `envelope.lookups` ARE the grant: any user who may read the
|
|
62
73
|
* escalation may read exactly the pinned editions it names — nothing else in
|
|
63
74
|
* the knowledge store. Snapshots are immutable, so responses are served from
|
|
64
|
-
* an in-process cache after the first read; a ref
|
|
65
|
-
*
|
|
75
|
+
* an in-process cache after the first read; a current ref reads the newest
|
|
76
|
+
* edition (as of the close, for a closed row). A ref with no edition answers
|
|
77
|
+
* with `missing: true` rather than failing the batch.
|
|
66
78
|
*
|
|
67
79
|
* @param input.id — escalation UUID
|
|
68
80
|
* @param auth — authenticated user context (must hold the escalation's role)
|
|
@@ -81,7 +93,7 @@ async function getEscalationLookups(input, auth) {
|
|
|
81
93
|
if (refs.length === 0) {
|
|
82
94
|
return { status: 200, data: { lookups: [] } };
|
|
83
95
|
}
|
|
84
|
-
const lookups = await (0, knowledge_1.resolveLookupRefs)(refs);
|
|
96
|
+
const lookups = await (0, knowledge_1.resolveLookupRefs)(refs, lookupAsOf(escalation));
|
|
85
97
|
return { status: 200, data: { lookups } };
|
|
86
98
|
}
|
|
87
99
|
catch (err) {
|
|
@@ -37,6 +37,8 @@ export declare function claimByMetadata(input: {
|
|
|
37
37
|
metadata?: Record<string, any>;
|
|
38
38
|
provisionIfAbsent?: ProvisionIfAbsent;
|
|
39
39
|
restrictRoles?: string[];
|
|
40
|
+
/** Claims only this row, when it still matches every other condition. */
|
|
41
|
+
assertId?: string;
|
|
40
42
|
}, auth: LTApiAuth): Promise<LTApiResult>;
|
|
41
43
|
/**
|
|
42
44
|
* Resolve an escalation by metadata key-value pair.
|
|
@@ -94,6 +94,9 @@ async function claimByMetadata(input, auth) {
|
|
|
94
94
|
if (!input.key || !input.value) {
|
|
95
95
|
return { status: 400, error: 'key and value are required' };
|
|
96
96
|
}
|
|
97
|
+
if (input.assertId !== undefined && !(0, uuid_1.isUuid)(input.assertId)) {
|
|
98
|
+
return { status: 404, error: 'No pending escalation found for this metadata' };
|
|
99
|
+
}
|
|
97
100
|
const resolved = await (0, helpers_1.resolveAssignee)(input.assignee, auth, input.provisionIfAbsent);
|
|
98
101
|
if ('error' in resolved)
|
|
99
102
|
return resolved.error;
|
|
@@ -105,6 +108,12 @@ async function claimByMetadata(input, auth) {
|
|
|
105
108
|
// (expected queues) intersects with the scope inside the same SQL filter.
|
|
106
109
|
const writeScope = await (0, helpers_1.getEscalationWriteScope)(auth.userId);
|
|
107
110
|
const allowedRoles = restrictScopeRoles(writeScope.allRoles, writeScope.global, input.restrictRoles);
|
|
111
|
+
if (input.assertId !== undefined) {
|
|
112
|
+
const asserted = await escalationService.claimAssertedByMetadata(input.assertId, input.key, input.value, claimUserId, input.durationMinutes, input.metadata, allowedRoles);
|
|
113
|
+
if (!asserted)
|
|
114
|
+
return { status: 404, error: 'No pending escalation found for this metadata' };
|
|
115
|
+
return { status: 200, data: asserted };
|
|
116
|
+
}
|
|
108
117
|
const result = await escalationService.claimByMetadata(input.key, input.value, claimUserId, input.durationMinutes, input.metadata, allowedRoles);
|
|
109
118
|
if (!result) {
|
|
110
119
|
// No rows matched. Check if candidates existed (role mismatch vs no match).
|
|
@@ -70,10 +70,13 @@ async function resolveBatchItem(input, auth) {
|
|
|
70
70
|
const escalation = await escalationService.getEscalation(id);
|
|
71
71
|
if (!escalation)
|
|
72
72
|
return { status: 404, error: 'Escalation not found' };
|
|
73
|
-
if (escalation.status === 'cancelled')
|
|
74
|
-
return { status: 409, error: 'Escalation is cancelled' };
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
if (escalation.status === 'cancelled') {
|
|
74
|
+
return { status: 409, error: 'Escalation is cancelled', data: { error: 'Escalation is cancelled', outcome: 'already-cancelled' } };
|
|
75
|
+
}
|
|
76
|
+
if (escalation.status !== 'pending') {
|
|
77
|
+
const error = 'Escalation not available for resolution';
|
|
78
|
+
return { status: 409, error, data: { error, outcome: `already-${escalation.status}` } };
|
|
79
|
+
}
|
|
77
80
|
// Advisory shape gate — cheap, readable rejection. The SDK's guarded
|
|
78
81
|
// statement re-checks and is the atomic arbiter (outcome 'not-batch').
|
|
79
82
|
const pending = escalation.metadata?.[escalation_1.ESCALATION_BATCH_KEYS.PENDING];
|
|
@@ -228,20 +231,24 @@ function batchOutcomeResult(result, itemKey, workflowId) {
|
|
|
228
231
|
return {
|
|
229
232
|
status: 409,
|
|
230
233
|
error: 'Batch item already submitted',
|
|
231
|
-
data: { error: 'Batch item already submitted', itemKey },
|
|
234
|
+
data: { error: 'Batch item already submitted', itemKey, outcome: 'duplicate-item' },
|
|
232
235
|
};
|
|
233
236
|
case 'claimed-by-other':
|
|
234
|
-
return { status: 409, error: 'Escalation is claimed by another user' };
|
|
237
|
+
return { status: 409, error: 'Escalation is claimed by another user', data: { error: 'Escalation is claimed by another user', outcome: 'claimed-by-other' } };
|
|
235
238
|
case 'claim-expired':
|
|
236
|
-
return { status: 409, error: 'Your claim has expired — re-claim this escalation to resolve it' };
|
|
239
|
+
return { status: 409, error: 'Your claim has expired — re-claim this escalation to resolve it', data: { error: 'Your claim has expired — re-claim this escalation to resolve it', outcome: 'claim-expired' } };
|
|
237
240
|
case 'not-found':
|
|
238
|
-
return { status: 404, error: 'Escalation not found' };
|
|
241
|
+
return { status: 404, error: 'Escalation not found', data: { error: 'Escalation not found', outcome: 'not-found' } };
|
|
239
242
|
case 'unknown-item':
|
|
240
|
-
return { status: 400, error: 'itemKey is not in the declared batch' };
|
|
243
|
+
return { status: 400, error: 'itemKey is not in the declared batch', data: { error: 'itemKey is not in the declared batch', outcome: 'unknown-item' } };
|
|
241
244
|
case 'not-batch':
|
|
242
|
-
return { status: 400, error: 'Escalation is not a batch' };
|
|
245
|
+
return { status: 400, error: 'Escalation is not a batch', data: { error: 'Escalation is not a batch', outcome: 'not-batch' } };
|
|
243
246
|
default:
|
|
244
247
|
// already-resolved / already-cancelled / already-expired
|
|
245
|
-
return {
|
|
248
|
+
return {
|
|
249
|
+
status: 409,
|
|
250
|
+
error: 'Escalation not available for resolution',
|
|
251
|
+
data: { error: 'Escalation not available for resolution', outcome: result.outcome },
|
|
252
|
+
};
|
|
246
253
|
}
|
|
247
254
|
}
|
package/build/api/roles.js
CHANGED
|
@@ -49,6 +49,7 @@ exports.listRoleListSchemaVersions = listRoleListSchemaVersions;
|
|
|
49
49
|
exports.deleteRole = deleteRole;
|
|
50
50
|
const roleService = __importStar(require("../services/role"));
|
|
51
51
|
const types_1 = require("../services/role/types");
|
|
52
|
+
const badge_grant_1 = require("../services/role/badge-grant");
|
|
52
53
|
const facet_sql_1 = require("../services/escalation/facet-sql");
|
|
53
54
|
/**
|
|
54
55
|
* List all distinct role names in the system.
|
|
@@ -291,6 +292,9 @@ async function updateRole(input) {
|
|
|
291
292
|
return { status: 400, error: 'default_pins must be [{ label, url, badge? }] with dashboard-relative urls' };
|
|
292
293
|
}
|
|
293
294
|
}
|
|
295
|
+
const grantError = (0, badge_grant_1.badgeGrantError)(input.properties?.[types_1.ROLE_PROPERTY_KEYS.BADGE_GRANT]);
|
|
296
|
+
if (grantError)
|
|
297
|
+
return { status: 400, error: grantError };
|
|
294
298
|
if (input.portals != null && !isPortalList(input.portals)) {
|
|
295
299
|
return {
|
|
296
300
|
status: 400,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ScanGrantScope, type ScanScheme } from '../../types';
|
|
2
|
+
export interface GrantPolicy {
|
|
3
|
+
ttlSeconds: number;
|
|
4
|
+
maxUses: number;
|
|
5
|
+
scope: ScanGrantScope;
|
|
6
|
+
/** The station role whose policy applied; absent when the scheme's did. */
|
|
7
|
+
role?: string;
|
|
8
|
+
}
|
|
9
|
+
/** The policy a badge scanned on this device mints under. */
|
|
10
|
+
export declare function stationGrantPolicy(scheme: ScanScheme, stationUserId: string, stationRole?: string): Promise<GrantPolicy>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.stationGrantPolicy = stationGrantPolicy;
|
|
37
|
+
const roleService = __importStar(require("../../services/role"));
|
|
38
|
+
const userService = __importStar(require("../../services/user"));
|
|
39
|
+
const badge_grant_1 = require("../../services/role/badge-grant");
|
|
40
|
+
const types_1 = require("../../types");
|
|
41
|
+
function schemePolicy(scheme) {
|
|
42
|
+
return {
|
|
43
|
+
ttlSeconds: scheme.grant_ttl_seconds ?? 0,
|
|
44
|
+
maxUses: scheme.grant_max_uses ?? 0,
|
|
45
|
+
scope: scheme.grant_scope ?? types_1.SCAN_GRANT_SCOPES.ACTION,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/** The policy a badge scanned on this device mints under. */
|
|
49
|
+
async function stationGrantPolicy(scheme, stationUserId, stationRole) {
|
|
50
|
+
const fallback = schemePolicy(scheme);
|
|
51
|
+
const user = await userService.getUser(stationUserId);
|
|
52
|
+
const memberRoles = (user?.roles ?? []).map((r) => r.role);
|
|
53
|
+
const candidates = stationRole
|
|
54
|
+
? memberRoles.filter((r) => r === stationRole)
|
|
55
|
+
: memberRoles;
|
|
56
|
+
const declared = [];
|
|
57
|
+
for (const role of candidates) {
|
|
58
|
+
const grant = (0, badge_grant_1.readBadgeGrant)(await roleService.getRoleProperties(role));
|
|
59
|
+
if (grant)
|
|
60
|
+
declared.push({ role, grant });
|
|
61
|
+
}
|
|
62
|
+
const distinct = new Set(declared.map((d) => JSON.stringify(d.grant)));
|
|
63
|
+
if (distinct.size !== 1)
|
|
64
|
+
return fallback;
|
|
65
|
+
const { role, grant } = declared[0];
|
|
66
|
+
return {
|
|
67
|
+
ttlSeconds: grant.ttl_seconds ?? fallback.ttlSeconds,
|
|
68
|
+
maxUses: grant.max_uses ?? fallback.maxUses,
|
|
69
|
+
scope: grant.scope ?? fallback.scope,
|
|
70
|
+
role,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -38,6 +38,7 @@ const scanCodeService = __importStar(require("../../services/scan-code"));
|
|
|
38
38
|
const escalationService = __importStar(require("../../services/escalation"));
|
|
39
39
|
const types_1 = require("../../types");
|
|
40
40
|
const identity_1 = require("./identity");
|
|
41
|
+
const grant_1 = require("./grant");
|
|
41
42
|
const context_1 = require("./context");
|
|
42
43
|
const locate_1 = require("./locate");
|
|
43
44
|
const verbs_1 = require("./verbs");
|
|
@@ -69,19 +70,19 @@ async function executeScanChoice(input, auth) {
|
|
|
69
70
|
data: { outcome: types_1.SCAN_OUTCOMES.UNCONFIGURED, error: 'the presented choice is no longer configured' },
|
|
70
71
|
};
|
|
71
72
|
}
|
|
72
|
-
// 2. The acting grant,
|
|
73
|
+
// 2. The acting grant, read (not spent) before anything reads or writes.
|
|
73
74
|
let effectiveAuth = auth;
|
|
74
|
-
let
|
|
75
|
+
let grant;
|
|
75
76
|
if (input.actingToken) {
|
|
76
|
-
const
|
|
77
|
-
if (!
|
|
77
|
+
const peeked = await (0, grant_1.peekGrant)(input.actingToken);
|
|
78
|
+
if (!peeked.ok) {
|
|
78
79
|
return {
|
|
79
80
|
status: 200,
|
|
80
|
-
data: { outcome: types_1.SCAN_OUTCOMES.NOT_PRIMED, notPrimed: rule.notPrimed, error:
|
|
81
|
+
data: { outcome: types_1.SCAN_OUTCOMES.NOT_PRIMED, notPrimed: rule.notPrimed, replayable: true, error: peeked.error },
|
|
81
82
|
};
|
|
82
83
|
}
|
|
83
|
-
effectiveAuth =
|
|
84
|
-
|
|
84
|
+
effectiveAuth = peeked.auth;
|
|
85
|
+
grant = peeked.grant;
|
|
85
86
|
}
|
|
86
87
|
// 3. The row anchors the target: the scheme's facet on the escalation the
|
|
87
88
|
// screen presented. A missing binding is loud misconfiguration.
|
|
@@ -100,7 +101,8 @@ async function executeScanChoice(input, auth) {
|
|
|
100
101
|
scannedAt: new Date().toISOString(),
|
|
101
102
|
auth: effectiveAuth,
|
|
102
103
|
stationAuth: auth,
|
|
103
|
-
acting,
|
|
104
|
+
acting: !!grant,
|
|
105
|
+
grant,
|
|
104
106
|
};
|
|
105
107
|
// 4. The identity gate, per the choice.
|
|
106
108
|
if (choice.requireActingIdentity && !(await (0, identity_1.actingIdentitySatisfied)(step, ctx))) {
|
|
@@ -116,8 +118,12 @@ async function executeScanChoice(input, auth) {
|
|
|
116
118
|
}
|
|
117
119
|
// 6. Dispatch through the same atomic executors a direct scan uses.
|
|
118
120
|
const synthesized = { query: step.query, verb: choice.verb, params: choice.params };
|
|
119
|
-
const result = await (0, verbs_1.dispatchChoiceVerb)(synthesized, ctx, presented);
|
|
120
|
-
|
|
121
|
+
const result = decorate(await (0, verbs_1.dispatchChoiceVerb)(synthesized, ctx, presented), ctx, input);
|
|
122
|
+
// 7. Settle the badge: refund a spend whose act did not land
|
|
123
|
+
const acting = await (0, grant_1.settleGrant)(ctx, result);
|
|
124
|
+
if (acting && result.data)
|
|
125
|
+
result.data = { ...result.data, acting };
|
|
126
|
+
return result;
|
|
121
127
|
}
|
|
122
128
|
catch (err) {
|
|
123
129
|
return { status: 500, error: err.message };
|
|
@@ -1,11 +1,34 @@
|
|
|
1
1
|
import * as scanCodeService from '../../services/scan-code';
|
|
2
2
|
import { type LTEscalationRecord, type ParsedScanCode, type ScanExecuteResponse, type ScanRule, type ScanScheme, type ScanStep } from '../../types';
|
|
3
3
|
import type { LTApiAuth, LTApiResult } from '../../types/sdk';
|
|
4
|
+
/** The held subject, re-derived from the client's pointer on this request. */
|
|
5
|
+
export interface HeldSubject {
|
|
6
|
+
row: LTEscalationRecord;
|
|
7
|
+
parsed: ParsedScanCode;
|
|
8
|
+
scheme: ScanScheme;
|
|
9
|
+
code: string;
|
|
10
|
+
}
|
|
11
|
+
/** The acting grant riding the request, and whether this request spent it. */
|
|
12
|
+
export interface GrantLedger {
|
|
13
|
+
token: string;
|
|
14
|
+
/** Before this request touched it. */
|
|
15
|
+
peeked: {
|
|
16
|
+
remaining: number | null;
|
|
17
|
+
bound: boolean;
|
|
18
|
+
};
|
|
19
|
+
/** Set once this request spends a use; null until then. */
|
|
20
|
+
spent: {
|
|
21
|
+
remaining: number | null;
|
|
22
|
+
bound: boolean;
|
|
23
|
+
} | null;
|
|
24
|
+
}
|
|
4
25
|
/** Everything a step executor needs about the scan that reached it. */
|
|
5
26
|
export interface StepContext {
|
|
6
27
|
scheme: ScanScheme;
|
|
7
28
|
rule: ScanRule;
|
|
8
29
|
parsed: ParsedScanCode;
|
|
30
|
+
/** The code as the station scanned it; absent when a choice re-derived the target. */
|
|
31
|
+
rawCode?: string;
|
|
9
32
|
scannedAt: string;
|
|
10
33
|
/** The effective actor — the acting (badged) user when a grant rode the request. */
|
|
11
34
|
auth: LTApiAuth;
|
|
@@ -13,9 +36,17 @@ export interface StepContext {
|
|
|
13
36
|
stationAuth: LTApiAuth;
|
|
14
37
|
/** True when `auth` came from an acting-identity grant. */
|
|
15
38
|
acting: boolean;
|
|
39
|
+
/** The grant behind `acting`; spent only when an act lands. */
|
|
40
|
+
grant?: GrantLedger;
|
|
41
|
+
/** The subject the station holds, when its pointer still checks out. */
|
|
42
|
+
subject?: HeldSubject;
|
|
43
|
+
/** The station sent a subject pointer that no longer checks out. */
|
|
44
|
+
subjectStale?: boolean;
|
|
16
45
|
}
|
|
17
46
|
export declare function targetFilter(step: ScanStep, ctx: StepContext): Record<string, any>;
|
|
18
47
|
export declare function templateContext(ctx: StepContext): scanCodeService.ScanTemplateContext;
|
|
48
|
+
/** The `{subject.x}` bag: the held row's metadata plus its id. */
|
|
49
|
+
export declare function subjectBag(row: LTEscalationRecord): Record<string, unknown>;
|
|
19
50
|
/**
|
|
20
51
|
* The metadata of the acting user's single live claim, or undefined when
|
|
21
52
|
* they hold none or more than one. One scoped list query, read before the
|
|
@@ -34,4 +65,17 @@ export declare function interpolatedMetadata(step: ScanStep, ctx: StepContext, t
|
|
|
34
65
|
export declare function executed(escalation: LTEscalationRecord | Record<string, any> | undefined, step: Pick<ScanStep, 'verb'>): LTApiResult<ScanExecuteResponse>;
|
|
35
66
|
export declare function forbidden(error?: string): LTApiResult<ScanExecuteResponse>;
|
|
36
67
|
export declare function conflict(error?: string): LTApiResult<ScanExecuteResponse>;
|
|
37
|
-
export declare function notPrimed(ctx: StepContext): LTApiResult<ScanExecuteResponse>;
|
|
68
|
+
export declare function notPrimed(ctx: StepContext, error?: string): LTApiResult<ScanExecuteResponse>;
|
|
69
|
+
/** Nothing was written; say why, and name what the step expected. */
|
|
70
|
+
export declare function refused(markdown: string, extra?: Partial<ScanExecuteResponse>): LTApiResult<ScanExecuteResponse>;
|
|
71
|
+
/**
|
|
72
|
+
* Interpolates a step's params, or falls through when a `{claim.…}` or
|
|
73
|
+
* `{item.…}` token has nothing to read: a literal token never reaches a row.
|
|
74
|
+
*/
|
|
75
|
+
export declare function templated<T>(step: ScanStep, ctx: StepContext, render: (tpl: scanCodeService.ScanTemplateContext) => T, item?: LTEscalationRecord): Promise<T | null>;
|
|
76
|
+
/**
|
|
77
|
+
* Attach the step's `done` copy to a write that landed. `tpl` carries the
|
|
78
|
+
* bags the copy may read (the container a subject step located, a fill's
|
|
79
|
+
* batch); an unreadable token renders empty rather than failing the act.
|
|
80
|
+
*/
|
|
81
|
+
export declare function withDone(result: LTApiResult<ScanExecuteResponse>, step: ScanStep, tpl: scanCodeService.ScanTemplateContext): LTApiResult<ScanExecuteResponse>;
|
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.targetFilter = targetFilter;
|
|
37
37
|
exports.templateContext = templateContext;
|
|
38
|
+
exports.subjectBag = subjectBag;
|
|
38
39
|
exports.liveClaimMetadata = liveClaimMetadata;
|
|
39
40
|
exports.stepTemplate = stepTemplate;
|
|
40
41
|
exports.provenance = provenance;
|
|
@@ -43,6 +44,9 @@ exports.executed = executed;
|
|
|
43
44
|
exports.forbidden = forbidden;
|
|
44
45
|
exports.conflict = conflict;
|
|
45
46
|
exports.notPrimed = notPrimed;
|
|
47
|
+
exports.refused = refused;
|
|
48
|
+
exports.templated = templated;
|
|
49
|
+
exports.withDone = withDone;
|
|
46
50
|
const scanCodeService = __importStar(require("../../services/scan-code"));
|
|
47
51
|
const escalationService = __importStar(require("../../services/escalation"));
|
|
48
52
|
const types_1 = require("../../types");
|
|
@@ -50,7 +54,17 @@ function targetFilter(step, ctx) {
|
|
|
50
54
|
return { [ctx.scheme.target_facet]: ctx.parsed.target, ...(step.query?.facets ?? {}) };
|
|
51
55
|
}
|
|
52
56
|
function templateContext(ctx) {
|
|
53
|
-
return {
|
|
57
|
+
return {
|
|
58
|
+
target: ctx.parsed.target,
|
|
59
|
+
category: ctx.parsed.category,
|
|
60
|
+
scannedAt: ctx.scannedAt,
|
|
61
|
+
code: ctx.parsed.raw ?? ctx.parsed.target,
|
|
62
|
+
...(ctx.subject ? { subject: subjectBag(ctx.subject.row) } : {}),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/** The `{subject.x}` bag: the held row's metadata plus its id. */
|
|
66
|
+
function subjectBag(row) {
|
|
67
|
+
return { ...(row.metadata ?? {}), id: row.id };
|
|
54
68
|
}
|
|
55
69
|
/**
|
|
56
70
|
* The metadata of the acting user's single live claim, or undefined when
|
|
@@ -102,13 +116,47 @@ function forbidden(error) {
|
|
|
102
116
|
function conflict(error) {
|
|
103
117
|
return { status: 200, data: { outcome: types_1.SCAN_OUTCOMES.CONFLICT, error } };
|
|
104
118
|
}
|
|
105
|
-
function notPrimed(ctx) {
|
|
119
|
+
function notPrimed(ctx, error) {
|
|
106
120
|
return {
|
|
107
121
|
status: 200,
|
|
108
122
|
data: {
|
|
109
123
|
outcome: types_1.SCAN_OUTCOMES.NOT_PRIMED,
|
|
110
124
|
notPrimed: ctx.rule.notPrimed,
|
|
111
|
-
|
|
125
|
+
replayable: true,
|
|
126
|
+
error: error ?? 'an acting identity is required — scan your badge',
|
|
112
127
|
},
|
|
113
128
|
};
|
|
114
129
|
}
|
|
130
|
+
/** Nothing was written; say why, and name what the step expected. */
|
|
131
|
+
function refused(markdown, extra = {}) {
|
|
132
|
+
return {
|
|
133
|
+
status: 200,
|
|
134
|
+
data: { outcome: types_1.SCAN_OUTCOMES.REFUSED, refusal: { markdown }, error: markdown, ...extra },
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Interpolates a step's params, or falls through when a `{claim.…}` or
|
|
139
|
+
* `{item.…}` token has nothing to read: a literal token never reaches a row.
|
|
140
|
+
*/
|
|
141
|
+
async function templated(step, ctx, render, item) {
|
|
142
|
+
const tpl = await stepTemplate(step, ctx, item);
|
|
143
|
+
try {
|
|
144
|
+
return render(tpl);
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
if (err instanceof scanCodeService.ScanTemplateError)
|
|
148
|
+
return null;
|
|
149
|
+
throw err;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Attach the step's `done` copy to a write that landed. `tpl` carries the
|
|
154
|
+
* bags the copy may read (the container a subject step located, a fill's
|
|
155
|
+
* batch); an unreadable token renders empty rather than failing the act.
|
|
156
|
+
*/
|
|
157
|
+
function withDone(result, step, tpl) {
|
|
158
|
+
const data = result.data;
|
|
159
|
+
if (!step.done || !data || data.outcome !== types_1.SCAN_OUTCOMES.EXECUTED || data.already || data.done)
|
|
160
|
+
return result;
|
|
161
|
+
return { ...result, data: { ...data, done: { markdown: scanCodeService.renderScanCopy(step.done.markdown, tpl) } } };
|
|
162
|
+
}
|