@hotmeshio/long-tail 0.30.4 → 0.30.5
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/index.d.ts +1 -0
- package/build/api/escalations/index.js +5 -2
- package/build/api/escalations/roster-action.d.ts +11 -0
- package/build/api/escalations/roster-action.js +47 -30
- package/build/api/escalations/roster-scan.d.ts +26 -0
- package/build/api/escalations/roster-scan.js +114 -0
- package/build/api/scan-codes/context.d.ts +9 -1
- package/build/api/scan-codes/context.js +16 -1
- package/build/api/scan-codes/execute.js +6 -1
- package/build/api/scan-codes/fill-labels.d.ts +8 -0
- package/build/api/scan-codes/fill-labels.js +23 -2
- package/build/api/scan-codes/hold.js +2 -0
- package/build/api/scan-codes/located.d.ts +10 -0
- package/build/api/scan-codes/located.js +74 -0
- package/build/api/scan-codes/open.d.ts +9 -0
- package/build/api/scan-codes/open.js +99 -0
- package/build/api/scan-codes/present.js +1 -0
- package/build/api/scan-codes/verb-fill.js +1 -1
- package/build/routes/escalations/resolve.js +18 -0
- package/build/services/role/index.d.ts +2 -0
- package/build/services/role/index.js +7 -0
- package/build/services/role/scan-done.js +4 -1
- package/build/services/role/sql.d.ts +1 -0
- package/build/services/role/sql.js +3 -1
- package/build/services/role/types.d.ts +2 -0
- package/build/services/scan-code/index.d.ts +1 -1
- package/build/services/scan-code/index.js +2 -1
- package/build/services/scan-code/parse.d.ts +5 -1
- package/build/services/scan-code/parse.js +8 -2
- package/build/services/scan-code/validate-station.d.ts +13 -0
- package/build/services/scan-code/validate-station.js +81 -0
- package/build/services/scan-code/validate-subject.js +33 -6
- package/build/services/scan-code/validate.js +12 -18
- package/build/system/mcp-servers/admin/schemas.d.ts +471 -4
- package/build/system/mcp-servers/admin/schemas.js +32 -4
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/index.d.ts +1 -1
- package/build/types/scan-choice.d.ts +2 -4
- package/build/types/scan-code/constants.d.ts +1 -0
- package/build/types/scan-code/constants.js +1 -0
- package/build/types/scan-code/response.d.ts +22 -4
- package/build/types/scan-code/rule.d.ts +61 -3
- package/dashboard/dist/assets/{AdminDashboard-VQ1fhhJP.js → AdminDashboard-D12QiMM5.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-VQ1fhhJP.js.map → AdminDashboard-D12QiMM5.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-BOe_W2Ij.js → AgentConfigPage-BKQd9b8m.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-BOe_W2Ij.js.map → AgentConfigPage-BKQd9b8m.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-5ov5D9V2.js → AgentDetailPage-ie-DxsIj.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-5ov5D9V2.js.map → AgentDetailPage-ie-DxsIj.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-DDFMKHhI.js → AgentsPage-Nqm2DxCP.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-DDFMKHhI.js.map → AgentsPage-Nqm2DxCP.js.map} +1 -1
- package/dashboard/dist/assets/{AvailableEscalationsPage-GFn8Sgg1.js → AvailableEscalationsPage-BRKyG5qZ.js} +2 -2
- package/dashboard/dist/assets/{AvailableEscalationsPage-GFn8Sgg1.js.map → AvailableEscalationsPage-BRKyG5qZ.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-Dqpo36dM.js → BotPicker-BizdmeJp.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-Dqpo36dM.js.map → BotPicker-BizdmeJp.js.map} +1 -1
- package/dashboard/dist/assets/{BulkAssignModal-CmLVxkz-.js → BulkAssignModal-BWfzPrRk.js} +2 -2
- package/dashboard/dist/assets/{BulkAssignModal-CmLVxkz-.js.map → BulkAssignModal-BWfzPrRk.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-Dfkip6_b.js → CapabilitiesPage-DT8q7Zlh.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-Dfkip6_b.js.map → CapabilitiesPage-DT8q7Zlh.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-CYNYMYSa.js → CollapsibleSection-al5mqR4O.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-CYNYMYSa.js.map → CollapsibleSection-al5mqR4O.js.map} +1 -1
- package/dashboard/dist/assets/{ConfirmDeleteModal-CpJNP-8w.js → ConfirmDeleteModal-BrlVktv2.js} +2 -2
- package/dashboard/dist/assets/{ConfirmDeleteModal-CpJNP-8w.js.map → ConfirmDeleteModal-BrlVktv2.js.map} +1 -1
- package/dashboard/dist/assets/{ConnectedAppsPage-DXIp2Dpl.js → ConnectedAppsPage-CLAsJ2yQ.js} +2 -2
- package/dashboard/dist/assets/{ConnectedAppsPage-DXIp2Dpl.js.map → ConnectedAppsPage-CLAsJ2yQ.js.map} +1 -1
- package/dashboard/dist/assets/{CountdownTimer-CuPY7zkb.js → CountdownTimer-D2D68exl.js} +2 -2
- package/dashboard/dist/assets/{CountdownTimer-CuPY7zkb.js.map → CountdownTimer-D2D68exl.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-CtrnkHcj.js → CredentialsPage-DWrZbEI0.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-CtrnkHcj.js.map → CredentialsPage-DWrZbEI0.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-DVjTw5Ri.js → CronLabel-DuXR8iWq.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-DVjTw5Ri.js.map → CronLabel-DuXR8iWq.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-gY_mGMTF.js → ElapsedCell-ronqG5-E.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-gY_mGMTF.js.map → ElapsedCell-ronqG5-E.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-DJN_ZEQa.js → EntityTimelinePanel-CKsktd84.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-DJN_ZEQa.js.map → EntityTimelinePanel-CKsktd84.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-A4KpTdJA.js → EscalationListSchemaPage-C954ngy3.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-A4KpTdJA.js.map → EscalationListSchemaPage-C954ngy3.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-nfCn42hT.js → EscalationSchemaPage-Dij9K0ON.js} +2 -2
- package/dashboard/dist/assets/{EscalationSchemaPage-nfCn42hT.js.map → EscalationSchemaPage-Dij9K0ON.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTimeline-CLvSr1SD.js → EscalationTimeline-DT2Owdl0.js} +2 -2
- package/dashboard/dist/assets/{EscalationTimeline-CLvSr1SD.js.map → EscalationTimeline-DT2Owdl0.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTitleSelect-CT7mYHkb.js → EscalationTitleSelect-BdbfMA98.js} +2 -2
- package/dashboard/dist/assets/{EscalationTitleSelect-CT7mYHkb.js.map → EscalationTitleSelect-BdbfMA98.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-CKaGRh-E.js → EscalationsOverview-niahs84P.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-CKaGRh-E.js.map → EscalationsOverview-niahs84P.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-2ywJsOLy.js → EventTable-DuLMBrSx.js} +2 -2
- package/dashboard/dist/assets/{EventTable-2ywJsOLy.js.map → EventTable-DuLMBrSx.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-Dy0b7wwf.js → FilterBar-jtY6KNpL.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-Dy0b7wwf.js.map → FilterBar-jtY6KNpL.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-yOVpraAy.js → GraphInvokePage-DSRAI0Zt.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-yOVpraAy.js.map → GraphInvokePage-DSRAI0Zt.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-67xXjKjN.js → HomePage-BUlSnCg8.js} +2 -2
- package/dashboard/dist/assets/{HomePage-67xXjKjN.js.map → HomePage-BUlSnCg8.js.map} +1 -1
- package/dashboard/dist/assets/{LinePage-CMsYtukW.js → LinePage-BJKhVM9Y.js} +3 -3
- package/dashboard/dist/assets/{LinePage-CMsYtukW.js.map → LinePage-BJKhVM9Y.js.map} +1 -1
- package/dashboard/dist/assets/{LinesPage-pwL46mOS.js → LinesPage-CrpJua3_.js} +3 -3
- package/dashboard/dist/assets/{LinesPage-pwL46mOS.js.map → LinesPage-CrpJua3_.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-CJmvGy2B.js → ListToolbar-BN0UPt0L.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-CJmvGy2B.js.map → ListToolbar-BN0UPt0L.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-DA9LLvNG.js → McpOverview-BgbJXYPh.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-DA9LLvNG.js.map → McpOverview-BgbJXYPh.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-N7qLmfE8.js → McpQueryDetailPage-BNjm2nrc.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-N7qLmfE8.js.map → McpQueryDetailPage-BNjm2nrc.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-CpsP3w7x.js → McpQueryPage-DplR8wP9.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-CpsP3w7x.js.map → McpQueryPage-DplR8wP9.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-qHRQ1pEY.js → McpRunDetailPage-BHVEcKV5.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-qHRQ1pEY.js.map → McpRunDetailPage-BHVEcKV5.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-BRDDYpTM.js → McpRunsPage-CtlLagcs.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-BRDDYpTM.js.map → McpRunsPage-CtlLagcs.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-zUaab-CL.js → OperationsPage-DH67bcW9.js} +3 -3
- package/dashboard/dist/assets/{OperationsPage-zUaab-CL.js.map → OperationsPage-DH67bcW9.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-el5BquXN.js → OperatorDashboard-CMkgMewd.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-el5BquXN.js.map → OperatorDashboard-CMkgMewd.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-B_tb8gfl.js → PersonaDetailPage-Cs1FFdNq.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-B_tb8gfl.js.map → PersonaDetailPage-Cs1FFdNq.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-BPI7mqM8.js → PersonasPage-CHTRdneF.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-BPI7mqM8.js.map → PersonasPage-CHTRdneF.js.map} +1 -1
- package/dashboard/dist/assets/{PortalPage-e_rBb1do.js → PortalPage-ChB5pBTZ.js} +2 -2
- package/dashboard/dist/assets/{PortalPage-e_rBb1do.js.map → PortalPage-ChB5pBTZ.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-D35RX1bB.js → ProcessDetailPage-CzyqSfal.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-D35RX1bB.js.map → ProcessDetailPage-CzyqSfal.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-CT81miI5.js → ProcessesListPage-rOwNkaU9.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-CT81miI5.js.map → ProcessesListPage-rOwNkaU9.js.map} +1 -1
- package/dashboard/dist/assets/{ResolverForm-BxJkoKAO.js → ResolverForm-DibnlZ-A.js} +2 -2
- package/dashboard/dist/assets/{ResolverForm-BxJkoKAO.js.map → ResolverForm-DibnlZ-A.js.map} +1 -1
- package/dashboard/dist/assets/{RoleDetailPage-DtU7vsJm.js → RoleDetailPage-Bv9R7iQC.js} +3 -3
- package/dashboard/dist/assets/{RoleDetailPage-DtU7vsJm.js.map → RoleDetailPage-Bv9R7iQC.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-BE7RWt9q.js → RolesPage-CUP7EH5U.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-BE7RWt9q.js.map → RolesPage-CUP7EH5U.js.map} +1 -1
- package/dashboard/dist/assets/{RosterWidget-BJMx0a8Z.js → RosterWidget-DZtmQcjU.js} +2 -2
- package/dashboard/dist/assets/RosterWidget-DZtmQcjU.js.map +1 -0
- package/dashboard/dist/assets/{RunAsSelector-Co6s9bqA.js → RunAsSelector-B9-1vgZr.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-Co6s9bqA.js.map → RunAsSelector-B9-1vgZr.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-C2TETaj5.js → ScanCodesPage-KN_e2rJl.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-C2TETaj5.js.map → ScanCodesPage-KN_e2rJl.js.map} +1 -1
- package/dashboard/dist/assets/{ScanSchemeDetailPage-C2UgU8l-.js → ScanSchemeDetailPage-CqItQ67Y.js} +4 -4
- package/dashboard/dist/assets/{ScanSchemeDetailPage-C2UgU8l-.js.map → ScanSchemeDetailPage-CqItQ67Y.js.map} +1 -1
- package/dashboard/dist/assets/ScanStationPage-B0qbUOwc.js +2 -0
- package/dashboard/dist/assets/ScanStationPage-B0qbUOwc.js.map +1 -0
- package/dashboard/dist/assets/{SchemeMatchFields-9H7SmbED.js → SchemeMatchFields-CL7TKnw3.js} +2 -2
- package/dashboard/dist/assets/{SchemeMatchFields-9H7SmbED.js.map → SchemeMatchFields-CL7TKnw3.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-miUdVAKw.js → StickyPagination-CUwxfBQH.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-miUdVAKw.js.map → StickyPagination-CUwxfBQH.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-D5Rk7pn7.js → StreamMessageDetail-DOjcO7d2.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-D5Rk7pn7.js.map → StreamMessageDetail-DOjcO7d2.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-B1QY1ZzH.js → SwimlaneTimeline-SPMpoLHP.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-B1QY1ZzH.js.map → SwimlaneTimeline-SPMpoLHP.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-DKUM37o8.js → TaskDetailPage-DvfzR2IQ.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-DKUM37o8.js.map → TaskDetailPage-DvfzR2IQ.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-CUulwvm-.js → TasksListPage-Jp6wmL7t.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-CUulwvm-.js.map → TasksListPage-Jp6wmL7t.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-CHTelacB.js → TimeAgo-BCQA0Gb_.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-CHTelacB.js.map → TimeAgo-BCQA0Gb_.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-NanLWLKo.js → TimestampCell-xhdMHDQt.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-NanLWLKo.js.map → TimestampCell-xhdMHDQt.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-CF1CHzgz.js → ToolTestPanel-D8M3ITrJ.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-CF1CHzgz.js.map → ToolTestPanel-D8M3ITrJ.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-CGO8XV_a.js → TopicDetailPage-DdBJQp31.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-CGO8XV_a.js.map → TopicDetailPage-DdBJQp31.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-Bt8gOKYr.js → TopicsPage-vpvsynD9.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-Bt8gOKYr.js.map → TopicsPage-vpvsynD9.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-DKXnK7DD.js → UserName-BK6Lzsdw.js} +2 -2
- package/dashboard/dist/assets/{UserName-DKXnK7DD.js.map → UserName-BK6Lzsdw.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-Crf7AIFc.js → WorkflowExecutionPage-DkM1TS4I.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-Crf7AIFc.js.map → WorkflowExecutionPage-DkM1TS4I.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard--isjt06C.js → WorkflowsDashboard-g_N4y3QS.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard--isjt06C.js.map → WorkflowsDashboard-g_N4y3QS.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-D7Oqf4-V.js → WorkflowsOverview-Drjo-Lu-.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-D7Oqf4-V.js.map → WorkflowsOverview-Drjo-Lu-.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-B0wxgrGP.js → YamlWorkflowDetailPage-CLltNHjZ.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-B0wxgrGP.js.map → YamlWorkflowDetailPage-CLltNHjZ.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-BVdLnm6K.js → YamlWorkflowsPage-CxQCB-Zi.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-BVdLnm6K.js.map → YamlWorkflowsPage-CxQCB-Zi.js.map} +1 -1
- package/dashboard/dist/assets/{agents-CHjbjHXA.js → agents-Dk25jjhj.js} +2 -2
- package/dashboard/dist/assets/{agents-CHjbjHXA.js.map → agents-Dk25jjhj.js.map} +1 -1
- package/dashboard/dist/assets/{bots-WrUhEPWs.js → bots-bRkCqhlq.js} +2 -2
- package/dashboard/dist/assets/{bots-WrUhEPWs.js.map → bots-bRkCqhlq.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-CunMmkj8.js → capabilities-DARawLry.js} +2 -2
- package/dashboard/dist/assets/{capabilities-CunMmkj8.js.map → capabilities-DARawLry.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-D6IZIZoh.js → controlplane-DKccxxs6.js} +2 -2
- package/dashboard/dist/assets/{controlplane-D6IZIZoh.js.map → controlplane-DKccxxs6.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-Bvo6JI4Z.js → escalation-columns-BaYuzMYf.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-Bvo6JI4Z.js.map → escalation-columns-BaYuzMYf.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-items-DFGRwo49.js → escalation-items-CwbNFnsH.js} +2 -2
- package/dashboard/dist/assets/{escalation-items-DFGRwo49.js.map → escalation-items-CwbNFnsH.js.map} +1 -1
- package/dashboard/dist/assets/{index-B8qrHwp9.js → index-BZgtzkkG.js} +2 -2
- package/dashboard/dist/assets/{index-B8qrHwp9.js.map → index-BZgtzkkG.js.map} +1 -1
- package/dashboard/dist/assets/{index-DRw0FXdX.js → index-Bx9HVzuT.js} +2 -2
- package/dashboard/dist/assets/{index-DRw0FXdX.js.map → index-Bx9HVzuT.js.map} +1 -1
- package/dashboard/dist/assets/{index-ygxyAKcc.js → index-CU2UW2y6.js} +14 -14
- package/dashboard/dist/assets/index-CU2UW2y6.js.map +1 -0
- package/dashboard/dist/assets/{index-OuKQ_0eB.js → index-Cf6qCgTf.js} +2 -2
- package/dashboard/dist/assets/{index-OuKQ_0eB.js.map → index-Cf6qCgTf.js.map} +1 -1
- package/dashboard/dist/assets/{index-DRK7M1_9.js → index-CtrSYqmL.js} +2 -2
- package/dashboard/dist/assets/{index-DRK7M1_9.js.map → index-CtrSYqmL.js.map} +1 -1
- package/dashboard/dist/assets/{index-Bo8QU31k.js → index-D1uliPqS.js} +2 -2
- package/dashboard/dist/assets/{index-Bo8QU31k.js.map → index-D1uliPqS.js.map} +1 -1
- package/dashboard/dist/assets/{index-B95LbYhW.js → index-DU-1gMks.js} +2 -2
- package/dashboard/dist/assets/{index-B95LbYhW.js.map → index-DU-1gMks.js.map} +1 -1
- package/dashboard/dist/assets/{index-CpCchhQv.js → index-DU2QCbgH.js} +2 -2
- package/dashboard/dist/assets/{index-CpCchhQv.js.map → index-DU2QCbgH.js.map} +1 -1
- package/dashboard/dist/assets/{index-BZFSXEkr.js → index-DgpL_Lgc.js} +2 -2
- package/dashboard/dist/assets/{index-BZFSXEkr.js.map → index-DgpL_Lgc.js.map} +1 -1
- package/dashboard/dist/assets/{index-boT612Jo.js → index-E_hJ7vtX.js} +2 -2
- package/dashboard/dist/assets/{index-boT612Jo.js.map → index-E_hJ7vtX.js.map} +1 -1
- package/dashboard/dist/assets/{index-DCJ483vt.js → index-dShcvdg3.js} +2 -2
- package/dashboard/dist/assets/{index-DCJ483vt.js.map → index-dShcvdg3.js.map} +1 -1
- package/dashboard/dist/assets/{index-C7EIu1mG.js → index-hKOlahpE.js} +2 -2
- package/dashboard/dist/assets/{index-C7EIu1mG.js.map → index-hKOlahpE.js.map} +1 -1
- package/dashboard/dist/assets/index-kzifJWbM.js +3 -0
- package/dashboard/dist/assets/index-kzifJWbM.js.map +1 -0
- package/dashboard/dist/assets/{knowledge-BubJBTwg.js → knowledge-DOe5ks-E.js} +2 -2
- package/dashboard/dist/assets/{knowledge-BubJBTwg.js.map → knowledge-DOe5ks-E.js.map} +1 -1
- package/dashboard/dist/assets/{machines-DSm5NFgs.js → machines-Zq_00v7k.js} +2 -2
- package/dashboard/dist/assets/{machines-DSm5NFgs.js.map → machines-Zq_00v7k.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-D6MckqOV.js → mcp-BL8kD0oh.js} +2 -2
- package/dashboard/dist/assets/{mcp-D6MckqOV.js.map → mcp-BL8kD0oh.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-VyCdOag6.js → mcp-query-BpokmJWi.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-VyCdOag6.js.map → mcp-query-BpokmJWi.js.map} +1 -1
- package/dashboard/dist/assets/{personas-CyJc10xe.js → personas-BubCnQZ8.js} +2 -2
- package/dashboard/dist/assets/{personas-CyJc10xe.js.map → personas-BubCnQZ8.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-B2inDtx3.js → pipelines--DUoMx7K.js} +2 -2
- package/dashboard/dist/assets/{pipelines-B2inDtx3.js.map → pipelines--DUoMx7K.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-DOP4d3M6.js → tasks-CJXN4OB4.js} +2 -2
- package/dashboard/dist/assets/{tasks-DOP4d3M6.js.map → tasks-CJXN4OB4.js.map} +1 -1
- package/dashboard/dist/assets/{topics-CNOjSWpX.js → topics-CAG08Ruo.js} +2 -2
- package/dashboard/dist/assets/{topics-CNOjSWpX.js.map → topics-CAG08Ruo.js.map} +1 -1
- package/dashboard/dist/assets/{useDebouncedValue-CgO0TGMd.js → useDebouncedValue-DQ2D8cm2.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-CgO0TGMd.js.map → useDebouncedValue-DQ2D8cm2.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-BWHvUKtK.js → useNamespace-DjEVAlJQ.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-BWHvUKtK.js.map → useNamespace-DjEVAlJQ.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-BZQ__ZGD.js → useYamlActivityEvents-etcpfIwo.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-BZQ__ZGD.js.map → useYamlActivityEvents-etcpfIwo.js.map} +1 -1
- package/dashboard/dist/assets/{validate-CAin6WM_.js → validate-YJK_6a7m.js} +2 -2
- package/dashboard/dist/assets/{validate-CAin6WM_.js.map → validate-YJK_6a7m.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-Dyln3od-.js → yaml-workflows-D97Bz6li.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-Dyln3od-.js.map → yaml-workflows-D97Bz6li.js.map} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/docs/api/http/escalations.md +15 -0
- package/docs/dashboard.md +2 -2
- package/docs/hitl/x-lt-roster.md +2 -0
- package/docs/hitl/x-lt-scan.md +12 -0
- package/docs/scan-codes.md +81 -3
- package/package.json +1 -1
- package/dashboard/dist/assets/RosterWidget-BJMx0a8Z.js.map +0 -1
- package/dashboard/dist/assets/ScanStationPage-nWYz-OD3.js +0 -2
- package/dashboard/dist/assets/ScanStationPage-nWYz-OD3.js.map +0 -1
- package/dashboard/dist/assets/index-P-DlgAWj.js +0 -3
- package/dashboard/dist/assets/index-P-DlgAWj.js.map +0 -1
- package/dashboard/dist/assets/index-ygxyAKcc.js.map +0 -1
|
@@ -0,0 +1,99 @@
|
|
|
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.withOpen = withOpen;
|
|
37
|
+
const escalationService = __importStar(require("../../services/escalation"));
|
|
38
|
+
const types_1 = require("../../types");
|
|
39
|
+
const OPEN_LABEL_DEFAULT = 'Open';
|
|
40
|
+
/** The answers the station shows on its own screen: a hold, a refusal, a write's done copy. */
|
|
41
|
+
function screenOf(data) {
|
|
42
|
+
if (data.outcome === types_1.SCAN_OUTCOMES.HELD && data.subject)
|
|
43
|
+
return 'hold';
|
|
44
|
+
if (data.outcome === types_1.SCAN_OUTCOMES.REFUSED)
|
|
45
|
+
return 'screen';
|
|
46
|
+
if (data.outcome === types_1.SCAN_OUTCOMES.EXECUTED
|
|
47
|
+
&& (data.done || data.clearSubject || data.progress || data.already))
|
|
48
|
+
return 'screen';
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Attach the step's Open button to the answer: on the held subject for a
|
|
53
|
+
* hold, so it stays while the row is held, else on the response. A target
|
|
54
|
+
* with no row, or a list facet the row does not carry, offers no button.
|
|
55
|
+
*/
|
|
56
|
+
async function withOpen(result, step, ctx) {
|
|
57
|
+
const data = result.data;
|
|
58
|
+
if (!step.open || !data)
|
|
59
|
+
return result;
|
|
60
|
+
const screen = screenOf(data);
|
|
61
|
+
if (!screen)
|
|
62
|
+
return result;
|
|
63
|
+
const link = await resolveOpen(step.open, ctx, data);
|
|
64
|
+
if (!link)
|
|
65
|
+
return result;
|
|
66
|
+
if (screen === 'hold')
|
|
67
|
+
return { ...result, data: { ...data, subject: { ...data.subject, open: link } } };
|
|
68
|
+
return { ...result, data: { ...data, open: link } };
|
|
69
|
+
}
|
|
70
|
+
async function resolveOpen(open, ctx, data) {
|
|
71
|
+
const row = await targetRow(open, ctx, data);
|
|
72
|
+
if (!row)
|
|
73
|
+
return null;
|
|
74
|
+
const label = open.label ?? OPEN_LABEL_DEFAULT;
|
|
75
|
+
if (!open.list)
|
|
76
|
+
return { label, escalationId: row.id, ...(open.claim ? { claim: true } : {}) };
|
|
77
|
+
const meta = (row.metadata ?? {});
|
|
78
|
+
const facets = {};
|
|
79
|
+
for (const key of open.list.facets) {
|
|
80
|
+
const value = meta[key];
|
|
81
|
+
if (!['string', 'number', 'boolean'].includes(typeof value) || value === '')
|
|
82
|
+
return null;
|
|
83
|
+
facets[key] = value;
|
|
84
|
+
}
|
|
85
|
+
return { label, facets, ...(open.list.role ? { role: open.list.role } : {}) };
|
|
86
|
+
}
|
|
87
|
+
/** The row the button opens: the one the step answered with, the held subject, or the scanned code's own row. */
|
|
88
|
+
async function targetRow(open, ctx, data) {
|
|
89
|
+
const answered = data.escalation;
|
|
90
|
+
if (open.target === 'located')
|
|
91
|
+
return ctx.located ?? null;
|
|
92
|
+
if (open.target === 'subject' && data.outcome !== types_1.SCAN_OUTCOMES.HELD)
|
|
93
|
+
return ctx.subject?.row ?? null;
|
|
94
|
+
if (!answered?.id)
|
|
95
|
+
return null;
|
|
96
|
+
if (!open.list || answered.metadata)
|
|
97
|
+
return answered;
|
|
98
|
+
return escalationService.getEscalation(String(answered.id));
|
|
99
|
+
}
|
|
@@ -117,6 +117,7 @@ async function presentStep(step, ctx) {
|
|
|
117
117
|
escalation,
|
|
118
118
|
choices,
|
|
119
119
|
...(step.facts ? { facts: renderFacts(step, ctx, escalation) } : {}),
|
|
120
|
+
...(step.show ? { show: step.show } : {}),
|
|
120
121
|
notPrimed: ctx.rule.notPrimed,
|
|
121
122
|
...(autoSelect ? { autoSelect: true } : {}),
|
|
122
123
|
},
|
|
@@ -105,7 +105,7 @@ async function fillStep(step, ctx) {
|
|
|
105
105
|
filled: batch.keys.length - batch.pending.length,
|
|
106
106
|
},
|
|
107
107
|
};
|
|
108
|
-
const candidates = keysFor(batch.pending, ctx.parsed.target, separator);
|
|
108
|
+
const candidates = (0, fill_labels_1.preferredKeys)(keysFor(batch.pending, ctx.parsed.target, separator), options, row, ctx.subject?.parsed.target);
|
|
109
109
|
if (candidates.length === 0) {
|
|
110
110
|
const declared = keysFor(batch.keys, ctx.parsed.target, separator);
|
|
111
111
|
const markdown = declared.length
|
|
@@ -171,6 +171,24 @@ function registerResolveRoutes(router) {
|
|
|
171
171
|
}, req.auth);
|
|
172
172
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
173
173
|
});
|
|
174
|
+
/**
|
|
175
|
+
* POST /api/escalations/:id/roster-scan
|
|
176
|
+
* A scan into a batch roster on this row's form. The field must declare
|
|
177
|
+
* x-lt-scan accepting the code's scheme; the scan fills the first open entry
|
|
178
|
+
* whose key is the code, as the person acting (the badged person when
|
|
179
|
+
* X-LT-Acting-Token rides the request).
|
|
180
|
+
* Body: { field: string, code: string }
|
|
181
|
+
*/
|
|
182
|
+
router.post('/:id/roster-scan', async (req, res) => {
|
|
183
|
+
const token = req.headers[acting_1.ACTING_TOKEN_HEADER];
|
|
184
|
+
const result = await api.runRosterScan({
|
|
185
|
+
id: req.params.id,
|
|
186
|
+
field: req.body?.field,
|
|
187
|
+
code: req.body?.code,
|
|
188
|
+
actingToken: typeof token === 'string' && token ? token : undefined,
|
|
189
|
+
}, req.auth);
|
|
190
|
+
res.status(result.status).json(result.data ?? { error: result.error });
|
|
191
|
+
});
|
|
174
192
|
/**
|
|
175
193
|
* POST /api/escalations/:id/resolve
|
|
176
194
|
* Resolve a pending escalation with a human-provided payload. Routes by
|
|
@@ -84,6 +84,8 @@ export declare function getRoleFormSchema(role: string): Promise<Record<string,
|
|
|
84
84
|
export declare function getRoleMetadataSchema(role: string): Promise<Record<string, any> | null>;
|
|
85
85
|
/** The role's `properties` bag (incl. the reserved ROLE_PROPERTY_KEYS). One PK read. */
|
|
86
86
|
export declare function getRoleProperties(role: string): Promise<Record<string, any> | null>;
|
|
87
|
+
/** The role's display title, or null when it declares none. One PK read. */
|
|
88
|
+
export declare function getRoleTitle(role: string): Promise<string | null>;
|
|
87
89
|
/**
|
|
88
90
|
* Delete a role. Returns an error message if the role is referenced.
|
|
89
91
|
*/
|
|
@@ -18,6 +18,7 @@ exports.getRoleListSchema = getRoleListSchema;
|
|
|
18
18
|
exports.getRoleFormSchema = getRoleFormSchema;
|
|
19
19
|
exports.getRoleMetadataSchema = getRoleMetadataSchema;
|
|
20
20
|
exports.getRoleProperties = getRoleProperties;
|
|
21
|
+
exports.getRoleTitle = getRoleTitle;
|
|
21
22
|
exports.deleteRole = deleteRole;
|
|
22
23
|
const list_schema_1 = require("../../shared/list-schema");
|
|
23
24
|
const db_1 = require("../../lib/db");
|
|
@@ -252,6 +253,12 @@ async function getRoleProperties(role) {
|
|
|
252
253
|
const { rows } = await pool.query(sql_1.GET_ROLE_PROPERTIES, [role]);
|
|
253
254
|
return rows[0]?.properties ?? null;
|
|
254
255
|
}
|
|
256
|
+
/** The role's display title, or null when it declares none. One PK read. */
|
|
257
|
+
async function getRoleTitle(role) {
|
|
258
|
+
const pool = (0, db_1.getPool)();
|
|
259
|
+
const { rows } = await pool.query(sql_1.GET_ROLE_TITLE, [role]);
|
|
260
|
+
return rows[0]?.title ?? null;
|
|
261
|
+
}
|
|
255
262
|
/**
|
|
256
263
|
* Delete a role. Returns an error message if the role is referenced.
|
|
257
264
|
*/
|
|
@@ -14,7 +14,7 @@ function scanDoneError(value) {
|
|
|
14
14
|
if (typeof value !== 'object' || Array.isArray(value))
|
|
15
15
|
return 'properties.scan_done must be an object';
|
|
16
16
|
const done = value;
|
|
17
|
-
const known = new Set(['return', 'after_seconds']);
|
|
17
|
+
const known = new Set(['return', 'after_seconds', 'button']);
|
|
18
18
|
const extra = Object.keys(done).filter((k) => !known.has(k));
|
|
19
19
|
if (extra.length)
|
|
20
20
|
return `properties.scan_done has unknown key(s): ${extra.join(', ')}`;
|
|
@@ -25,6 +25,9 @@ function scanDoneError(value) {
|
|
|
25
25
|
&& (!Number.isInteger(done.after_seconds) || done.after_seconds < 0 || done.after_seconds > AFTER_SECONDS_MAX)) {
|
|
26
26
|
return `properties.scan_done.after_seconds must be an integer from 0 to ${AFTER_SECONDS_MAX}`;
|
|
27
27
|
}
|
|
28
|
+
if (done.button !== undefined && (typeof done.button !== 'string' || !done.button.trim())) {
|
|
29
|
+
return 'properties.scan_done.button must be non-empty text';
|
|
30
|
+
}
|
|
28
31
|
return null;
|
|
29
32
|
}
|
|
30
33
|
/** The role's return policy from its properties bag, or null when it declares none (or an unusable one). */
|
|
@@ -80,6 +80,7 @@ export declare const GET_ROLE_FORM_SCHEMA = "\n SELECT form_schema FROM lt_role
|
|
|
80
80
|
export declare const LIST_ENFORCING_ROLES = "\n SELECT role FROM lt_roles WHERE enforce_schema";
|
|
81
81
|
export declare const GET_ROLE_METADATA_SCHEMA = "\n SELECT metadata_schema FROM lt_roles WHERE role = $1";
|
|
82
82
|
export declare const GET_ROLE_PROPERTIES = "\n SELECT properties FROM lt_roles WHERE role = $1";
|
|
83
|
+
export declare const GET_ROLE_TITLE = "\n SELECT title FROM lt_roles WHERE role = $1";
|
|
83
84
|
export declare const GET_ROLE_UPSTREAMS = "\n SELECT upstream_role FROM lt_role_upstreams WHERE role = $1 ORDER BY upstream_role";
|
|
84
85
|
export declare const LIST_ROLE_SCHEMA_VERSIONS = "\n SELECT\n s.version,\n s.form_schema IS NOT NULL AS has_form_schema,\n s.metadata_schema IS NOT NULL AS has_metadata_schema,\n s.change_summary,\n s.created_at,\n s.version = r.current_schema_version AS is_current\n FROM lt_role_schemas s\n JOIN lt_roles r ON r.role = s.role\n WHERE s.role = $1\n ORDER BY s.version DESC";
|
|
85
86
|
export declare const GET_ROLE_SCHEMA_VERSION = "\n SELECT s.role, s.version, s.form_schema, s.metadata_schema,\n s.change_summary, s.created_at, r.current_schema_version AS latest_version\n FROM lt_role_schemas s\n JOIN lt_roles r ON r.role = s.role\n WHERE s.role = $1 AND s.version = $2";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// ─── Escalation chain queries ───────────────────────────────────────────────
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.COUNT_ACTIVE_ESCALATION_REFS = exports.COUNT_WORKFLOW_REFS = exports.COUNT_CHAIN_REFS = exports.COUNT_USER_ROLE_REFS = exports.LIST_ROLES_WITH_DETAILS = exports.GET_ROLE_LIST_SCHEMA_CURRENT = exports.GET_ROLE_LIST_SCHEMA_VERSION = exports.LIST_ROLE_LIST_SCHEMA_VERSIONS = exports.GET_ROLE_SCHEMA_CURRENT = exports.GET_ROLE_SCHEMA_VERSION = exports.LIST_ROLE_SCHEMA_VERSIONS = exports.GET_ROLE_UPSTREAMS = exports.GET_ROLE_PROPERTIES = exports.GET_ROLE_METADATA_SCHEMA = exports.LIST_ENFORCING_ROLES = exports.GET_ROLE_FORM_SCHEMA = exports.UPDATE_ROLE_METADATA = exports.DELETE_ROLE = exports.GET_ROLE_ROW = exports.LIST_CONFIGURED_ROLES = exports.LIST_ROLES = exports.ENSURE_ROLE_EXISTS = exports.CHECK_ESCALATION_CHAIN_EXISTS = exports.DELETE_ESCALATION_CHAINS_BY_SOURCE = exports.DELETE_ESCALATION_CHAIN = exports.ADD_ESCALATION_CHAIN = exports.INSERT_ESCALATION_CHAIN = exports.GET_ALL_ESCALATION_CHAINS = exports.GET_ESCALATION_TARGETS = void 0;
|
|
4
|
+
exports.COUNT_ACTIVE_ESCALATION_REFS = exports.COUNT_WORKFLOW_REFS = exports.COUNT_CHAIN_REFS = exports.COUNT_USER_ROLE_REFS = exports.LIST_ROLES_WITH_DETAILS = exports.GET_ROLE_LIST_SCHEMA_CURRENT = exports.GET_ROLE_LIST_SCHEMA_VERSION = exports.LIST_ROLE_LIST_SCHEMA_VERSIONS = exports.GET_ROLE_SCHEMA_CURRENT = exports.GET_ROLE_SCHEMA_VERSION = exports.LIST_ROLE_SCHEMA_VERSIONS = exports.GET_ROLE_UPSTREAMS = exports.GET_ROLE_TITLE = exports.GET_ROLE_PROPERTIES = exports.GET_ROLE_METADATA_SCHEMA = exports.LIST_ENFORCING_ROLES = exports.GET_ROLE_FORM_SCHEMA = exports.UPDATE_ROLE_METADATA = exports.DELETE_ROLE = exports.GET_ROLE_ROW = exports.LIST_CONFIGURED_ROLES = exports.LIST_ROLES = exports.ENSURE_ROLE_EXISTS = exports.CHECK_ESCALATION_CHAIN_EXISTS = exports.DELETE_ESCALATION_CHAINS_BY_SOURCE = exports.DELETE_ESCALATION_CHAIN = exports.ADD_ESCALATION_CHAIN = exports.INSERT_ESCALATION_CHAIN = exports.GET_ALL_ESCALATION_CHAINS = exports.GET_ESCALATION_TARGETS = void 0;
|
|
5
5
|
exports.GET_ESCALATION_TARGETS = `
|
|
6
6
|
SELECT target_role
|
|
7
7
|
FROM lt_config_role_escalations
|
|
@@ -197,6 +197,8 @@ exports.GET_ROLE_METADATA_SCHEMA = `
|
|
|
197
197
|
SELECT metadata_schema FROM lt_roles WHERE role = $1`;
|
|
198
198
|
exports.GET_ROLE_PROPERTIES = `
|
|
199
199
|
SELECT properties FROM lt_roles WHERE role = $1`;
|
|
200
|
+
exports.GET_ROLE_TITLE = `
|
|
201
|
+
SELECT title FROM lt_roles WHERE role = $1`;
|
|
200
202
|
exports.GET_ROLE_UPSTREAMS = `
|
|
201
203
|
SELECT upstream_role FROM lt_role_upstreams WHERE role = $1 ORDER BY upstream_role`;
|
|
202
204
|
// ─── Versioned role schemas ─────────────────────────────────────────────────
|
|
@@ -43,6 +43,8 @@ export interface RoleScanDone {
|
|
|
43
43
|
return: 'home' | string;
|
|
44
44
|
/** Seconds the done copy stays up first (0-60, default 2). */
|
|
45
45
|
after_seconds?: number;
|
|
46
|
+
/** A button on the done screen that returns at once, e.g. "Done". */
|
|
47
|
+
button?: string;
|
|
46
48
|
}
|
|
47
49
|
/** A station role's badge policy. Absent fields keep the badge scheme's value. */
|
|
48
50
|
export interface RoleBadgeGrant {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { listScanSchemes, getScanScheme, listScanRules, getScanRule, } from './read';
|
|
2
2
|
export { upsertScanScheme, deleteScanScheme, upsertScanRule, deleteScanRule, seedScanScheme, seedScanRule, applyScanScheme, applyScanRule, type ScanSchemeInput, type ScanRuleInput, } from './write';
|
|
3
|
-
export { parseScanCode, interpolateScanTemplate, mentionsClaimToken, renderScanCopy, ScanTemplateError, type ScanParseResult, type ScanParseFailure, type ScanTemplateContext, } from './parse';
|
|
3
|
+
export { parseScanCode, interpolateScanTemplate, mentionsClaimToken, mentionsLocatedToken, renderScanCopy, ScanTemplateError, type ScanParseResult, type ScanParseFailure, type ScanTemplateContext, } from './parse';
|
|
4
4
|
export { assertValidScheme, assertValidSteps, assertValidIdentityRule, assertSchemesCoexist, } from './validate';
|
|
5
5
|
export { isValidGtin, normalizeGtin, displayGtin } from '../../shared/scan-code';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.displayGtin = exports.normalizeGtin = exports.isValidGtin = exports.assertSchemesCoexist = exports.assertValidIdentityRule = exports.assertValidSteps = exports.assertValidScheme = exports.ScanTemplateError = exports.renderScanCopy = exports.mentionsClaimToken = exports.interpolateScanTemplate = exports.parseScanCode = exports.applyScanRule = exports.applyScanScheme = exports.seedScanRule = exports.seedScanScheme = exports.deleteScanRule = exports.upsertScanRule = exports.deleteScanScheme = exports.upsertScanScheme = exports.getScanRule = exports.listScanRules = exports.getScanScheme = exports.listScanSchemes = void 0;
|
|
3
|
+
exports.displayGtin = exports.normalizeGtin = exports.isValidGtin = exports.assertSchemesCoexist = exports.assertValidIdentityRule = exports.assertValidSteps = exports.assertValidScheme = exports.ScanTemplateError = exports.renderScanCopy = exports.mentionsLocatedToken = exports.mentionsClaimToken = exports.interpolateScanTemplate = exports.parseScanCode = exports.applyScanRule = exports.applyScanScheme = exports.seedScanRule = exports.seedScanScheme = exports.deleteScanRule = exports.upsertScanRule = exports.deleteScanScheme = exports.upsertScanScheme = exports.getScanRule = exports.listScanRules = exports.getScanScheme = exports.listScanSchemes = void 0;
|
|
4
4
|
var read_1 = require("./read");
|
|
5
5
|
Object.defineProperty(exports, "listScanSchemes", { enumerable: true, get: function () { return read_1.listScanSchemes; } });
|
|
6
6
|
Object.defineProperty(exports, "getScanScheme", { enumerable: true, get: function () { return read_1.getScanScheme; } });
|
|
@@ -19,6 +19,7 @@ var parse_1 = require("./parse");
|
|
|
19
19
|
Object.defineProperty(exports, "parseScanCode", { enumerable: true, get: function () { return parse_1.parseScanCode; } });
|
|
20
20
|
Object.defineProperty(exports, "interpolateScanTemplate", { enumerable: true, get: function () { return parse_1.interpolateScanTemplate; } });
|
|
21
21
|
Object.defineProperty(exports, "mentionsClaimToken", { enumerable: true, get: function () { return parse_1.mentionsClaimToken; } });
|
|
22
|
+
Object.defineProperty(exports, "mentionsLocatedToken", { enumerable: true, get: function () { return parse_1.mentionsLocatedToken; } });
|
|
22
23
|
Object.defineProperty(exports, "renderScanCopy", { enumerable: true, get: function () { return parse_1.renderScanCopy; } });
|
|
23
24
|
Object.defineProperty(exports, "ScanTemplateError", { enumerable: true, get: function () { return parse_1.ScanTemplateError; } });
|
|
24
25
|
var validate_1 = require("./validate");
|
|
@@ -27,6 +27,8 @@ export interface ScanTemplateContext {
|
|
|
27
27
|
container?: Record<string, unknown>;
|
|
28
28
|
/** The batch a fill step read: `pending`, `total`, `filled`. */
|
|
29
29
|
fill?: Record<string, unknown>;
|
|
30
|
+
/** The scanned code's own pending row: its metadata plus `id`, `role` and `roleTitle`. */
|
|
31
|
+
located?: Record<string, unknown>;
|
|
30
32
|
}
|
|
31
33
|
/** A bag token the context cannot resolve. */
|
|
32
34
|
export declare class ScanTemplateError extends Error {
|
|
@@ -36,11 +38,13 @@ export declare class ScanTemplateError extends Error {
|
|
|
36
38
|
}
|
|
37
39
|
/** True when any string in the params mentions a `{claim.…}` token. */
|
|
38
40
|
export declare function mentionsClaimToken(value: unknown): boolean;
|
|
41
|
+
/** True when any string in the value mentions a `{located.…}` token. */
|
|
42
|
+
export declare function mentionsLocatedToken(value: unknown): boolean;
|
|
39
43
|
/**
|
|
40
44
|
* Replace the template tokens inside string values of a params object.
|
|
41
45
|
* Deep, pure, non-mutating. The scan tokens are plain text replacement; the
|
|
42
46
|
* bag tokens (`{claim.x}`, `{item.x}`, `{subject.x}`, `{container.x}`,
|
|
43
|
-
* `{fill.x}`) read the context's facet bags and throw
|
|
47
|
+
* `{fill.x}`, `{located.x}`) read the context's facet bags and throw
|
|
44
48
|
* {@link ScanTemplateError} when they cannot resolve, so a literal token
|
|
45
49
|
* never reaches a row. No expression language.
|
|
46
50
|
*/
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ScanTemplateError = void 0;
|
|
4
4
|
exports.parseScanCode = parseScanCode;
|
|
5
5
|
exports.mentionsClaimToken = mentionsClaimToken;
|
|
6
|
+
exports.mentionsLocatedToken = mentionsLocatedToken;
|
|
6
7
|
exports.interpolateScanTemplate = interpolateScanTemplate;
|
|
7
8
|
exports.renderScanCopy = renderScanCopy;
|
|
8
9
|
const scan_code_1 = require("../../shared/scan-code");
|
|
@@ -21,18 +22,23 @@ class ScanTemplateError extends Error {
|
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
exports.ScanTemplateError = ScanTemplateError;
|
|
24
|
-
const BAG_TOKEN = /\{(claim|item|subject|container|fill)\.([a-zA-Z0-9_]+)\}/g;
|
|
25
|
+
const BAG_TOKEN = /\{(claim|item|subject|container|fill|located)\.([a-zA-Z0-9_]+)\}/g;
|
|
25
26
|
const MISSING_BAG = {
|
|
26
27
|
claim: 'the actor holds no single live claim',
|
|
27
28
|
item: 'no located item row on this step',
|
|
28
29
|
subject: 'no subject is held',
|
|
29
30
|
container: 'no container was located',
|
|
30
31
|
fill: 'no batch was read',
|
|
32
|
+
located: 'the scanned code has no pending row the reader can read',
|
|
31
33
|
};
|
|
32
34
|
/** True when any string in the params mentions a `{claim.…}` token. */
|
|
33
35
|
function mentionsClaimToken(value) {
|
|
34
36
|
return JSON.stringify(value ?? null).includes(`{${types_1.SCAN_TEMPLATE_BAGS.CLAIM}.`);
|
|
35
37
|
}
|
|
38
|
+
/** True when any string in the value mentions a `{located.…}` token. */
|
|
39
|
+
function mentionsLocatedToken(value) {
|
|
40
|
+
return JSON.stringify(value ?? null).includes(`{${types_1.SCAN_TEMPLATE_BAGS.LOCATED}.`);
|
|
41
|
+
}
|
|
36
42
|
function resolveBagToken(ctx, bag, facet, token) {
|
|
37
43
|
const source = ctx[bag];
|
|
38
44
|
if (!source)
|
|
@@ -49,7 +55,7 @@ function resolveBagToken(ctx, bag, facet, token) {
|
|
|
49
55
|
* Replace the template tokens inside string values of a params object.
|
|
50
56
|
* Deep, pure, non-mutating. The scan tokens are plain text replacement; the
|
|
51
57
|
* bag tokens (`{claim.x}`, `{item.x}`, `{subject.x}`, `{container.x}`,
|
|
52
|
-
* `{fill.x}`) read the context's facet bags and throw
|
|
58
|
+
* `{fill.x}`, `{located.x}`) read the context's facet bags and throw
|
|
53
59
|
* {@link ScanTemplateError} when they cannot resolve, so a literal token
|
|
54
60
|
* never reaches a row. No expression language.
|
|
55
61
|
*/
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ScanDoneCopy, type ScanStep, type ScanVerb } from '../../types';
|
|
2
|
+
/** A form field name, as `hold.show` and a present step's `show` name one. */
|
|
3
|
+
export declare const ROSTER_FIELD: RegExp;
|
|
4
|
+
/** The longest a done screen waits before the station returns. */
|
|
5
|
+
export declare const SCAN_DONE_AFTER_SECONDS_MAX = 60;
|
|
6
|
+
/** A done copy: markdown, an optional pause before the station returns, and the line under it. */
|
|
7
|
+
export declare function assertValidDoneCopy(done: ScanDoneCopy | undefined, at: string, field?: string): void;
|
|
8
|
+
/** `done` on a step or a choice that writes. */
|
|
9
|
+
export declare function assertValidDone(done: ScanDoneCopy | undefined, verb: ScanVerb, at: string, kind?: 'steps' | 'choices'): void;
|
|
10
|
+
/** `open`: the Open button on the hold, done or refusal screen a step answers with. */
|
|
11
|
+
export declare function assertValidOpen(step: ScanStep, at: string): void;
|
|
12
|
+
/** `show` on a present step: the roster field rendered above the choices. */
|
|
13
|
+
export declare function assertValidPresentShow(step: ScanStep, at: string): void;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SCAN_DONE_AFTER_SECONDS_MAX = exports.ROSTER_FIELD = void 0;
|
|
4
|
+
exports.assertValidDoneCopy = assertValidDoneCopy;
|
|
5
|
+
exports.assertValidDone = assertValidDone;
|
|
6
|
+
exports.assertValidOpen = assertValidOpen;
|
|
7
|
+
exports.assertValidPresentShow = assertValidPresentShow;
|
|
8
|
+
const types_1 = require("../../types");
|
|
9
|
+
const facet_sql_1 = require("../escalation/facet-sql");
|
|
10
|
+
/** A form field name, as `hold.show` and a present step's `show` name one. */
|
|
11
|
+
exports.ROSTER_FIELD = /^[A-Za-z_][A-Za-z0-9_-]*$/;
|
|
12
|
+
/** The longest a done screen waits before the station returns. */
|
|
13
|
+
exports.SCAN_DONE_AFTER_SECONDS_MAX = 60;
|
|
14
|
+
const OPEN_TARGETS = new Set(['row', 'subject', 'located']);
|
|
15
|
+
function isPlainObject(value) {
|
|
16
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
17
|
+
}
|
|
18
|
+
/** A done copy: markdown, an optional pause before the station returns, and the line under it. */
|
|
19
|
+
function assertValidDoneCopy(done, at, field = 'done') {
|
|
20
|
+
if (!isPlainObject(done) || typeof done.markdown !== 'string' || !done.markdown) {
|
|
21
|
+
throw new Error(`${at}: ${field}.markdown is required`);
|
|
22
|
+
}
|
|
23
|
+
const after = done.afterSeconds;
|
|
24
|
+
if (after !== undefined && (typeof after !== 'number' || !Number.isInteger(after)
|
|
25
|
+
|| after < 0 || after > exports.SCAN_DONE_AFTER_SECONDS_MAX)) {
|
|
26
|
+
throw new Error(`${at}: ${field}.afterSeconds must be an integer from 0 to ${exports.SCAN_DONE_AFTER_SECONDS_MAX}`);
|
|
27
|
+
}
|
|
28
|
+
if (done.nextPrompt !== undefined && (typeof done.nextPrompt !== 'string' || !done.nextPrompt.trim())) {
|
|
29
|
+
throw new Error(`${at}: ${field}.nextPrompt must be non-empty markdown`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** `done` on a step or a choice that writes. */
|
|
33
|
+
function assertValidDone(done, verb, at, kind = 'steps') {
|
|
34
|
+
if (done === undefined)
|
|
35
|
+
return;
|
|
36
|
+
assertValidDoneCopy(done, at);
|
|
37
|
+
if (!types_1.SCAN_MUTATING_VERBS.includes(verb))
|
|
38
|
+
throw new Error(`${at}: done applies only to ${kind} that write`);
|
|
39
|
+
}
|
|
40
|
+
/** `open`: the Open button on the hold, done or refusal screen a step answers with. */
|
|
41
|
+
function assertValidOpen(step, at) {
|
|
42
|
+
const open = step.open;
|
|
43
|
+
if (open === undefined)
|
|
44
|
+
return;
|
|
45
|
+
if (!isPlainObject(open))
|
|
46
|
+
throw new Error(`${at}: open must be an object`);
|
|
47
|
+
if (!OPEN_TARGETS.has(open.target)) {
|
|
48
|
+
throw new Error(`${at}: open.target must be 'row', 'subject' or 'located'`);
|
|
49
|
+
}
|
|
50
|
+
if (open.target === 'subject' && !step.subject && step.verb !== types_1.SCAN_VERBS.HOLD) {
|
|
51
|
+
throw new Error(`${at}: open.target 'subject' needs a held subject (a hold step, or a step with a subject gate)`);
|
|
52
|
+
}
|
|
53
|
+
if (open.label !== undefined && (typeof open.label !== 'string' || !open.label.trim())) {
|
|
54
|
+
throw new Error(`${at}: open.label must be non-empty text`);
|
|
55
|
+
}
|
|
56
|
+
if (open.claim !== undefined && typeof open.claim !== 'boolean') {
|
|
57
|
+
throw new Error(`${at}: open.claim must be a boolean`);
|
|
58
|
+
}
|
|
59
|
+
if (open.list !== undefined) {
|
|
60
|
+
const list = open.list;
|
|
61
|
+
if (!isPlainObject(list) || !Array.isArray(list.facets) || list.facets.length === 0
|
|
62
|
+
|| !list.facets.every((f) => typeof f === 'string' && facet_sql_1.FACET_KEY.test(f))) {
|
|
63
|
+
throw new Error(`${at}: open.list.facets must be a non-empty array of facet keys`);
|
|
64
|
+
}
|
|
65
|
+
if (list.role !== undefined && (typeof list.role !== 'string' || !list.role)) {
|
|
66
|
+
throw new Error(`${at}: open.list.role must be a role name`);
|
|
67
|
+
}
|
|
68
|
+
if (open.claim)
|
|
69
|
+
throw new Error(`${at}: open.claim applies to a row, not a list`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** `show` on a present step: the roster field rendered above the choices. */
|
|
73
|
+
function assertValidPresentShow(step, at) {
|
|
74
|
+
if (step.show === undefined)
|
|
75
|
+
return;
|
|
76
|
+
if (step.verb !== types_1.SCAN_VERBS.PRESENT)
|
|
77
|
+
throw new Error(`${at}: show applies only to present steps (a hold uses params.hold.show)`);
|
|
78
|
+
if (typeof step.show !== 'string' || !exports.ROSTER_FIELD.test(step.show)) {
|
|
79
|
+
throw new Error(`${at}: show must name a roster field of the row's form`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.assertValidSubjectStep = assertValidSubjectStep;
|
|
4
4
|
const types_1 = require("../../types");
|
|
5
5
|
const facet_sql_1 = require("../escalation/facet-sql");
|
|
6
|
+
const validate_station_1 = require("./validate-station");
|
|
6
7
|
function isSchemeList(value) {
|
|
7
8
|
return Array.isArray(value) && value.length > 0
|
|
8
9
|
&& value.every((v) => Number.isInteger(v) && v >= 10 && v <= 99);
|
|
@@ -10,9 +11,7 @@ function isSchemeList(value) {
|
|
|
10
11
|
function isStringList(value) {
|
|
11
12
|
return Array.isArray(value) && value.length > 0 && value.every((v) => typeof v === 'string' && v);
|
|
12
13
|
}
|
|
13
|
-
/** A
|
|
14
|
-
const HOLD_SHOW_FIELD = /^[A-Za-z_][A-Za-z0-9_-]*$/;
|
|
15
|
-
/** A fill's label map lives on the batch row: `envelope.<path>` or `metadata.<path>`. */
|
|
14
|
+
/** A fill's per-key maps live on the batch row: `envelope.<path>` or `metadata.<path>`. */
|
|
16
15
|
const FILL_LABELS_PATH = /^(envelope|metadata)\.[A-Za-z0-9_.-]+$/;
|
|
17
16
|
function isPlainObject(value) {
|
|
18
17
|
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
@@ -91,8 +90,8 @@ function assertValidSubjectStep(step, at) {
|
|
|
91
90
|
if (!isStringList(step.match.facets) || !step.match.facets.every((f) => facet_sql_1.FACET_KEY.test(f))) {
|
|
92
91
|
throw new Error(`${at}: match.facets must be a non-empty array of facet keys`);
|
|
93
92
|
}
|
|
94
|
-
if (accumulate?.from !== 'subject') {
|
|
95
|
-
throw new Error(`${at}: match.facets compares the located container
|
|
93
|
+
if (accumulate?.from !== 'subject' && !(accumulate?.into === 'subject' && accumulate.item)) {
|
|
94
|
+
throw new Error(`${at}: match.facets compares the subject with a located row: the container of a from-subject accumulate, or the item's own row of an into-subject accumulate with item`);
|
|
96
95
|
}
|
|
97
96
|
}
|
|
98
97
|
}
|
|
@@ -169,9 +168,30 @@ function assertValidHold(step, at) {
|
|
|
169
168
|
throw new Error(`${at}: params.hold.expect.prompt must be markdown`);
|
|
170
169
|
}
|
|
171
170
|
}
|
|
172
|
-
if (hold.show !== undefined && (typeof hold.show !== 'string' || !
|
|
171
|
+
if (hold.show !== undefined && (typeof hold.show !== 'string' || !validate_station_1.ROSTER_FIELD.test(hold.show))) {
|
|
173
172
|
throw new Error(`${at}: params.hold.show must name a roster field of the held row's form`);
|
|
174
173
|
}
|
|
174
|
+
if (hold.release !== undefined)
|
|
175
|
+
assertValidRelease(hold.release, at);
|
|
176
|
+
if (hold.whenAllIn !== undefined) {
|
|
177
|
+
if (hold.show === undefined)
|
|
178
|
+
throw new Error(`${at}: params.hold.whenAllIn requires params.hold.show`);
|
|
179
|
+
(0, validate_station_1.assertValidDoneCopy)(hold.whenAllIn, at, 'params.hold.whenAllIn');
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function assertValidRelease(release, at) {
|
|
183
|
+
if (!isPlainObject(release))
|
|
184
|
+
throw new Error(`${at}: params.hold.release must be an object`);
|
|
185
|
+
if (release.label !== undefined && (typeof release.label !== 'string' || !release.label.trim())) {
|
|
186
|
+
throw new Error(`${at}: params.hold.release.label must be non-empty text`);
|
|
187
|
+
}
|
|
188
|
+
if (release.tone !== undefined && release.tone !== 'neutral' && release.tone !== 'accent') {
|
|
189
|
+
throw new Error(`${at}: params.hold.release.tone must be 'neutral' or 'accent'`);
|
|
190
|
+
}
|
|
191
|
+
if (release.return !== undefined
|
|
192
|
+
&& (typeof release.return !== 'string' || !(release.return === 'home' || release.return.startsWith('/')))) {
|
|
193
|
+
throw new Error(`${at}: params.hold.release.return must be 'home' or a dashboard-relative route`);
|
|
194
|
+
}
|
|
175
195
|
}
|
|
176
196
|
function assertValidFill(step, at) {
|
|
177
197
|
const fill = step.params?.fill;
|
|
@@ -196,6 +216,13 @@ function assertValidFill(step, at) {
|
|
|
196
216
|
if (fill.label !== undefined && fill.labels === undefined) {
|
|
197
217
|
throw new Error(`${at}: params.fill.label requires params.fill.labels`);
|
|
198
218
|
}
|
|
219
|
+
if (fill.prefer !== undefined) {
|
|
220
|
+
if (typeof fill.prefer !== 'string' || !FILL_LABELS_PATH.test(fill.prefer)) {
|
|
221
|
+
throw new Error(`${at}: params.fill.prefer must name a map on the row, e.g. "envelope.key_owners"`);
|
|
222
|
+
}
|
|
223
|
+
if (fill.into !== 'subject')
|
|
224
|
+
throw new Error(`${at}: params.fill.prefer compares with the held subject, so it needs into: 'subject'`);
|
|
225
|
+
}
|
|
199
226
|
if (step.confirm)
|
|
200
227
|
throw new Error(`${at}: fill cannot carry confirm`);
|
|
201
228
|
}
|
|
@@ -10,6 +10,7 @@ const facet_sql_1 = require("../escalation/facet-sql");
|
|
|
10
10
|
const validate_subject_1 = require("./validate-subject");
|
|
11
11
|
const validate_query_1 = require("./validate-query");
|
|
12
12
|
const validate_facts_1 = require("./validate-facts");
|
|
13
|
+
const validate_station_1 = require("./validate-station");
|
|
13
14
|
const validate_scheme_pattern_1 = require("./validate-scheme-pattern");
|
|
14
15
|
const VALID_VERBS = new Set(Object.values(types_1.SCAN_VERBS));
|
|
15
16
|
/** Double-scan selection tokens — short, label-printable, never scheme-shaped. */
|
|
@@ -156,14 +157,7 @@ function assertValidChoices(choices, at) {
|
|
|
156
157
|
throw new Error(`${cat}: duplicate code "${choice.code}"`);
|
|
157
158
|
codes.add(choice.code);
|
|
158
159
|
}
|
|
159
|
-
|
|
160
|
-
if (!choice.done || typeof choice.done !== 'object' || typeof choice.done.markdown !== 'string' || !choice.done.markdown) {
|
|
161
|
-
throw new Error(`${cat}: done.markdown is required`);
|
|
162
|
-
}
|
|
163
|
-
if (!types_1.SCAN_MUTATING_VERBS.includes(choice.verb)) {
|
|
164
|
-
throw new Error(`${cat}: done applies only to choices that write`);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
160
|
+
(0, validate_station_1.assertValidDone)(choice.done, choice.verb, cat, 'choices');
|
|
167
161
|
if (choice.hidden !== undefined) {
|
|
168
162
|
if (typeof choice.hidden !== 'boolean')
|
|
169
163
|
throw new Error(`${cat}: hidden must be a boolean`);
|
|
@@ -293,14 +287,9 @@ function assertValidSteps(steps) {
|
|
|
293
287
|
}
|
|
294
288
|
}
|
|
295
289
|
(0, validate_subject_1.assertValidSubjectStep)(step, at);
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
}
|
|
300
|
-
if (!types_1.SCAN_MUTATING_VERBS.includes(step.verb)) {
|
|
301
|
-
throw new Error(`${at}: done applies only to steps that write`);
|
|
302
|
-
}
|
|
303
|
-
}
|
|
290
|
+
(0, validate_station_1.assertValidDone)(step.done, step.verb, at);
|
|
291
|
+
(0, validate_station_1.assertValidOpen)(step, at);
|
|
292
|
+
(0, validate_station_1.assertValidPresentShow)(step, at);
|
|
304
293
|
assertValidFollow(step, at);
|
|
305
294
|
assertValidTemplateTokens(step, at);
|
|
306
295
|
if (step.query && step.query.roles && !Array.isArray(step.query.roles)) {
|
|
@@ -322,7 +311,7 @@ function assertValidSteps(steps) {
|
|
|
322
311
|
}
|
|
323
312
|
});
|
|
324
313
|
}
|
|
325
|
-
const BAG_TOKEN = /\{(claim|item|subject|container|fill)\.([^}]*)\}/g;
|
|
314
|
+
const BAG_TOKEN = /\{(claim|item|subject|container|fill|located)\.([^}]*)\}/g;
|
|
326
315
|
/**
|
|
327
316
|
* Bag tokens name facet keys and may only read what the step has:
|
|
328
317
|
* `{item.…}` the row an item-mode accumulate, an into-subject accumulate
|
|
@@ -330,7 +319,9 @@ const BAG_TOKEN = /\{(claim|item|subject|container|fill)\.([^}]*)\}/g;
|
|
|
330
319
|
* presents),
|
|
331
320
|
* `{subject.…}` the held subject (steps with a subject gate), and
|
|
332
321
|
* `{container.…}` / `{fill.…}` only inside refusal and done copy, where a
|
|
333
|
-
* subject accumulate or a fill has read them (into-subject: the held row)
|
|
322
|
+
* subject accumulate or a fill has read them (into-subject: the held row),
|
|
323
|
+
* and `{located.…}` (the scanned code's own pending row) only inside refusal
|
|
324
|
+
* and done copy.
|
|
334
325
|
*/
|
|
335
326
|
function assertValidTemplateTokens(step, at) {
|
|
336
327
|
const accumulate = step.verb === types_1.SCAN_VERBS.ACCUMULATE ? step.params?.accumulate : undefined;
|
|
@@ -355,6 +346,9 @@ function assertValidTemplateTokens(step, at) {
|
|
|
355
346
|
if (bag === 'fill' && !(inRefusal && step.verb === types_1.SCAN_VERBS.FILL)) {
|
|
356
347
|
throw new Error(`${at}: ${token} is readable only in the refusal or done copy of a fill step`);
|
|
357
348
|
}
|
|
349
|
+
if (bag === 'located' && !inRefusal) {
|
|
350
|
+
throw new Error(`${at}: ${token} is readable only in refusal or done copy`);
|
|
351
|
+
}
|
|
358
352
|
}
|
|
359
353
|
};
|
|
360
354
|
check(step.params, false);
|