@runcofactor/cli 0.54.0 → 0.56.0
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/README.md +2 -1
- package/dist/{account-6YJAU53I.js → account-CZYZD2JS.js} +5 -5
- package/dist/{alert-Z7V2ZUEW.js → alert-JQ4SDEB7.js} +8 -8
- package/dist/{api-catalog-UEDTRM6E.js → api-catalog-IWQC35P2.js} +5 -5
- package/dist/{api-key-V5GEPRRG.js → api-key-GUDXIIEA.js} +5 -5
- package/dist/{attachment-M7VZ6GSE.js → attachment-CPZYOBUB.js} +5 -5
- package/dist/{auth-DVTMWJKF.js → auth-DS6MBVEI.js} +3 -3
- package/dist/{benchmark-KZJZYUTQ.js → benchmark-6HPCIQHD.js} +5 -5
- package/dist/{blackcat-QJXYDE66.js → blackcat-V3L63WFE.js} +3 -3
- package/dist/{chunk-FLDIN6VX.js → chunk-2E3STBHS.js} +2 -2
- package/dist/{chunk-KNWKOKM7.js → chunk-2OHYMT3A.js} +20 -11
- package/dist/chunk-2OHYMT3A.js.map +1 -0
- package/dist/{chunk-L4Y5PZUE.js → chunk-3LGCHNBC.js} +2 -2
- package/dist/{chunk-ZFN5FWN2.js → chunk-4MFMPC5P.js} +46 -2
- package/dist/chunk-4MFMPC5P.js.map +1 -0
- package/dist/{chunk-2M4PZK6Q.js → chunk-56HFZHQM.js} +8 -8
- package/dist/{chunk-AQOHNAEN.js → chunk-5OYWNS6D.js} +20 -9
- package/dist/chunk-5OYWNS6D.js.map +1 -0
- package/dist/{chunk-RA2NRAWU.js → chunk-62EXS76C.js} +6 -6
- package/dist/{chunk-HGEJHS45.js → chunk-6ILWJFKY.js} +368 -6
- package/dist/chunk-6ILWJFKY.js.map +1 -0
- package/dist/{chunk-4EWSONHO.js → chunk-BDOL622T.js} +4 -4
- package/dist/{chunk-T6EQFICG.js → chunk-C3CXVX2B.js} +4 -4
- package/dist/{chunk-33U56YGD.js → chunk-CWICLBLU.js} +2 -1
- package/dist/{chunk-33U56YGD.js.map → chunk-CWICLBLU.js.map} +1 -1
- package/dist/{chunk-MQQCUU5S.js → chunk-DEVD2WD2.js} +2 -2
- package/dist/{chunk-TRC63RSK.js → chunk-EWK44F6V.js} +3 -3
- package/dist/chunk-EWK44F6V.js.map +1 -0
- package/dist/{chunk-Q7UAEFW5.js → chunk-FNHPTTRF.js} +7 -5
- package/dist/chunk-FNHPTTRF.js.map +1 -0
- package/dist/{chunk-JAIMLQOU.js → chunk-GCD4EHCD.js} +6 -6
- package/dist/{chunk-7MRZWPVC.js → chunk-H6ZMKNP7.js} +3 -3
- package/dist/{chunk-ZOPVBINJ.js → chunk-IEWAH7W3.js} +5 -5
- package/dist/{chunk-74TU6PGO.js → chunk-IV4HRGKX.js} +77 -12
- package/dist/chunk-IV4HRGKX.js.map +1 -0
- package/dist/{chunk-ZO5MSM4Q.js → chunk-J2ZQULU3.js} +2 -2
- package/dist/{chunk-IVWWYKAM.js → chunk-K2IDR6FR.js} +3 -3
- package/dist/{chunk-QGP67JOK.js → chunk-KTZRI27M.js} +4 -4
- package/dist/{chunk-HESV3F6U.js → chunk-L644NMDI.js} +3 -3
- package/dist/{chunk-HESV3F6U.js.map → chunk-L644NMDI.js.map} +1 -1
- package/dist/{chunk-LPQTXBJF.js → chunk-LFT7GUWS.js} +63 -17
- package/dist/chunk-LFT7GUWS.js.map +1 -0
- package/dist/{chunk-O7MBDOMO.js → chunk-O7B2IYCZ.js} +30 -14
- package/dist/chunk-O7B2IYCZ.js.map +1 -0
- package/dist/{chunk-R2CVV7QT.js → chunk-RHWPZKRV.js} +28 -1
- package/dist/chunk-RHWPZKRV.js.map +1 -0
- package/dist/{chunk-3YNR6U6Q.js → chunk-UJSW72LG.js} +3 -3
- package/dist/{chunk-G2SCV2CY.js → chunk-VACACCD6.js} +3 -3
- package/dist/{chunk-CV22445U.js → chunk-VMAR67FF.js} +2 -2
- package/dist/{chunk-QYHJUHL7.js → chunk-VMJ7TBVM.js} +2 -2
- package/dist/chunk-WRRA4ATV.js +332 -0
- package/dist/chunk-WRRA4ATV.js.map +1 -0
- package/dist/{chunk-YACDH6MJ.js → chunk-XHEVDABB.js} +2 -2
- package/dist/{chunk-7VBX2M4F.js → chunk-XHGF6VC6.js} +4 -4
- package/dist/{credential-546ER7WQ.js → credential-GJW7LGYP.js} +5 -5
- package/dist/{credential-template-BWMEBGBN.js → credential-template-UWBYKKWD.js} +5 -5
- package/dist/dev-PBW7BSOD.js +605 -0
- package/dist/dev-PBW7BSOD.js.map +1 -0
- package/dist/{digest-NIVBDDI2.js → digest-XEHGCJM4.js} +8 -8
- package/dist/{docs-AK4MDP6K.js → docs-KH4BCEQF.js} +5 -5
- package/dist/{doctor-NCLA47EL.js → doctor-FOXXE5SK.js} +3 -3
- package/dist/{environment-X3PV5IN2.js → environment-EBDPQTIS.js} +7 -7
- package/dist/{eval-5FZKYZ6O.js → eval-QZSSEICV.js} +67 -27
- package/dist/eval-QZSSEICV.js.map +1 -0
- package/dist/{exploration-2RVGIUKT.js → exploration-LCGKRGOQ.js} +5 -5
- package/dist/{exploratory-test-SJ5HFI3L.js → exploratory-test-SGECQGIX.js} +13 -5
- package/dist/exploratory-test-SGECQGIX.js.map +1 -0
- package/dist/{external-run-4NDVAHQB.js → external-run-2AJAI5O7.js} +9 -9
- package/dist/{feature-flag-C4IRE724.js → feature-flag-P7N4WQIH.js} +5 -5
- package/dist/{feedback-337OZCKC.js → feedback-LAT7TQ2T.js} +6 -6
- package/dist/{flow-D7ZLBKCH.js → flow-NH2DC6AP.js} +5 -5
- package/dist/{github-LKXYIALH.js → github-FCEKBLXI.js} +6 -6
- package/dist/index.js +106 -408
- package/dist/index.js.map +1 -1
- package/dist/{init-GKEC6LPH.js → init-5U5EZOAW.js} +5 -5
- package/dist/{install-K45SAT2V.js → install-X3UNVXKY.js} +5 -5
- package/dist/{issues-2HMTQYWR.js → issues-4P6I3YQW.js} +8 -8
- package/dist/{knobs-KUCGLO5Z.js → knobs-JKTWJ6ZG.js} +5 -5
- package/dist/{landing-KAET2I73.js → landing-6AGLKI66.js} +7 -7
- package/dist/{list-GDV4UYWV.js → list-TWP2RP33.js} +5 -5
- package/dist/{local-NFOSJLLV.js → local-D75QE5TB.js} +7 -7
- package/dist/{login-Y77HWROY.js → login-RBET4TIP.js} +5 -5
- package/dist/{mcp-CPCFMU6B.js → mcp-562SUUMK.js} +11 -11
- package/dist/{metrics-Y245ST63.js → metrics-4WF2GEPA.js} +5 -5
- package/dist/{monitor-BUDWSC3S.js → monitor-WJXH54H2.js} +5 -5
- package/dist/{perf-3JOAXPHP.js → perf-C6N6P7YG.js} +12 -361
- package/dist/perf-C6N6P7YG.js.map +1 -0
- package/dist/{product-CXL3YTMD.js → product-CYEQ7HOB.js} +5 -5
- package/dist/{product-map-656BTU74.js → product-map-MSDLIFZY.js} +7 -7
- package/dist/{prompts-3SZ7O5E6.js → prompts-ME53WPN4.js} +5 -5
- package/dist/{proofs-4CSCCSNL.js → proofs-D3G6ZUFP.js} +11 -9
- package/dist/{property-IEKBXRVY.js → property-5GLJNAVB.js} +29 -10
- package/dist/property-5GLJNAVB.js.map +1 -0
- package/dist/{psql-M4CM6TSI.js → psql-EXAUDU3W.js} +5 -5
- package/dist/{record-QP4TYZBS.js → record-EE7NGNKY.js} +6 -6
- package/dist/{redis-KG47IGJV.js → redis-M4EYWKOJ.js} +5 -5
- package/dist/{release-QHPSQULK.js → release-4KUWVWWC.js} +5 -5
- package/dist/{runbook-YVBG2QK3.js → runbook-AHU77ANQ.js} +5 -5
- package/dist/{sandbox-ZXDZTCCN.js → sandbox-FBLJEYA2.js} +1917 -1633
- package/dist/sandbox-FBLJEYA2.js.map +1 -0
- package/dist/{scenarios-2SX2NUCD.js → scenarios-TU656T2B.js} +5 -5
- package/dist/{schedule-P6F7MLXX.js → schedule-DXJI6SYO.js} +8 -8
- package/dist/{session-SZMCZTPE.js → session-RUFTJHF4.js} +10 -10
- package/dist/{skill-D4XFW6QI.js → skill-ZK76GQ47.js} +111 -13
- package/dist/skill-ZK76GQ47.js.map +1 -0
- package/dist/skills/cofactor-debug-run/SKILL.md +6 -1
- package/dist/skills/cofactor-debug-run/history/2.0.10.md +320 -0
- package/dist/skills/cofactor-debug-run/history/2.0.9.md +319 -0
- package/dist/skills/cofactor-debug-run/version.json +1 -1
- package/dist/{slack-UDXTPOSW.js → slack-M3OKDVMY.js} +6 -6
- package/dist/{spec-YCBBIV27.js → spec-5MXEBLYR.js} +5 -5
- package/dist/{src-DY7GLRO2.js → src-2X5OQRPJ.js} +4 -4
- package/dist/{src-NG7DRE5A.js → src-72EFBA2R.js} +3 -3
- package/dist/{src-DEGBASCD.js → src-KH6WSBJV.js} +5 -5
- package/dist/{src-ZKVNVLXY.js → src-VLV36QYH.js} +127 -20
- package/dist/src-VLV36QYH.js.map +1 -0
- package/dist/{start-ZYZSORPY.js → start-PDYBRB5T.js} +5 -5
- package/dist/{status-ESIG6A7W.js → status-VMVPVCDA.js} +5 -5
- package/dist/{tag-3K5Y25AR.js → tag-7KTDLPVU.js} +6 -6
- package/dist/{task-JLNX7O3M.js → task-QLFYZNKR.js} +6 -6
- package/dist/{teams-F4IU3EXE.js → teams-Y7BXCY6P.js} +7 -7
- package/dist/{test-suite-QHDUW5W5.js → test-suite-6U22AYFG.js} +15 -14
- package/dist/test-suite-6U22AYFG.js.map +1 -0
- package/dist/{tickets-NBL5WACL.js → tickets-CQDJDNPY.js} +5 -5
- package/dist/{trace-ZKYAI5JF.js → trace-QDORWXYX.js} +8 -8
- package/dist/{triage-5NWCREUM.js → triage-GY7M3UGG.js} +6 -6
- package/dist/{trigger-KXYYY5IR.js → trigger-DLFAORX4.js} +9 -9
- package/dist/{update-check-Q2URVJLC.js → update-check-ES6XQ7OF.js} +4 -4
- package/dist/{upgrade-4XSASC7U.js → upgrade-WKEOW5GS.js} +5 -5
- package/dist/{usage-UY7VZYVY.js → usage-E6FDTR3W.js} +7 -7
- package/dist/{utilities-53NXNLA7.js → utilities-4Z6YX3L5.js} +6 -6
- package/dist/{visual-IJAT7X7D.js → visual-TA6LPVDJ.js} +5 -5
- package/dist/{workflow-OQNH2FIS.js → workflow-B5FXS2CJ.js} +92 -36
- package/dist/workflow-B5FXS2CJ.js.map +1 -0
- package/dist/{workflow-cache-FP6MKLVR.js → workflow-cache-MNLEMRMM.js} +16 -16
- package/dist/{workflow-cache-convergence-resolve-HS5KO7US.js → workflow-cache-convergence-resolve-G5HJM6MF.js} +5 -5
- package/dist/{workflow-debug-EM55H2QE.js → workflow-debug-TNBUGSBK.js} +11 -11
- package/dist/{workflow-feedback-GNWNWVHH.js → workflow-feedback-G2ZXAUGI.js} +5 -5
- package/dist/{workflow-fork-M5AQWST7.js → workflow-fork-6HHOMC2D.js} +5 -5
- package/dist/{workflow-promotion-HYULZDYL.js → workflow-promotion-RG7L6JZT.js} +5 -5
- package/dist/{workflow-proposals-EN327FSE.js → workflow-proposals-ZNF2F3UE.js} +5 -5
- package/dist/{workflow-revisions-ZMTVNWRW.js → workflow-revisions-TP64Z6FO.js} +5 -5
- package/dist/{workflow-status-FNAJG34W.js → workflow-status-5RG3JX56.js} +5 -5
- package/package.json +3 -2
- package/dist/chunk-74TU6PGO.js.map +0 -1
- package/dist/chunk-AQOHNAEN.js.map +0 -1
- package/dist/chunk-HGEJHS45.js.map +0 -1
- package/dist/chunk-KNWKOKM7.js.map +0 -1
- package/dist/chunk-LPQTXBJF.js.map +0 -1
- package/dist/chunk-O7MBDOMO.js.map +0 -1
- package/dist/chunk-Q7UAEFW5.js.map +0 -1
- package/dist/chunk-R2CVV7QT.js.map +0 -1
- package/dist/chunk-TRC63RSK.js.map +0 -1
- package/dist/chunk-ZFN5FWN2.js.map +0 -1
- package/dist/eval-5FZKYZ6O.js.map +0 -1
- package/dist/exploratory-test-SJ5HFI3L.js.map +0 -1
- package/dist/perf-3JOAXPHP.js.map +0 -1
- package/dist/property-IEKBXRVY.js.map +0 -1
- package/dist/sandbox-ZXDZTCCN.js.map +0 -1
- package/dist/skill-D4XFW6QI.js.map +0 -1
- package/dist/src-ZKVNVLXY.js.map +0 -1
- package/dist/test-suite-QHDUW5W5.js.map +0 -1
- package/dist/workflow-OQNH2FIS.js.map +0 -1
- /package/dist/{account-6YJAU53I.js.map → account-CZYZD2JS.js.map} +0 -0
- /package/dist/{alert-Z7V2ZUEW.js.map → alert-JQ4SDEB7.js.map} +0 -0
- /package/dist/{api-catalog-UEDTRM6E.js.map → api-catalog-IWQC35P2.js.map} +0 -0
- /package/dist/{api-key-V5GEPRRG.js.map → api-key-GUDXIIEA.js.map} +0 -0
- /package/dist/{attachment-M7VZ6GSE.js.map → attachment-CPZYOBUB.js.map} +0 -0
- /package/dist/{auth-DVTMWJKF.js.map → auth-DS6MBVEI.js.map} +0 -0
- /package/dist/{benchmark-KZJZYUTQ.js.map → benchmark-6HPCIQHD.js.map} +0 -0
- /package/dist/{blackcat-QJXYDE66.js.map → blackcat-V3L63WFE.js.map} +0 -0
- /package/dist/{chunk-FLDIN6VX.js.map → chunk-2E3STBHS.js.map} +0 -0
- /package/dist/{chunk-L4Y5PZUE.js.map → chunk-3LGCHNBC.js.map} +0 -0
- /package/dist/{chunk-2M4PZK6Q.js.map → chunk-56HFZHQM.js.map} +0 -0
- /package/dist/{chunk-RA2NRAWU.js.map → chunk-62EXS76C.js.map} +0 -0
- /package/dist/{chunk-4EWSONHO.js.map → chunk-BDOL622T.js.map} +0 -0
- /package/dist/{chunk-T6EQFICG.js.map → chunk-C3CXVX2B.js.map} +0 -0
- /package/dist/{chunk-MQQCUU5S.js.map → chunk-DEVD2WD2.js.map} +0 -0
- /package/dist/{chunk-JAIMLQOU.js.map → chunk-GCD4EHCD.js.map} +0 -0
- /package/dist/{chunk-7MRZWPVC.js.map → chunk-H6ZMKNP7.js.map} +0 -0
- /package/dist/{chunk-ZOPVBINJ.js.map → chunk-IEWAH7W3.js.map} +0 -0
- /package/dist/{chunk-ZO5MSM4Q.js.map → chunk-J2ZQULU3.js.map} +0 -0
- /package/dist/{chunk-IVWWYKAM.js.map → chunk-K2IDR6FR.js.map} +0 -0
- /package/dist/{chunk-QGP67JOK.js.map → chunk-KTZRI27M.js.map} +0 -0
- /package/dist/{chunk-3YNR6U6Q.js.map → chunk-UJSW72LG.js.map} +0 -0
- /package/dist/{chunk-G2SCV2CY.js.map → chunk-VACACCD6.js.map} +0 -0
- /package/dist/{chunk-CV22445U.js.map → chunk-VMAR67FF.js.map} +0 -0
- /package/dist/{chunk-QYHJUHL7.js.map → chunk-VMJ7TBVM.js.map} +0 -0
- /package/dist/{chunk-YACDH6MJ.js.map → chunk-XHEVDABB.js.map} +0 -0
- /package/dist/{chunk-7VBX2M4F.js.map → chunk-XHGF6VC6.js.map} +0 -0
- /package/dist/{credential-546ER7WQ.js.map → credential-GJW7LGYP.js.map} +0 -0
- /package/dist/{credential-template-BWMEBGBN.js.map → credential-template-UWBYKKWD.js.map} +0 -0
- /package/dist/{digest-NIVBDDI2.js.map → digest-XEHGCJM4.js.map} +0 -0
- /package/dist/{docs-AK4MDP6K.js.map → docs-KH4BCEQF.js.map} +0 -0
- /package/dist/{doctor-NCLA47EL.js.map → doctor-FOXXE5SK.js.map} +0 -0
- /package/dist/{environment-X3PV5IN2.js.map → environment-EBDPQTIS.js.map} +0 -0
- /package/dist/{exploration-2RVGIUKT.js.map → exploration-LCGKRGOQ.js.map} +0 -0
- /package/dist/{external-run-4NDVAHQB.js.map → external-run-2AJAI5O7.js.map} +0 -0
- /package/dist/{feature-flag-C4IRE724.js.map → feature-flag-P7N4WQIH.js.map} +0 -0
- /package/dist/{feedback-337OZCKC.js.map → feedback-LAT7TQ2T.js.map} +0 -0
- /package/dist/{flow-D7ZLBKCH.js.map → flow-NH2DC6AP.js.map} +0 -0
- /package/dist/{github-LKXYIALH.js.map → github-FCEKBLXI.js.map} +0 -0
- /package/dist/{init-GKEC6LPH.js.map → init-5U5EZOAW.js.map} +0 -0
- /package/dist/{install-K45SAT2V.js.map → install-X3UNVXKY.js.map} +0 -0
- /package/dist/{issues-2HMTQYWR.js.map → issues-4P6I3YQW.js.map} +0 -0
- /package/dist/{knobs-KUCGLO5Z.js.map → knobs-JKTWJ6ZG.js.map} +0 -0
- /package/dist/{landing-KAET2I73.js.map → landing-6AGLKI66.js.map} +0 -0
- /package/dist/{list-GDV4UYWV.js.map → list-TWP2RP33.js.map} +0 -0
- /package/dist/{local-NFOSJLLV.js.map → local-D75QE5TB.js.map} +0 -0
- /package/dist/{login-Y77HWROY.js.map → login-RBET4TIP.js.map} +0 -0
- /package/dist/{mcp-CPCFMU6B.js.map → mcp-562SUUMK.js.map} +0 -0
- /package/dist/{metrics-Y245ST63.js.map → metrics-4WF2GEPA.js.map} +0 -0
- /package/dist/{monitor-BUDWSC3S.js.map → monitor-WJXH54H2.js.map} +0 -0
- /package/dist/{product-CXL3YTMD.js.map → product-CYEQ7HOB.js.map} +0 -0
- /package/dist/{product-map-656BTU74.js.map → product-map-MSDLIFZY.js.map} +0 -0
- /package/dist/{prompts-3SZ7O5E6.js.map → prompts-ME53WPN4.js.map} +0 -0
- /package/dist/{proofs-4CSCCSNL.js.map → proofs-D3G6ZUFP.js.map} +0 -0
- /package/dist/{psql-M4CM6TSI.js.map → psql-EXAUDU3W.js.map} +0 -0
- /package/dist/{record-QP4TYZBS.js.map → record-EE7NGNKY.js.map} +0 -0
- /package/dist/{redis-KG47IGJV.js.map → redis-M4EYWKOJ.js.map} +0 -0
- /package/dist/{release-QHPSQULK.js.map → release-4KUWVWWC.js.map} +0 -0
- /package/dist/{runbook-YVBG2QK3.js.map → runbook-AHU77ANQ.js.map} +0 -0
- /package/dist/{scenarios-2SX2NUCD.js.map → scenarios-TU656T2B.js.map} +0 -0
- /package/dist/{schedule-P6F7MLXX.js.map → schedule-DXJI6SYO.js.map} +0 -0
- /package/dist/{session-SZMCZTPE.js.map → session-RUFTJHF4.js.map} +0 -0
- /package/dist/{slack-UDXTPOSW.js.map → slack-M3OKDVMY.js.map} +0 -0
- /package/dist/{spec-YCBBIV27.js.map → spec-5MXEBLYR.js.map} +0 -0
- /package/dist/{src-DEGBASCD.js.map → src-2X5OQRPJ.js.map} +0 -0
- /package/dist/{src-DY7GLRO2.js.map → src-72EFBA2R.js.map} +0 -0
- /package/dist/{src-NG7DRE5A.js.map → src-KH6WSBJV.js.map} +0 -0
- /package/dist/{start-ZYZSORPY.js.map → start-PDYBRB5T.js.map} +0 -0
- /package/dist/{status-ESIG6A7W.js.map → status-VMVPVCDA.js.map} +0 -0
- /package/dist/{tag-3K5Y25AR.js.map → tag-7KTDLPVU.js.map} +0 -0
- /package/dist/{task-JLNX7O3M.js.map → task-QLFYZNKR.js.map} +0 -0
- /package/dist/{teams-F4IU3EXE.js.map → teams-Y7BXCY6P.js.map} +0 -0
- /package/dist/{tickets-NBL5WACL.js.map → tickets-CQDJDNPY.js.map} +0 -0
- /package/dist/{trace-ZKYAI5JF.js.map → trace-QDORWXYX.js.map} +0 -0
- /package/dist/{triage-5NWCREUM.js.map → triage-GY7M3UGG.js.map} +0 -0
- /package/dist/{trigger-KXYYY5IR.js.map → trigger-DLFAORX4.js.map} +0 -0
- /package/dist/{update-check-Q2URVJLC.js.map → update-check-ES6XQ7OF.js.map} +0 -0
- /package/dist/{upgrade-4XSASC7U.js.map → upgrade-WKEOW5GS.js.map} +0 -0
- /package/dist/{usage-UY7VZYVY.js.map → usage-E6FDTR3W.js.map} +0 -0
- /package/dist/{utilities-53NXNLA7.js.map → utilities-4Z6YX3L5.js.map} +0 -0
- /package/dist/{visual-IJAT7X7D.js.map → visual-TA6LPVDJ.js.map} +0 -0
- /package/dist/{workflow-cache-FP6MKLVR.js.map → workflow-cache-MNLEMRMM.js.map} +0 -0
- /package/dist/{workflow-cache-convergence-resolve-HS5KO7US.js.map → workflow-cache-convergence-resolve-G5HJM6MF.js.map} +0 -0
- /package/dist/{workflow-debug-EM55H2QE.js.map → workflow-debug-TNBUGSBK.js.map} +0 -0
- /package/dist/{workflow-feedback-GNWNWVHH.js.map → workflow-feedback-G2ZXAUGI.js.map} +0 -0
- /package/dist/{workflow-fork-M5AQWST7.js.map → workflow-fork-6HHOMC2D.js.map} +0 -0
- /package/dist/{workflow-promotion-HYULZDYL.js.map → workflow-promotion-RG7L6JZT.js.map} +0 -0
- /package/dist/{workflow-proposals-EN327FSE.js.map → workflow-proposals-ZNF2F3UE.js.map} +0 -0
- /package/dist/{workflow-revisions-ZMTVNWRW.js.map → workflow-revisions-TP64Z6FO.js.map} +0 -0
- /package/dist/{workflow-status-FNAJG34W.js.map → workflow-status-5RG3JX56.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../emulation/src/plugins/aws/index.ts","../../emulation/src/plugins/aws/config.ts","../../emulation/src/plugins/aws/protocol.ts","../../emulation/src/plugins/aws/ssm.ts","../../emulation/src/plugins/aws/kms.ts","../../emulation/src/service/tls.ts","../../emulation/src/plugins/aws/secrets-manager.ts","../../emulation/src/plugins/email.ts","../../emulation/src/plugins/email/actions.ts","../../emulation/src/plugins/email/handlers.ts","../../emulation/src/plugins/email/capture.ts","../../emulation/src/plugins/email/parsing.ts","../../emulation/src/plugins/email/mailosaur.ts","../../emulation/src/plugins/email/types.ts","../../emulation/src/plugins/oidc-core.ts","../../emulation/src/plugins/jwt.ts","../../emulation/src/persona-identity.ts","../../emulation/src/plugins/google-oauth.ts","../../emulation/src/plugins/esri/index.ts","../../emulation/src/token-match.ts","../../emulation/src/plugins/esri/errors.ts","../../emulation/src/plugins/esri/layers.ts","../../emulation/src/credential-keys.ts","../../emulation/src/redact-json.ts","../../emulation/src/plugins/esri/where.ts","../../emulation/src/plugins/esri/params.ts","../../emulation/src/plugins/esri/operations.ts","../../emulation/src/plugin.ts","../../emulation/src/plugins/esri/tenants.ts","../../emulation/src/plugins/esri/query.ts","../../emulation/src/plugins/jira.ts","../../emulation/src/plugins/maximo-stub.ts","../../emulation/src/plugins/maximo-stub-data.ts","../../emulation/src/authorize-key.ts","../../emulation/src/sign-in-gate.ts","../../emulation/src/plugins/oidc.ts","../../emulation/src/plugins/slack.ts","../../emulation/src/plugins/index.ts","../../emulation/src/operations.ts","../../emulation/src/env-contract.ts","../../emulation/src/google-oauth-browser.ts","../../emulation/src/oidc-gate-browser.ts"],"sourcesContent":["/**\n * AWS Emulation Plugin\n *\n * Emulates AWS service APIs an app calls with its unmodified AWS SDK: the\n * sandbox resolves `<service>.<region>.amazonaws.com` to the emulator, which\n * serves it over TLS from the emulation CA, so no `AWS_ENDPOINT_URL_*` or code\n * change is needed. Only the services the config declares a section for are\n * intercepted, in each configured region (default `us-east-1`); the `email`\n * plugin keeps owning SES.\n *\n * Services: Secrets Manager (read-only, seeded by the definition) and KMS\n * (seeded Decrypt mappings plus Encrypt/Decrypt/GenerateDataKey under an\n * emulated key) and SSM Parameter Store (read-only, seeded by the definition).\n *\n * Seeded values may hold `${params.x}` and `${secrets.NAME}` references; the\n * sandbox resolves them before the emulator starts (see the sandbox helper's\n * `emulationConfigFor` in emulation-refs.ts), so this plugin only ever sees final values. No\n * value is logged, recorded or returned by an operation: the `secrets`\n * operation lists names, ARNs and version ids.\n *\n * @module\n */\n\nimport { z } from 'zod';\nimport type { EmulationPlugin } from '../../plugin.js';\nimport { awsConfigSchema, declaredServices, type AwsConfigInput } from './config.js';\nimport { serviceHost } from './protocol.js';\nimport { handleKms, initKms } from './kms.js';\nimport { handleSecretsManager, initSecretsManager, secretArn } from './secrets-manager.js';\nimport { handleSsm, initSsm, PARAMETER_TYPES, PARAMETER_VERSION, parameterArn } from './ssm.js';\nimport type { AwsCtx, AwsFixture, AwsState } from './types.js';\n\n/**\n * Each service's handler answers only its own host. It returns null for\n * another host, and also for its own host's calls it does not emulate; those\n * stay a 501, since every later handler also checks its own host first.\n */\nconst SERVICE_HANDLERS = [handleSecretsManager, handleKms, handleSsm];\n\nconst parameterSummary = z.object({\n name: z.string(),\n type: z.enum(PARAMETER_TYPES),\n version: z.number(),\n /** The parameter's ARN in each intercepted region. */\n arns: z.array(z.string()),\n /** How many times the app has read the parameter since boot. */\n reads: z.number(),\n});\n\nconst secretSummary = z.object({\n name: z.string(),\n versionId: z.string(),\n /** The secret's ARN in each intercepted region. */\n arns: z.array(z.string()),\n /** How many times the app has read the secret's value since boot. */\n reads: z.number(),\n});\n\nexport const awsPlugin: EmulationPlugin<AwsConfigInput, AwsFixture, AwsState> = {\n id: 'aws',\n name: 'AWS (Secrets Manager, KMS, SSM Parameter Store)',\n version: '1.0.0',\n\n configSchema: awsConfigSchema,\n configReferences: true,\n\n // Definition validation already checked the config; parsing again applies its defaults.\n domains: (input) => {\n const config = awsConfigSchema.parse(input);\n return declaredServices(config).flatMap((service) => config.regions.map((region) => serviceHost(service, region)));\n },\n\n needsBrowserIntercept: false,\n\n operations: [\n {\n id: 'secrets',\n description: 'The seeded Secrets Manager secrets: names, ARNs, version ids and read counts, never values.',\n input: z.object({}).strict(),\n output: z.object({ secrets: z.array(secretSummary) }),\n handler: (ctx: AwsCtx) => ({\n secrets: [...(ctx.state.secretsManager?.secrets.values() ?? [])].map((secret) => ({\n name: secret.name,\n versionId: secret.versionId,\n arns: ctx.state.regions.map((region) => secretArn(secret, region)),\n reads: secret.reads,\n })),\n }),\n },\n {\n id: 'parameters',\n description: 'The seeded SSM parameters: names, types, versions, ARNs and read counts, never values.',\n input: z.object({}).strict(),\n output: z.object({ parameters: z.array(parameterSummary) }),\n handler: (ctx: AwsCtx) => ({\n parameters: [...(ctx.state.ssm?.parameters.values() ?? [])].map((parameter) => ({\n name: parameter.name,\n type: parameter.type,\n version: PARAMETER_VERSION,\n arns: ctx.state.regions.map((region) => parameterArn(parameter, region)),\n reads: parameter.reads,\n })),\n }),\n },\n ],\n\n routes: [\n // Every AWS JSON 1.1 call is `POST /`; the host names the service and `X-Amz-Target` the operation.\n {\n method: 'POST',\n path: '/',\n handler: (req, ctx: AwsCtx) => {\n for (const handle of SERVICE_HANDLERS) {\n const response = handle(req, ctx);\n if (response) return response;\n }\n return null;\n },\n },\n ],\n\n initialize(input): AwsState {\n const config = awsConfigSchema.parse(input);\n return {\n regions: config.regions,\n createdDate: Math.floor(Date.now() / 1000),\n secretsManager: config.secrets_manager ? initSecretsManager(config.secrets_manager) : null,\n kms: config.kms ? initKms(config.kms) : null,\n ssm: config.ssm ? initSsm(config.ssm) : null,\n };\n },\n};\n","/**\n * The `aws` plugin's config: a definition's `emulation.aws` block. Each\n * declared service section is intercepted in every listed region; a service\n * without a section is not intercepted at all.\n *\n * @module\n */\n\nimport { z } from 'zod';\nimport { isBase64, REGION, type AwsService } from './protocol.js';\nimport { PARAMETER_TYPES } from './ssm.js';\n\n/** Secrets Manager's own secret-name alphabet (1–512 characters). */\nconst SECRET_NAME = /^[A-Za-z0-9/_+=.@-]{1,512}$/;\n\nconst secretsManagerSchema = z.strictObject({\n /** Secret name -> its value: a string is the SecretString as is; an object is served as its JSON. */\n secrets: z\n .record(z.string(), z.union([z.string(), z.record(z.string(), z.unknown())]))\n .superRefine((secrets, ctx) => {\n for (const name of Object.keys(secrets)) {\n if (!SECRET_NAME.test(name)) {\n ctx.addIssue({ code: 'custom', path: [name], message: 'a secret name is 1-512 letters, digits and /_+=.@-' });\n }\n }\n }),\n});\n\n/**\n * Standard padded base64, or a value holding a reference: the sandbox checks\n * the config again once references are resolved, so that one must be base64 too.\n */\nconst base64OrReference = z.string().refine((value) => isBase64(value) || value.includes('${'), { message: 'must be base64' });\n\nconst kmsSchema = z.strictObject({\n /** Ciphertext made by real KMS -> its plaintext, both base64: the only way such ciphertext decrypts in a sandbox. */\n decrypt: z\n .array(\n z.strictObject({\n ciphertext: base64OrReference,\n plaintext: base64OrReference,\n /** The key real KMS encrypted it under (id, ARN or alias); Decrypt answers with it. */\n key_id: z\n .string()\n .regex(/^(?:alias\\/[\\w/.-]+|[\\w-]+|arn:[a-z-]+:kms:[a-z0-9-]+:\\d{12}:(?:key\\/[\\w-]+|alias\\/[\\w/.-]+))$/, {\n message: 'must be a key id, key ARN, alias name or alias ARN',\n })\n .optional(),\n })\n )\n .default([]),\n});\n\n/** Parameter Store's name alphabet: a plain name or a `/`-separated path. */\nconst PARAMETER_NAME = /^[A-Za-z0-9_.\\-/]{1,2048}$/;\n\nconst ssmSchema = z.strictObject({\n /** Parameter name -> its value and type (String unless given). */\n parameters: z\n .record(\n z.string(),\n z.strictObject({\n value: z.string(),\n type: z.enum(PARAMETER_TYPES).default('String'),\n })\n )\n .superRefine((parameters, ctx) => {\n for (const name of Object.keys(parameters)) {\n if (!PARAMETER_NAME.test(name)) {\n ctx.addIssue({ code: 'custom', path: [name], message: 'a parameter name is 1-2048 letters, digits and _.-/' });\n }\n }\n }),\n});\n\nexport const awsConfigSchema = z\n .strictObject({\n /** Regions whose service endpoints are intercepted. */\n regions: z\n .array(z.string().regex(REGION, 'must be an AWS region such as us-east-1 (China regions are not emulated)'))\n .min(1)\n .default(['us-east-1']),\n secrets_manager: secretsManagerSchema.optional(),\n kms: kmsSchema.optional(),\n ssm: ssmSchema.optional(),\n })\n .refine((config) => declaredServices(config).length > 0, {\n message: 'declare at least one service: secrets_manager, kms, ssm',\n });\n\n/** The config as a definition writes it. */\nexport type AwsConfigInput = z.input<typeof awsConfigSchema>;\n/** The config with defaults applied. */\nexport type AwsConfig = z.output<typeof awsConfigSchema>;\n\n/** The services a config declares, in endpoint-prefix form. */\nexport function declaredServices(config: { secrets_manager?: unknown; kms?: unknown; ssm?: unknown }): AwsService[] {\n const sections: Array<[unknown, AwsService]> = [\n [config.secrets_manager, 'secretsmanager'],\n [config.kms, 'kms'],\n [config.ssm, 'ssm'],\n ];\n return sections.filter(([section]) => section !== undefined).map(([, service]) => service);\n}\n","/**\n * The AWS JSON 1.1 wire protocol shared by every service the `aws` plugin\n * emulates: which service and region a request is for (from its host), the\n * operation it calls (from `X-Amz-Target`), and AWS-shaped success and error\n * responses. Requests are never signature-checked: any credentials work.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport type { EmulationRequest, EmulationResponse } from '../../plugin.js';\n\n/** The account id in every emulated ARN (no real account has it). */\nexport const ACCOUNT_ID = '000000000000';\n\n/** The services the plugin can emulate, by their endpoint prefix (`<service>.<region>.amazonaws.com`). */\nexport type AwsService = 'secretsmanager' | 'kms' | 'ssm';\n\n/** A region name in the standard (`.amazonaws.com`) or GovCloud partitions; China's `.amazonaws.com.cn` hosts are not emulated. */\nexport const REGION = /^(?!cn-)[a-z]{2}(-[a-z]+)+-\\d+$/;\n\nconst HOST = /^([a-z0-9-]+)\\.([a-z0-9-]+)\\.amazonaws\\.com$/;\n\n/** The service endpoint host of `service` in `region`. */\nexport function serviceHost(service: AwsService, region: string): string {\n return `${service}.${region}.amazonaws.com`;\n}\n\nconst BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;\n\n/** Whether `value` is standard, padded base64 (the JSON protocols' blob encoding). */\nexport function isBase64(value: string): boolean {\n return BASE64.test(value);\n}\n\n/** The ARN partition of a region. */\nexport function partition(region: string): string {\n return region.startsWith('us-gov-') ? 'aws-us-gov' : 'aws';\n}\n\n/** The region of a request to `<service>.<region>.amazonaws.com`, or null for another host. */\nexport function requestRegion(req: EmulationRequest, service: AwsService): string | null {\n const match = HOST.exec(req.url.hostname.toLowerCase());\n return match && match[1] === service ? match[2]! : null;\n}\n\n/** The operation an `X-Amz-Target: <prefix>.<Operation>` header names, or null when it names another prefix. */\nexport function targetOperation(req: EmulationRequest, prefix: string): string | null {\n const target = req.headers['x-amz-target'] ?? '';\n return target.startsWith(`${prefix}.`) ? target.slice(prefix.length + 1) : null;\n}\n\nfunction headers(): Record<string, string> {\n return { 'content-type': 'application/x-amz-json-1.1', 'x-amzn-requestid': crypto.randomUUID() };\n}\n\n/**\n * A 200 JSON 1.1 response. Its content type keeps it out of the recorder's\n * response previews (JSON only), and `SecretString` is a credential key there\n * anyway, so a served value is never recorded.\n */\nexport function awsOk(body: object): EmulationResponse {\n return { status: 200, headers: headers(), body: JSON.stringify(body) };\n}\n\n/** A 400 AWS JSON 1.1 error: `__type` names the exception, as the SDKs expect; `messageKey` is the service's own casing. */\nexport function awsError(type: string, message: string, messageKey: 'Message' | 'message'): EmulationResponse {\n return {\n status: 400,\n headers: { ...headers(), 'x-amzn-errortype': type },\n body: JSON.stringify({ __type: type, [messageKey]: message }),\n };\n}\n\n/** The request's JSON object body, or null when it is not one. */\nexport function jsonBody(req: EmulationRequest): Record<string, unknown> | null {\n try {\n const parsed: unknown = JSON.parse(req.body ?? '{}');\n return typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed) ? (parsed as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n}\n\n/** A stable hex digest of `parts`, for ids that must not change across copies of a sandbox. */\nexport function stableHex(...parts: string[]): string {\n return crypto.createHash('sha256').update(parts.join('\\0')).digest('hex');\n}\n\n/** A stable UUID-shaped id derived from `parts`. */\nexport function stableUuid(...parts: string[]): string {\n const hex = stableHex(...parts);\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;\n}\n\n/** A request's `MaxResults` within [1, max], defaulting to max; null when out of range. */\nexport function maxResults(raw: unknown, max: number): number | null {\n if (raw === undefined) return max;\n return typeof raw === 'number' && Number.isInteger(raw) && raw >= 1 && raw <= max ? raw : null;\n}\n\n/** One page of `items` from an opaque `NextToken`; null when the token is not one this emulator issued. */\nexport function paginate<T>(\n items: T[],\n maxResults: number,\n nextToken: unknown\n): { page: T[]; nextToken?: string } | null {\n let start = 0;\n if (nextToken !== undefined) {\n const text = typeof nextToken === 'string' ? Buffer.from(nextToken, 'base64url').toString('utf8') : '';\n const decoded = /^\\d+$/.test(text) ? Number(text) : NaN;\n if (!(decoded > 0 && decoded <= items.length)) return null;\n start = decoded;\n }\n const end = start + maxResults;\n return {\n page: items.slice(start, end),\n ...(end < items.length ? { nextToken: Buffer.from(String(end), 'utf8').toString('base64url') } : {}),\n };\n}\n","/**\n * AWS Systems Manager Parameter Store, read-only: the parameters a definition\n * seeds, served by `GetParameter`, `GetParameters`, `GetParametersByPath` and\n * `DescribeParameters` with the field names and types of the real API. Each\n * parameter has version 1. A SecureString's value is returned only with\n * `WithDecryption: true`; without it the value is an opaque base64 stand-in\n * for KMS ciphertext that never encodes the value. Writes (`PutParameter`,\n * ...), parameter filters on reads, the deprecated `Filters` of\n * DescribeParameters, and version or label selectors (`name:1`) are not\n * emulated: 501 in Sandboxes v2, rather than an approximate answer. A 501 is\n * recorded with its headers (`X-Amz-Target` names the operation) and no body.\n *\n * @module\n */\n\nimport type { EmulationRequest, EmulationResponse } from '../../plugin.js';\nimport type { AwsConfig } from './config.js';\nimport { ACCOUNT_ID, awsError, awsOk, jsonBody, maxResults, paginate, partition, requestRegion, stableHex, targetOperation } from './protocol.js';\nimport type { AwsCtx } from './types.js';\n\n/** The parameter types, shared with the config schema and the `parameters` operation. */\nexport const PARAMETER_TYPES = ['String', 'StringList', 'SecureString'] as const;\ntype ParameterType = (typeof PARAMETER_TYPES)[number];\n\n/** Every seeded parameter has one version. */\nexport const PARAMETER_VERSION = 1;\n\ninterface SeededParameter {\n name: string;\n type: ParameterType;\n value: string;\n /** How many times the app has read this parameter's value. */\n reads: number;\n}\n\nexport interface SsmState {\n /** By name, in the order the definition declares them. */\n parameters: Map<string, SeededParameter>;\n}\n\n/** The key SSM names for a SecureString encrypted with the account's default key. */\nconst DEFAULT_SECURE_KEY = 'alias/aws/ssm';\n\nexport function initSsm(section: NonNullable<AwsConfig['ssm']>): SsmState {\n const parameters = new Map<string, SeededParameter>();\n for (const [name, { value, type }] of Object.entries(section.parameters)) {\n parameters.set(name, { name, type, value, reads: 0 });\n }\n return { parameters };\n}\n\nexport function parameterArn(parameter: SeededParameter, region: string): string {\n const path = parameter.name.startsWith('/') ? parameter.name.slice(1) : parameter.name;\n return `arn:${partition(region)}:ssm:${region}:${ACCOUNT_ID}:parameter/${path}`;\n}\n\n/** A parameter by name or ARN, in `region`. */\nfunction findParameter(state: SsmState, region: string, id: string): SeededParameter | undefined {\n if (!id.startsWith('arn:')) return state.parameters.get(id);\n for (const parameter of state.parameters.values()) {\n if (parameterArn(parameter, region) === id) return parameter;\n }\n return undefined;\n}\n\nconst notFound = (name: string) => awsError('ParameterNotFound', `Parameter ${name} not found.`, 'message');\nconst validation = (message: string) => awsError('ValidationException', message, 'message');\n\n/** The `Parameter` shape GetParameter(s) and GetParametersByPath return. */\nfunction parameterValue(parameter: SeededParameter, region: string, withDecryption: boolean, createdDate: number) {\n parameter.reads += 1;\n const hidden = parameter.type === 'SecureString' && !withDecryption;\n return {\n Name: parameter.name,\n Type: parameter.type,\n Value: hidden ? Buffer.from(stableHex('ssm-securestring', parameter.name), 'hex').toString('base64') : parameter.value,\n Version: PARAMETER_VERSION,\n LastModifiedDate: createdDate,\n ARN: parameterArn(parameter, region),\n DataType: 'text',\n };\n}\n\nfunction withDecryption(body: Record<string, unknown>): boolean {\n return body.WithDecryption === true;\n}\n\nconst invalidToken = () => awsError('InvalidNextToken', 'The specified token is not valid.', 'message');\n\nfunction getParameter(state: SsmState, region: string, body: Record<string, unknown>, createdDate: number) {\n if (typeof body.Name !== 'string' || body.Name === '') return validation('Name is required.');\n const parameter = findParameter(state, region, body.Name);\n if (!parameter) return notFound(body.Name);\n return awsOk({ Parameter: parameterValue(parameter, region, withDecryption(body), createdDate) });\n}\n\nfunction getParameters(state: SsmState, region: string, body: Record<string, unknown>, createdDate: number) {\n const names = body.Names;\n if (!Array.isArray(names) || names.length === 0 || names.length > 10 || !names.every((name) => typeof name === 'string')) {\n return validation('Names must be a list of 1 to 10 parameter names.');\n }\n const parameters = [];\n const invalid = [];\n for (const name of names as string[]) {\n const parameter = findParameter(state, region, name);\n if (parameter) parameters.push(parameterValue(parameter, region, withDecryption(body), createdDate));\n else invalid.push(name);\n }\n return awsOk({ Parameters: parameters, InvalidParameters: invalid });\n}\n\n/** Whether `name` is under `path`: one level below it, or any depth when `recursive`. */\nfunction underPath(name: string, path: string, recursive: boolean): boolean {\n const prefix = path.endsWith('/') ? path : `${path}/`;\n if (!name.startsWith(prefix)) return false;\n return recursive || !name.slice(prefix.length).includes('/');\n}\n\nfunction getParametersByPath(state: SsmState, region: string, body: Record<string, unknown>, createdDate: number) {\n if (typeof body.Path !== 'string' || !body.Path.startsWith('/')) return validation('Path must begin with \"/\".');\n const max = maxResults(body.MaxResults, 10);\n if (max === null) return validation('MaxResults must be between 1 and 10.');\n const path = body.Path;\n const matching = [...state.parameters.values()].filter((parameter) => underPath(parameter.name, path, body.Recursive === true));\n const paged = paginate(matching, max, body.NextToken);\n if (!paged) return invalidToken();\n return awsOk({\n Parameters: paged.page.map((parameter) => parameterValue(parameter, region, withDecryption(body), createdDate)),\n ...(paged.nextToken ? { NextToken: paged.nextToken } : {}),\n });\n}\n\ntype StringFilter = { Key: string; Option?: string; Values?: string[] };\n\n/**\n * Whether a parameter passes `DescribeParameters`' `ParameterFilters`: `Name`\n * (Equals or BeginsWith), `Type` (Equals) and `Path` (OneLevel or Recursive).\n * Null when a filter uses anything else, so the call is reported unemulated\n * rather than answered wrongly.\n */\nfunction describeMatcher(body: Record<string, unknown>): ((parameter: SeededParameter) => boolean) | null {\n if (body.Filters !== undefined) return null;\n const checks: Array<(parameter: SeededParameter) => boolean> = [];\n const add = (filter: StringFilter): boolean => {\n const values = filter.Values ?? [];\n const option = filter.Option ?? (filter.Key === 'Path' ? 'OneLevel' : 'Equals');\n if (filter.Key === 'Name' && (option === 'Equals' || option === 'BeginsWith')) {\n checks.push((p) => values.some((value) => (option === 'Equals' ? p.name === value : p.name.startsWith(value))));\n } else if (filter.Key === 'Type' && option === 'Equals') {\n checks.push((p) => values.includes(p.type));\n } else if (filter.Key === 'Path' && (option === 'OneLevel' || option === 'Recursive')) {\n checks.push((p) => values.some((value) => underPath(p.name, value, option === 'Recursive')));\n } else return false;\n return true;\n };\n const raw = body.ParameterFilters ?? [];\n if (!Array.isArray(raw)) return null;\n for (const entry of raw) {\n if (typeof entry !== 'object' || entry === null) return null;\n const { Key, Option, Values } = entry as Record<string, unknown>;\n if (typeof Key !== 'string' || (Values !== undefined && !(Array.isArray(Values) && Values.every((v) => typeof v === 'string')))) return null;\n const filter: StringFilter = {\n Key,\n ...(typeof Option === 'string' ? { Option } : {}),\n ...(Values !== undefined ? { Values: Values as string[] } : {}),\n };\n if (!add(filter)) return null;\n }\n return (parameter) => checks.every((check) => check(parameter));\n}\n\nfunction describeParameters(state: SsmState, region: string, body: Record<string, unknown>, createdDate: number) {\n const matches = describeMatcher(body);\n if (!matches) return null;\n const max = maxResults(body.MaxResults, 50);\n if (max === null) return validation('MaxResults must be between 1 and 50.');\n const paged = paginate([...state.parameters.values()].filter(matches), max, body.NextToken);\n if (!paged) return invalidToken();\n return awsOk({\n Parameters: paged.page.map((parameter) => ({\n Name: parameter.name,\n ARN: parameterArn(parameter, region),\n Type: parameter.type,\n ...(parameter.type === 'SecureString' ? { KeyId: DEFAULT_SECURE_KEY } : {}),\n LastModifiedDate: createdDate,\n Version: PARAMETER_VERSION,\n Tier: 'Standard',\n Policies: [],\n DataType: 'text',\n })),\n ...(paged.nextToken ? { NextToken: paged.nextToken } : {}),\n });\n}\n\nconst OPERATIONS = {\n GetParameter: getParameter,\n GetParameters: getParameters,\n GetParametersByPath: getParametersByPath,\n DescribeParameters: describeParameters,\n} as const;\n\n/** `POST /` on an SSM endpoint. Null (not emulated) for another host, any other operation, or an unsupported filter. */\nexport function handleSsm(req: EmulationRequest, ctx: AwsCtx): EmulationResponse | null {\n const state = ctx.state.ssm;\n const region = requestRegion(req, 'ssm');\n const operation = targetOperation(req, 'AmazonSSM');\n if (!state || !region || !operation || !Object.hasOwn(OPERATIONS, operation)) return null;\n const body = jsonBody(req);\n if (!body) return awsError('SerializationException', 'The request body is not a JSON object.', 'message');\n // Filters on reads and `name:version` / `name:label` selectors are not emulated: 501, not a wrong answer.\n if (body.ParameterFilters !== undefined && operation !== 'DescribeParameters') return null;\n const names = [body.Name, ...(Array.isArray(body.Names) ? body.Names : [])];\n if (names.some((name) => typeof name === 'string' && !name.startsWith('arn:') && name.includes(':'))) return null;\n return OPERATIONS[operation as keyof typeof OPERATIONS](state, region, body, ctx.state.createdDate);\n}\n","/**\n * AWS KMS, minimal. `Decrypt` answers the ciphertext a definition seeds (made\n * by real KMS, which only a seeded mapping can answer), and `Encrypt`,\n * `Decrypt` and `GenerateDataKey` work under one emulated symmetric key, so an\n * app that encrypts at run time round-trips. Any other operation is not\n * emulated: 501 in Sandboxes v2.\n *\n * The emulated key is internal, never configured: derived (HKDF-SHA256) from\n * the emulation CA's private key, which the emulator creates at its first\n * start, before the ready snapshot is captured, and keeps root-only across\n * restarts. Every copy of a snapshot therefore has the same key and decrypts\n * what the snapshot's seeds or another copy encrypted. Any KeyId (key id, key\n * ARN, alias name or ARN) is accepted and answered as a key ARN.\n *\n * Emulated ciphertext is `cfkms1 | key ARN length (2 bytes) | key ARN | IV\n * (12) | tag (16) | AES-256-GCM ciphertext`, with the key ARN (length-prefixed)\n * and the encryption context as additional authenticated data, so decrypting\n * with a different context fails as on AWS (InvalidCiphertextException).\n * Seeded ciphertext was made by real KMS under a context the emulator cannot\n * check, so its Decrypt ignores EncryptionContext.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport { existsSync, readFileSync } from 'node:fs';\nimport type { EmulationRequest, EmulationResponse } from '../../plugin.js';\nimport { CA_KEY_FILE } from '../../service/tls.js';\nimport type { AwsConfig } from './config.js';\nimport { ACCOUNT_ID, awsError, awsOk, isBase64, jsonBody, partition, requestRegion, stableUuid, targetOperation } from './protocol.js';\nimport type { AwsCtx } from './types.js';\n\nconst MAGIC = Buffer.from('cfkms1', 'utf8');\nconst ALGORITHM = 'SYMMETRIC_DEFAULT';\nconst IV_BYTES = 12;\nconst TAG_BYTES = 16;\nconst MAX_PLAINTEXT_BYTES = 4096;\nconst MAX_DATA_KEY_BYTES = 1024;\n\ninterface SeededCiphertext {\n plaintext: Buffer;\n /** The key the seed names, as given; null when it names none. */\n keyId: string | null;\n}\n\nexport interface KmsState {\n /** Seeded ciphertext, as canonical base64 -> what it decrypts to. */\n seeded: Map<string, SeededCiphertext>;\n /** The emulated key, derived on first use (`masterKey`). */\n masterKey: Buffer | null;\n}\n\n/**\n * The state for a config's `kms` section. The config was parsed by the\n * plugin's schema with every reference resolved, so both blobs are base64.\n */\nexport function initKms(section: NonNullable<AwsConfig['kms']>): KmsState {\n const seeded = new Map<string, SeededCiphertext>();\n for (const entry of section.decrypt) {\n seeded.set(Buffer.from(entry.ciphertext, 'base64').toString('base64'), { plaintext: Buffer.from(entry.plaintext, 'base64'), keyId: entry.key_id ?? null });\n }\n return { seeded, masterKey: null };\n}\n\n/** The emulated key: HKDF of the CA's private key, so it lives exactly as long as the CA (see the module doc). */\nfunction deriveKey(): Buffer {\n // The emulator creates the CA before it serves anything; without one (a host that runs no CA) KMS cannot work.\n if (!existsSync(CA_KEY_FILE)) throw new Error(`KMS emulation needs the emulation CA key at ${CA_KEY_FILE}`);\n const caKey = readFileSync(CA_KEY_FILE);\n return Buffer.from(crypto.hkdfSync('sha256', caKey, 'cofactor-emulation', 'aws-kms-key', 32));\n}\n\n/** A KeyId (key id, key ARN, alias name or alias ARN) as the key ARN AWS answers with; null for a malformed ARN. */\nfunction keyArn(keyId: string, region: string): string | null {\n if (keyId.startsWith('arn:')) {\n if (/^arn:[a-z-]+:kms:[a-z0-9-]+:\\d{12}:key\\/[^/]+$/.test(keyId)) return keyId;\n const alias = /^arn:[a-z-]+:kms:[a-z0-9-]+:\\d{12}:(alias\\/.+)$/.exec(keyId)?.[1];\n return alias === undefined ? null : keyArn(alias, region);\n }\n // An alias has no key id of its own here: it names a stable emulated one.\n const id = keyId.startsWith('alias/') ? stableUuid('kms-alias', keyId) : keyId;\n return `arn:${partition(region)}:kms:${region}:${ACCOUNT_ID}:key/${id}`;\n}\n\n/** The encryption context as additional authenticated data: its entries sorted by key. */\nfunction contextAad(context: unknown): Buffer {\n const entries = typeof context === 'object' && context !== null ? Object.entries(context).sort(([a], [b]) => (a < b ? -1 : 1)) : [];\n return Buffer.from(JSON.stringify(entries), 'utf8');\n}\n\nfunction seal(key: Buffer, arn: string, plaintext: Buffer, context: unknown): Buffer {\n const iv = crypto.randomBytes(IV_BYTES);\n const arnBytes = Buffer.from(arn, 'utf8');\n const length = Buffer.alloc(2);\n length.writeUInt16BE(arnBytes.length);\n const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);\n cipher.setAAD(Buffer.concat([length, arnBytes, contextAad(context)]));\n const sealed = Buffer.concat([cipher.update(plaintext), cipher.final()]);\n return Buffer.concat([MAGIC, length, arnBytes, iv, cipher.getAuthTag(), sealed]);\n}\n\n/** The key ARN and plaintext of emulated ciphertext, or null when it is not ours or does not authenticate. */\nfunction open(key: Buffer, blob: Buffer, context: unknown): { arn: string; plaintext: Buffer } | null {\n if (blob.length < MAGIC.length + 2 || !blob.subarray(0, MAGIC.length).equals(MAGIC)) return null;\n const arnLength = blob.readUInt16BE(MAGIC.length);\n const arnStart = MAGIC.length + 2;\n const ivStart = arnStart + arnLength;\n const sealedStart = ivStart + IV_BYTES + TAG_BYTES;\n if (blob.length < sealedStart) return null;\n const arnBytes = blob.subarray(arnStart, ivStart);\n try {\n const decipher = crypto.createDecipheriv('aes-256-gcm', key, blob.subarray(ivStart, ivStart + IV_BYTES));\n decipher.setAAD(Buffer.concat([blob.subarray(MAGIC.length, arnStart), arnBytes, contextAad(context)]));\n decipher.setAuthTag(blob.subarray(ivStart + IV_BYTES, sealedStart));\n const plaintext = Buffer.concat([decipher.update(blob.subarray(sealedStart)), decipher.final()]);\n return { arn: arnBytes.toString('utf8'), plaintext };\n } catch {\n // A failed GCM authentication is exactly AWS's InvalidCiphertextException (wrong context, tampered blob).\n return null;\n }\n}\n\nconst invalidCiphertext = () => awsError('InvalidCiphertextException', 'The ciphertext is invalid or was not encrypted under this emulated key.', 'message');\nconst incorrectKey = () =>\n awsError('IncorrectKeyException', 'The key ID in the request does not identify a CMK that can perform this operation.', 'message');\nconst validation = (message: string) => awsError('ValidationException', message, 'message');\n\nfunction masterKey(state: KmsState): Buffer {\n state.masterKey ??= deriveKey();\n return state.masterKey;\n}\n\nconst malformedKey = (keyId: string) => validation(`Invalid keyId ${keyId}`);\n\n/** A base64 blob field of the request, or null when it is missing or not base64. */\nfunction blobField(value: unknown): Buffer | null {\n return typeof value === 'string' && value !== '' && isBase64(value) ? Buffer.from(value, 'base64') : null;\n}\n\nfunction decrypt(state: KmsState, region: string, body: Record<string, unknown>): EmulationResponse {\n const blob = blobField(body.CiphertextBlob);\n if (!blob) return validation('CiphertextBlob must be base64-encoded ciphertext.');\n const requested = typeof body.KeyId === 'string' ? keyArn(body.KeyId, region) : null;\n if (typeof body.KeyId === 'string' && requested === null) return malformedKey(body.KeyId);\n const seeded = state.seeded.get(blob.toString('base64'));\n if (seeded) {\n // A seed without a KeyId answers with a stable emulated key's ARN and matches any requested key.\n // The schema accepts only a well-formed key_id, so keyArn cannot return null for it.\n const arn = keyArn(seeded.keyId ?? stableUuid('kms-key', 'default'), region)!;\n if (requested !== null && seeded.keyId !== null && requested !== arn) return incorrectKey();\n return awsOk({ KeyId: arn, Plaintext: seeded.plaintext.toString('base64'), EncryptionAlgorithm: ALGORITHM });\n }\n const opened = open(masterKey(state), blob, body.EncryptionContext);\n if (!opened) return invalidCiphertext();\n if (requested !== null && requested !== opened.arn) return incorrectKey();\n return awsOk({ KeyId: opened.arn, Plaintext: opened.plaintext.toString('base64'), EncryptionAlgorithm: ALGORITHM });\n}\n\nfunction encrypt(state: KmsState, region: string, body: Record<string, unknown>): EmulationResponse {\n if (typeof body.KeyId !== 'string' || body.KeyId === '') return validation('KeyId is required.');\n const plaintext = blobField(body.Plaintext);\n if (!plaintext || plaintext.length > MAX_PLAINTEXT_BYTES) return validation('Plaintext must be 1 to 4096 base64-encoded bytes.');\n const arn = keyArn(body.KeyId, region);\n if (arn === null) return malformedKey(body.KeyId);\n return awsOk({\n CiphertextBlob: seal(masterKey(state), arn, plaintext, body.EncryptionContext).toString('base64'),\n KeyId: arn,\n EncryptionAlgorithm: ALGORITHM,\n });\n}\n\nfunction generateDataKey(state: KmsState, region: string, body: Record<string, unknown>): EmulationResponse {\n if (typeof body.KeyId !== 'string' || body.KeyId === '') return validation('KeyId is required.');\n const bytes =\n body.KeySpec === 'AES_256' ? 32 : body.KeySpec === 'AES_128' ? 16 : typeof body.NumberOfBytes === 'number' ? body.NumberOfBytes : null;\n if (bytes === null || !Number.isInteger(bytes) || bytes < 1 || bytes > MAX_DATA_KEY_BYTES) {\n return validation('Please specify either number of bytes (1 to 1024) or key spec (AES_256 or AES_128).');\n }\n const arn = keyArn(body.KeyId, region);\n if (arn === null) return malformedKey(body.KeyId);\n const plaintext = crypto.randomBytes(bytes);\n return awsOk({\n CiphertextBlob: seal(masterKey(state), arn, plaintext, body.EncryptionContext).toString('base64'),\n Plaintext: plaintext.toString('base64'),\n KeyId: arn,\n });\n}\n\nconst OPERATIONS = {\n Decrypt: decrypt,\n Encrypt: encrypt,\n GenerateDataKey: generateDataKey,\n} as const;\n\n/** `POST /` on a KMS endpoint. Null (not emulated) for another host or any other operation. */\nexport function handleKms(req: EmulationRequest, ctx: AwsCtx): EmulationResponse | null {\n const state = ctx.state.kms;\n const region = requestRegion(req, 'kms');\n const operation = targetOperation(req, 'TrentService');\n if (!state || !region || !operation || !Object.hasOwn(OPERATIONS, operation)) return null;\n const body = jsonBody(req);\n if (!body) return awsError('SerializationException', 'The request body is not a JSON object.', 'message');\n return OPERATIONS[operation as keyof typeof OPERATIONS](state, region, body);\n}\n","/**\n * TLS Certificate Generation\n *\n * Generates a self-signed CA and per-domain certificates at startup.\n * The CA cert is written to a shared volume so app containers can trust it\n * via NODE_EXTRA_CA_CERTS.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport { execFileSync } from 'node:child_process';\nimport { writeFileSync, readFileSync, mkdirSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport interface TlsConfig {\n /** PEM-encoded certificate (including CA chain) */\n cert: string;\n /** PEM-encoded private key */\n key: string;\n}\n\nconst CA_DIR = '/etc/emulation';\n/**\n * The CA's private key, which the aws plugin's emulated KMS key is derived\n * from: regenerating the CA (never done; see ensureCa) would also orphan\n * every ciphertext encrypted under that key.\n */\nexport const CA_KEY_FILE = join(CA_DIR, 'ca.key');\n\nconst DOMAIN_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9]$/;\n\n/** Validate domain names to prevent injection into openssl arguments. */\nfunction validateDomains(domains: string[]): void {\n for (const domain of domains) {\n if (!DOMAIN_PATTERN.test(domain) || domain.length > 253) {\n throw new Error(`Invalid domain for TLS cert generation: ${domain}`);\n }\n }\n}\n\nconst EXEC_OPTS = { stdio: 'pipe' as const, timeout: 30_000 };\n\n/**\n * Create the self-signed CA in `caDir`, or reuse the one already on disk.\n * Runs at emulator start whether or not any domain needs a certificate: the\n * supervisor treats `ca.crt` as part of \"healthy\", and an `oidc`-only copy\n * has no domains.\n *\n * The CA must survive an emulator restart: app containers read\n * `NODE_EXTRA_CA_CERTS` once at their own startup, so a rotated CA would\n * silently break TLS trust for any app container that started before the\n * restart. Only the leaf (server) cert, which is re-issued on every start,\n * is allowed to change.\n *\n * `caDir` defaults to the production shared-volume path; overridable so\n * tests can point at a scratch directory instead of `/etc/emulation`\n * (which requires root).\n */\nexport function ensureCa(caDir: string = CA_DIR): { caCertPath: string; caKeyPath: string } {\n mkdirSync(caDir, { recursive: true });\n const caCertPath = join(caDir, 'ca.crt');\n const caKeyPath = join(caDir, 'ca.key');\n\n if (!(existsSync(caCertPath) && existsSync(caKeyPath))) {\n const caKey = crypto.generateKeyPairSync('rsa', { modulusLength: 2048 });\n const caKeyPem = caKey.privateKey.export({ type: 'pkcs8', format: 'pem' }) as string;\n writeFileSync(caKeyPath, caKeyPem, { mode: 0o600 });\n\n execFileSync('openssl', [\n 'req', '-new', '-x509',\n '-key', caKeyPath,\n '-out', caCertPath,\n '-days', '365',\n '-subj', '/CN=Emulation Proxy CA/O=Canary',\n '-addext', 'basicConstraints=critical,CA:TRUE',\n ], EXEC_OPTS);\n }\n\n return { caCertPath, caKeyPath };\n}\n\n/**\n * Generate domain certificates signed by the CA (created or reused through\n * {@link ensureCa}) for the given domains. Only the leaf cert is new on each call.\n */\nexport function generateTlsCerts(domains: string[], caDir: string = CA_DIR): TlsConfig {\n validateDomains(domains);\n const { caCertPath, caKeyPath } = ensureCa(caDir);\n\n // Generate server key + cert signed by CA for all domains\n const serverKey = crypto.generateKeyPairSync('rsa', { modulusLength: 2048 });\n const serverKeyPem = serverKey.privateKey.export({ type: 'pkcs8', format: 'pem' }) as string;\n\n const serverKeyPath = join(caDir, 'server.key');\n const serverCsrPath = join(caDir, 'server.csr');\n const serverCertPath = join(caDir, 'server.crt');\n const extPath = join(caDir, 'server.ext');\n\n writeFileSync(serverKeyPath, serverKeyPem, { mode: 0o600 });\n\n // Build SAN extension file\n const sanEntries = domains.map((d, i) => `DNS.${i + 1} = ${d}`).join('\\n');\n const extContent = [\n 'authorityKeyIdentifier=keyid,issuer',\n 'basicConstraints=CA:FALSE',\n 'keyUsage=digitalSignature,keyEncipherment',\n 'extendedKeyUsage=serverAuth',\n 'subjectAltName=@alt_names',\n '',\n '[alt_names]',\n sanEntries,\n ].join('\\n');\n writeFileSync(extPath, extContent);\n\n // Generate CSR\n execFileSync('openssl', [\n 'req', '-new',\n '-key', serverKeyPath,\n '-out', serverCsrPath,\n '-subj', `/CN=${domains[0]}`,\n ], EXEC_OPTS);\n\n // Sign with CA\n execFileSync('openssl', [\n 'x509', '-req',\n '-in', serverCsrPath,\n '-CA', caCertPath,\n '-CAkey', caKeyPath,\n '-CAcreateserial',\n '-out', serverCertPath,\n '-days', '365',\n '-extfile', extPath,\n ], EXEC_OPTS);\n\n const caCert = readFileSync(caCertPath, 'utf-8');\n const serverCert = readFileSync(serverCertPath, 'utf-8');\n\n return {\n cert: serverCert + '\\n' + caCert,\n key: serverKeyPem,\n };\n}\n","/**\n * AWS Secrets Manager, read-only: the secrets a definition seeds, served by\n * `GetSecretValue`, `BatchGetSecretValue`, `DescribeSecret` and `ListSecrets`\n * with the field names and types of the real API. Each secret has one version,\n * staged `AWSCURRENT`. Writes (`CreateSecret`, `PutSecretValue`, ...) are not\n * emulated: like any unimplemented call they answer 501 in Sandboxes v2, which\n * never passes through to the real service.\n *\n * A secret's ARN, version id and ARN suffix derive from its name only, so they\n * are the same in every copy of a sandbox and across restarts.\n *\n * @module\n */\n\nimport type { EmulationRequest, EmulationResponse } from '../../plugin.js';\nimport type { AwsConfig } from './config.js';\nimport {\n ACCOUNT_ID,\n awsError,\n awsOk,\n jsonBody,\n maxResults,\n paginate,\n partition,\n requestRegion,\n stableHex,\n stableUuid,\n targetOperation,\n} from './protocol.js';\nimport type { AwsCtx } from './types.js';\n\nconst NOT_FOUND = \"Secrets Manager can't find the specified secret.\";\nconst CURRENT = 'AWSCURRENT';\nconst ARN = /^arn:([a-z-]+):secretsmanager:([a-z0-9-]+):(\\d{12}):secret:(.+)$/;\nconst FILTER_KEYS = new Set(['description', 'name', 'tag-key', 'tag-value', 'primary-region', 'owning-service', 'all']);\n\nexport interface SeededSecret {\n name: string;\n /** The six characters Secrets Manager appends to a secret's name in its ARN. */\n suffix: string;\n versionId: string;\n secretString: string;\n /** How many times the app has read this secret's value. */\n reads: number;\n}\n\nexport interface SecretsManagerState {\n /** By name, in the order the definition declares them. */\n secrets: Map<string, SeededSecret>;\n}\n\n/** The state for a config's `secrets_manager` section: each value as its SecretString. */\nexport function initSecretsManager(section: NonNullable<AwsConfig['secrets_manager']>): SecretsManagerState {\n const secrets = new Map<string, SeededSecret>();\n for (const [name, value] of Object.entries(section.secrets)) {\n secrets.set(name, {\n name,\n suffix: stableHex('secret-suffix', name).slice(0, 6),\n versionId: stableUuid('secret-version', name),\n secretString: typeof value === 'string' ? value : JSON.stringify(value),\n reads: 0,\n });\n }\n return { secrets };\n}\n\nexport function secretArn(secret: SeededSecret, region: string): string {\n return `arn:${partition(region)}:secretsmanager:${region}:${ACCOUNT_ID}:secret:${secret.name}-${secret.suffix}`;\n}\n\n/** A secret by name, full ARN, or partial ARN (without the suffix), in `region`. */\nfunction findSecret(state: SecretsManagerState, region: string, secretId: string): SeededSecret | undefined {\n const arn = ARN.exec(secretId);\n if (!arn) return state.secrets.get(secretId);\n const [, arnPartition, arnRegion, account, rest] = arn;\n if (arnPartition !== partition(region) || arnRegion !== region || account !== ACCOUNT_ID) return undefined;\n for (const secret of state.secrets.values()) {\n if (`${secret.name}-${secret.suffix}` === rest) return secret;\n }\n return state.secrets.get(rest!);\n}\n\nconst notFound = (message = NOT_FOUND) => awsError('ResourceNotFoundException', message, 'Message');\nconst invalidParameter = (message: string) => awsError('InvalidParameterException', message, 'Message');\n\nfunction secretValue(secret: SeededSecret, region: string, createdDate: number) {\n secret.reads += 1;\n return {\n ARN: secretArn(secret, region),\n Name: secret.name,\n VersionId: secret.versionId,\n SecretString: secret.secretString,\n VersionStages: [CURRENT],\n CreatedDate: createdDate,\n };\n}\n\ntype Filter = { Key: string; Values: string[] };\n\n/** The request's `Filters`, or an error response when they are malformed. */\nfunction parseFilters(raw: unknown): Filter[] | EmulationResponse {\n if (raw === undefined) return [];\n if (!Array.isArray(raw)) return invalidParameter('Filters must be a list.');\n const filters: Filter[] = [];\n for (const entry of raw) {\n const key = typeof entry === 'object' && entry !== null ? (entry as Record<string, unknown>).Key : undefined;\n const values = typeof entry === 'object' && entry !== null ? (entry as Record<string, unknown>).Values : undefined;\n if (typeof key !== 'string' || !FILTER_KEYS.has(key)) return invalidParameter(`Invalid filter key: ${String(key)}`);\n if (!Array.isArray(values) || !values.every((value) => typeof value === 'string')) {\n return invalidParameter('Filter values must be a list of strings.');\n }\n filters.push({ Key: key, Values: values });\n }\n return filters;\n}\n\n/**\n * Whether a secret passes every filter (filters AND, a filter's values OR). A\n * value starting with `!` negates it. `name` is a case-sensitive prefix match;\n * `all` matches when every word of the value appears in the name, ignoring\n * case. A seeded secret has no description, tags, primary region or owning\n * service, so those keys match nothing (and their `!` negations match every\n * secret, as \"not tagged X\" does on AWS).\n */\nfunction matchesFilters(secret: SeededSecret, filters: Filter[]): boolean {\n return filters.every((filter) =>\n filter.Values.some((raw) => {\n const negated = raw.startsWith('!');\n const value = negated ? raw.slice(1) : raw;\n let matches = false;\n if (filter.Key === 'name') matches = secret.name.startsWith(value);\n else if (filter.Key === 'all') {\n const name = secret.name.toLowerCase();\n matches = value.toLowerCase().split(/\\s+/).filter(Boolean).every((word) => name.includes(word));\n }\n return negated ? !matches : matches;\n })\n );\n}\n\nfunction getSecretValue(state: SecretsManagerState, region: string, body: Record<string, unknown>, createdDate: number) {\n if (typeof body.SecretId !== 'string' || body.SecretId === '') return invalidParameter('You must provide a SecretId.');\n const secret = findSecret(state, region, body.SecretId);\n if (!secret) return notFound();\n if (body.VersionId !== undefined && body.VersionId !== secret.versionId) {\n return notFound(`Secrets Manager can't find the specified secret value for VersionId: ${String(body.VersionId)}`);\n }\n if (body.VersionStage !== undefined && body.VersionStage !== CURRENT) {\n return notFound(`Secrets Manager can't find the specified secret value for staging label: ${String(body.VersionStage)}`);\n }\n return awsOk(secretValue(secret, region, createdDate));\n}\n\nfunction batchGetSecretValue(state: SecretsManagerState, region: string, body: Record<string, unknown>, createdDate: number) {\n const hasList = body.SecretIdList !== undefined;\n if (hasList === (body.Filters !== undefined)) {\n return invalidParameter('Either SecretIdList or Filters must be specified, but not both.');\n }\n if (hasList) {\n const ids = body.SecretIdList;\n if (!Array.isArray(ids) || ids.length === 0 || ids.length > 20 || !ids.every((id) => typeof id === 'string')) {\n return invalidParameter('SecretIdList must be a list of 1 to 20 secret ids.');\n }\n const values = [];\n const errors = [];\n for (const id of ids as string[]) {\n const secret = findSecret(state, region, id);\n if (secret) values.push(secretValue(secret, region, createdDate));\n else errors.push({ SecretId: id, ErrorCode: 'ResourceNotFoundException', Message: NOT_FOUND });\n }\n return awsOk({ SecretValues: values, Errors: errors });\n }\n const filters = parseFilters(body.Filters);\n if (!Array.isArray(filters)) return filters;\n const max = maxResults(body.MaxResults, 20);\n if (max === null) return invalidParameter('MaxResults must be between 1 and 20.');\n const matching = [...state.secrets.values()].filter((secret) => matchesFilters(secret, filters));\n const paged = paginate(matching, max, body.NextToken);\n if (!paged) return awsError('InvalidNextTokenException', 'The NextToken value is invalid.', 'Message');\n return awsOk({\n SecretValues: paged.page.map((secret) => secretValue(secret, region, createdDate)),\n Errors: [],\n ...(paged.nextToken ? { NextToken: paged.nextToken } : {}),\n });\n}\n\nfunction describeSecret(state: SecretsManagerState, region: string, body: Record<string, unknown>, createdDate: number) {\n if (typeof body.SecretId !== 'string' || body.SecretId === '') return invalidParameter('You must provide a SecretId.');\n const secret = findSecret(state, region, body.SecretId);\n if (!secret) return notFound();\n return awsOk({\n ARN: secretArn(secret, region),\n Name: secret.name,\n CreatedDate: createdDate,\n LastChangedDate: createdDate,\n VersionIdsToStages: { [secret.versionId]: [CURRENT] },\n });\n}\n\nfunction listSecrets(state: SecretsManagerState, region: string, body: Record<string, unknown>, createdDate: number) {\n const filters = parseFilters(body.Filters);\n if (!Array.isArray(filters)) return filters;\n const max = maxResults(body.MaxResults, 100);\n if (max === null) return invalidParameter('MaxResults must be between 1 and 100.');\n const matching = [...state.secrets.values()].filter((secret) => matchesFilters(secret, filters));\n const paged = paginate(matching, max, body.NextToken);\n if (!paged) return awsError('InvalidNextTokenException', 'The NextToken value is invalid.', 'Message');\n return awsOk({\n SecretList: paged.page.map((secret) => ({\n ARN: secretArn(secret, region),\n Name: secret.name,\n CreatedDate: createdDate,\n LastChangedDate: createdDate,\n SecretVersionsToStages: { [secret.versionId]: [CURRENT] },\n })),\n ...(paged.nextToken ? { NextToken: paged.nextToken } : {}),\n });\n}\n\nconst OPERATIONS = {\n GetSecretValue: getSecretValue,\n BatchGetSecretValue: batchGetSecretValue,\n DescribeSecret: describeSecret,\n ListSecrets: listSecrets,\n} as const;\n\n/** `POST /` on a Secrets Manager endpoint. Null (not emulated) for any other operation. */\nexport function handleSecretsManager(req: EmulationRequest, ctx: AwsCtx): EmulationResponse | null {\n const state = ctx.state.secretsManager;\n const region = requestRegion(req, 'secretsmanager');\n const operation = targetOperation(req, 'secretsmanager');\n if (!state || !region || !operation || !Object.hasOwn(OPERATIONS, operation)) return null;\n const body = jsonBody(req);\n if (!body) return awsError('SerializationException', 'The request body is not a JSON object.', 'Message');\n return OPERATIONS[operation as keyof typeof OPERATIONS](state, region, body, ctx.state.createdDate);\n}\n","/**\n * Email Provider Emulation Plugin\n *\n * Emulates the HTTP send APIs of several email providers so a sandboxed app's\n * outbound mail is captured in-process instead of leaving the sandbox. One\n * plugin spans many providers; each send request normalizes into a shared\n * `CapturedEmail` shape for assertions and API-side inbox ingestion.\n *\n * Supported providers (HTTP APIs only):\n * - Amazon SES: `POST /` and SES v2 `POST /v2/email/outbound-emails`.\n * - SendGrid: `POST /v3/mail/send`.\n * - Resend: `POST /emails`.\n * - Postmark: `POST /email` and `POST /email/batch`.\n * - Mailgun: `POST /v3/:domain/messages`.\n *\n * With `mailosaur: {}` it also serves Mailosaur's read API on mailosaur.com\n * over the same captures (see `email/mailosaur.ts`), so a suite reading mail\n * through a Mailosaur SDK finds what the app sent.\n *\n * Unknown paths on these hosts pass through to the real provider.\n *\n * @module\n */\n\nimport { z } from 'zod';\nimport type { EmulationPlugin } from '../plugin.js';\nimport { emailActionInterfaces } from './email/actions.js';\nimport {\n handleMailgun,\n handlePostmarkBatch,\n handlePostmarkSingle,\n handleResend,\n handleSendgrid,\n handleSesV1,\n handleSesV2,\n} from './email/handlers.js';\nimport {\n handleDeleteAllMessages,\n handleDeleteMessage,\n handleGetMessage,\n handleGetServer,\n handleListMessages,\n handleListServers,\n handleSearchMessages,\n MAILOSAUR_API_HOST,\n} from './email/mailosaur.js';\nimport { capturedEmailSchema, emailConfigSchema, emailFixtureSchema } from './email/types.js';\nimport type { EmailCtx, EmailEmuConfig, EmailFixture, EmailState } from './email/types.js';\n\nexport { emailFixtureSchema } from './email/types.js';\nexport type {\n CapturedEmail,\n EmailEmuConfig,\n EmailFixture,\n EmailProvider,\n EmailState,\n} from './email/types.js';\n\nconst DEFAULT_SES_REGIONS = ['us-east-1'];\n\n/** Shared by the `sent-emails` controlRead (v1) and operation (v2). */\nfunction getSentEmails(ctx: EmailCtx): { emails: EmailState['sentEmails'] } {\n return { emails: ctx.state.sentEmails };\n}\n\nexport const emailPlugin: EmulationPlugin<EmailEmuConfig, EmailFixture, EmailState> = {\n id: 'email',\n name: 'Email (multi-provider)',\n version: '1.0.0',\n\n domains: (config) => {\n const sesRegions = config.sesRegions?.length ? config.sesRegions : DEFAULT_SES_REGIONS;\n return [\n 'api.sendgrid.com',\n 'api.resend.com',\n 'api.postmarkapp.com',\n 'api.mailgun.net',\n 'api.eu.mailgun.net',\n ...sesRegions.map((region) => `email.${region}.amazonaws.com`),\n ...(config.extraDomains ?? []),\n ...(config.mailosaur ? [MAILOSAUR_API_HOST] : []),\n ];\n },\n\n configSchema: emailConfigSchema,\n\n needsBrowserIntercept: false,\n\n fixtureSchema: emailFixtureSchema,\n defaultFixture: {},\n\n actionInterfaces: emailActionInterfaces,\n\n controlReads: [\n {\n path: 'sent-emails',\n handler: (_req, ctx: EmailCtx) => ({\n status: 200,\n body: getSentEmails(ctx),\n }),\n },\n ],\n\n operations: [\n {\n id: 'sent-emails',\n description: 'All emails captured since boot or last reset.',\n input: z.object({}).strict(),\n output: z.object({ emails: z.array(capturedEmailSchema) }),\n handler: (ctx: EmailCtx) => getSentEmails(ctx),\n },\n ],\n\n routes: [\n { method: 'POST', path: '/v3/mail/send', handler: handleSendgrid },\n { method: 'POST', path: '/emails', handler: handleResend },\n { method: 'POST', path: '/email', handler: handlePostmarkSingle },\n { method: 'POST', path: '/email/batch', handler: handlePostmarkBatch },\n { method: 'POST', path: '/v3/:domain/messages', handler: handleMailgun },\n { method: 'POST', path: '/v2/email/outbound-emails', handler: handleSesV2 },\n { method: 'POST', path: '/api/messages/search', handler: handleSearchMessages },\n { method: 'GET', path: '/api/messages', handler: handleListMessages },\n { method: 'DELETE', path: '/api/messages', handler: handleDeleteAllMessages },\n { method: 'GET', path: '/api/messages/:id', handler: handleGetMessage },\n { method: 'DELETE', path: '/api/messages/:id', handler: handleDeleteMessage },\n { method: 'GET', path: '/api/servers', handler: handleListServers },\n { method: 'GET', path: '/api/servers/:id', handler: handleGetServer },\n { method: 'POST', path: '/', handler: handleSesV1 },\n ],\n\n initialize(_config, _fixture, _env): EmailState {\n return { sentEmails: [], mailosaurHidden: new Set() };\n },\n};\n","/**\n * Email plugin action-interface declarations.\n *\n * @module\n */\n\nimport type { ActionInterfaceDef } from '../../plugin.js';\n\nexport const emailActionInterfaces: ActionInterfaceDef[] = [\n {\n slug: 'email-sent-messages',\n label: 'Read emails the app sent',\n description:\n 'Return the emails the app sent via any emulated provider since boot (or the last reset), for assertions.',\n inputSchema: { type: 'object', properties: {} },\n outputSchema: {\n type: 'object',\n properties: {\n emails: {\n type: 'array',\n description: 'Captured emails: { id, provider, from, to[], subject, text, html, ... }',\n },\n },\n },\n scaffoldScript: `# Read emails the app sent to the emulated providers.\ncurl -sf \"$EMULATION_BASE_URL/plugins/email/sent-emails\" \\\\\n -H \"Authorization: Bearer $EMULATION_CONTROL_TOKEN\"`,\n },\n {\n slug: 'email-reset',\n label: 'Clear captured emails',\n description: 'Reset the email emulator, discarding all captured emails.',\n inputSchema: { type: 'object', properties: {} },\n outputSchema: { type: 'object', properties: { ok: { type: 'boolean' } } },\n scaffoldScript: `# Discard all captured emails.\ncurl -sf -X POST \"$EMULATION_BASE_URL/plugins/email/reset\" \\\\\n -H \"Authorization: Bearer $EMULATION_CONTROL_TOKEN\"`,\n },\n];\n","/**\n * Provider-specific HTTP handlers for the email emulation plugin.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport type { EmulationRequest, EmulationResponse } from '../../plugin.js';\nimport { record } from './capture.js';\nimport {\n decodeBase64,\n extractGenericAttachments,\n isRecord,\n parseAddress,\n parseAddressList,\n parseRawMime,\n safeParseJson,\n} from './parsing.js';\nimport type { EmailCtx } from './types.js';\n\n/** SendGrid v3 - POST /v3/mail/send (returns 202 with X-Message-Id). */\nexport function handleSendgrid(req: EmulationRequest, ctx: EmailCtx): EmulationResponse {\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return { status: 400, body: { errors: [{ message: 'Invalid JSON body' }] } };\n if (!isRecord(parsed.data))\n return { status: 400, body: { errors: [{ message: 'Invalid JSON body' }] } };\n const data = parsed.data;\n\n const personalizations: unknown[] = Array.isArray(data.personalizations)\n ? data.personalizations\n : [];\n const to: string[] = [];\n const cc: string[] = [];\n const bcc: string[] = [];\n let subject: string | null = typeof data.subject === 'string' ? data.subject : null;\n for (const p of personalizations) {\n const pers = isRecord(p) ? p : {};\n to.push(...parseAddressList(pers.to).emails);\n cc.push(...parseAddressList(pers.cc).emails);\n bcc.push(...parseAddressList(pers.bcc).emails);\n if (!subject && typeof pers.subject === 'string') subject = pers.subject;\n }\n\n const fromAddr = parseAddress(data.from);\n const content = Array.isArray(data.content) ? data.content.filter(isRecord) : [];\n const textValue = content.find((c) => c.type === 'text/plain')?.value;\n const htmlValue = content.find((c) => c.type === 'text/html')?.value;\n const text = typeof textValue === 'string' ? textValue : null;\n const html = typeof htmlValue === 'string' ? htmlValue : null;\n\n const captured = record(ctx, {\n provider: 'sendgrid',\n from: fromAddr?.email ?? '',\n ...(fromAddr?.name ? { fromName: fromAddr.name } : {}),\n to,\n cc,\n bcc,\n subject,\n text,\n html,\n headers: { 'x-provider': 'sendgrid' },\n attachments: extractGenericAttachments(data.attachments, 'filename', 'type'),\n });\n\n return { status: 202, headers: { 'x-message-id': captured.id }, body: '' };\n}\n\n/** Resend - POST /emails (returns 200 {id}). */\nexport function handleResend(req: EmulationRequest, ctx: EmailCtx): EmulationResponse {\n const parsed = safeParseJson(req.body);\n if (!parsed.ok)\n return { status: 400, body: { message: 'Invalid JSON body', name: 'validation_error' } };\n if (!isRecord(parsed.data))\n return { status: 400, body: { message: 'Invalid JSON body', name: 'validation_error' } };\n const data = parsed.data;\n\n const fromAddr = parseAddress(data.from);\n const captured = record(ctx, {\n provider: 'resend',\n from: fromAddr?.email ?? '',\n ...(fromAddr?.name ? { fromName: fromAddr.name } : {}),\n to: parseAddressList(data.to).emails,\n cc: parseAddressList(data.cc).emails,\n bcc: parseAddressList(data.bcc).emails,\n subject: typeof data.subject === 'string' ? data.subject : null,\n text: typeof data.text === 'string' ? data.text : null,\n html: typeof data.html === 'string' ? data.html : null,\n headers: { 'x-provider': 'resend' },\n attachments: extractGenericAttachments(data.attachments, 'filename', 'content_type'),\n });\n\n return { status: 200, body: { id: captured.id } };\n}\n\n/** Postmark - POST /email (returns 200 {MessageID, ErrorCode:0}). */\nexport function handlePostmarkSingle(req: EmulationRequest, ctx: EmailCtx): EmulationResponse {\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return { status: 422, body: { ErrorCode: 300, Message: 'Invalid JSON body' } };\n if (!isRecord(parsed.data))\n return { status: 422, body: { ErrorCode: 300, Message: 'Invalid JSON body' } };\n return { status: 200, body: postmarkRecord(ctx, parsed.data) };\n}\n\n/** Postmark - POST /email/batch (returns 200 [{MessageID}, ...]). */\nexport function handlePostmarkBatch(req: EmulationRequest, ctx: EmailCtx): EmulationResponse {\n const parsed = safeParseJson(req.body);\n if (!parsed.ok || !Array.isArray(parsed.data)) {\n return { status: 422, body: { ErrorCode: 300, Message: 'Invalid batch body' } };\n }\n return {\n status: 200,\n body: parsed.data.map((entry) => postmarkRecord(ctx, isRecord(entry) ? entry : {})),\n };\n}\n\nfunction postmarkRecord(ctx: EmailCtx, data: Record<string, unknown>) {\n const fromAddr = parseAddress(typeof data.From === 'string' ? data.From : null);\n const captured = record(ctx, {\n provider: 'postmark',\n from: fromAddr?.email ?? '',\n ...(fromAddr?.name ? { fromName: fromAddr.name } : {}),\n to: parseAddressList(data.To).emails,\n cc: parseAddressList(data.Cc).emails,\n bcc: parseAddressList(data.Bcc).emails,\n subject: typeof data.Subject === 'string' ? data.Subject : null,\n text: typeof data.TextBody === 'string' ? data.TextBody : null,\n html: typeof data.HtmlBody === 'string' ? data.HtmlBody : null,\n headers: { 'x-provider': 'postmark' },\n attachments: extractGenericAttachments(data.Attachments, 'Name', 'ContentType'),\n });\n return {\n To: parseAddressList(data.To).emails.join(', '),\n SubmittedAt: captured.receivedAt,\n MessageID: captured.id,\n ErrorCode: 0,\n Message: 'OK',\n };\n}\n\n/** Mailgun - POST /v3/:domain/messages (form-encoded, returns 200 {id, message}). */\nexport function handleMailgun(req: EmulationRequest, ctx: EmailCtx): EmulationResponse {\n const form = new URLSearchParams(req.body ?? '');\n const fromAddr = parseAddress(form.get('from'));\n const collect = (key: string) =>\n form.getAll(key).flatMap((value) => parseAddressList(value).emails);\n\n const captured = record(ctx, {\n provider: 'mailgun',\n from: fromAddr?.email ?? '',\n ...(fromAddr?.name ? { fromName: fromAddr.name } : {}),\n to: collect('to'),\n cc: collect('cc'),\n bcc: collect('bcc'),\n subject: form.get('subject'),\n text: form.get('text'),\n html: form.get('html'),\n headers: { 'x-provider': 'mailgun' },\n attachments: [],\n });\n\n return {\n status: 200,\n body: { id: `<${captured.id}@mailgun.emulated>`, message: 'Queued. Thank you.' },\n };\n}\n\n/** Amazon SES - POST / (SendEmail / SendRawEmail, query/form-encoded). */\nexport function handleSesV1(req: EmulationRequest, ctx: EmailCtx): EmulationResponse {\n const form = new URLSearchParams(req.body ?? '');\n const action = form.get('Action') ?? '';\n\n if (action === 'SendRawEmail') {\n const rawData = form.get('RawMessage.Data');\n const mime = rawData ? parseRawMime(decodeBase64(rawData)) : null;\n const captured = record(ctx, {\n provider: 'ses',\n from: mime?.from?.email ?? (form.get('Source') ?? '').toLowerCase(),\n ...(mime?.from?.name ? { fromName: mime.from.name } : {}),\n to: mime?.to ?? sesMemberList(form, 'Destinations.member'),\n cc: mime?.cc ?? [],\n bcc: mime?.bcc ?? [],\n subject: mime?.subject ?? null,\n text: mime?.text ?? null,\n html: mime?.html ?? null,\n headers: { 'x-provider': 'ses', 'x-ses-action': 'SendRawEmail' },\n attachments: [],\n });\n return sesXmlResponse('SendRawEmail', captured.id);\n }\n\n const captured = record(ctx, {\n provider: 'ses',\n from: (form.get('Source') ?? '').toLowerCase(),\n to: sesMemberList(form, 'Destination.ToAddresses.member'),\n cc: sesMemberList(form, 'Destination.CcAddresses.member'),\n bcc: sesMemberList(form, 'Destination.BccAddresses.member'),\n subject: form.get('Message.Subject.Data'),\n text: form.get('Message.Body.Text.Data'),\n html: form.get('Message.Body.Html.Data'),\n headers: { 'x-provider': 'ses', 'x-ses-action': action || 'SendEmail' },\n attachments: [],\n });\n return sesXmlResponse('SendEmail', captured.id);\n}\n\n/** Amazon SES v2 - POST /v2/email/outbound-emails (JSON). */\nexport function handleSesV2(req: EmulationRequest, ctx: EmailCtx): EmulationResponse {\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return { status: 400, body: { message: 'Invalid JSON body' } };\n if (!isRecord(parsed.data)) return { status: 400, body: { message: 'Invalid JSON body' } };\n const data = parsed.data;\n\n const dest = isRecord(data.Destination) ? data.Destination : {};\n const content = isRecord(data.Content) ? data.Content : {};\n const simple = isRecord(content.Simple) ? content.Simple : undefined;\n const raw = isRecord(content.Raw) ? content.Raw : undefined;\n\n let subject: string | null = null;\n let text: string | null = null;\n let html: string | null = null;\n let from = String(data.FromEmailAddress ?? '').toLowerCase();\n let to = parseAddressList(dest.ToAddresses).emails;\n let cc = parseAddressList(dest.CcAddresses).emails;\n let bcc = parseAddressList(dest.BccAddresses).emails;\n\n if (raw?.Data) {\n const mime = parseRawMime(decodeBase64(String(raw.Data)));\n if (mime.from) from = mime.from.email;\n if (mime.to.length) to = mime.to;\n if (mime.cc.length) cc = mime.cc;\n if (mime.bcc.length) bcc = mime.bcc;\n subject = mime.subject;\n text = mime.text;\n html = mime.html;\n } else if (simple) {\n const subjObj = isRecord(simple.Subject) ? simple.Subject : undefined;\n const bodyObj = isRecord(simple.Body) ? simple.Body : undefined;\n const textObj = bodyObj && isRecord(bodyObj.Text) ? bodyObj.Text : undefined;\n const htmlObj = bodyObj && isRecord(bodyObj.Html) ? bodyObj.Html : undefined;\n subject = subjObj?.Data ? String(subjObj.Data) : null;\n text = textObj?.Data ? String(textObj.Data) : null;\n html = htmlObj?.Data ? String(htmlObj.Data) : null;\n }\n\n const fromAddr = parseAddress(from);\n const captured = record(ctx, {\n provider: 'ses',\n from: fromAddr?.email ?? from,\n ...(fromAddr?.name ? { fromName: fromAddr.name } : {}),\n to,\n cc,\n bcc,\n subject,\n text,\n html,\n headers: { 'x-provider': 'ses', 'x-ses-action': 'SendEmailV2' },\n attachments: [],\n });\n\n return { status: 200, body: { MessageId: captured.id } };\n}\n\nfunction sesMemberList(form: URLSearchParams, prefix: string): string[] {\n const out: string[] = [];\n for (let i = 1; ; i++) {\n const value = form.get(`${prefix}.${i}`);\n if (value === null) break;\n const parsed = parseAddress(value);\n if (parsed) out.push(parsed.email);\n }\n return out;\n}\n\nfunction sesXmlResponse(\n action: 'SendEmail' | 'SendRawEmail',\n messageId: string\n): EmulationResponse {\n const requestId = crypto.randomUUID();\n const body = `<${action}Response xmlns=\"http://ses.amazonaws.com/doc/2010-12-01/\">\n <${action}Result>\n <MessageId>${messageId}</MessageId>\n </${action}Result>\n <ResponseMetadata>\n <RequestId>${requestId}</RequestId>\n </ResponseMetadata>\n</${action}Response>`;\n return { status: 200, headers: { 'content-type': 'application/xml' }, body };\n}\n","/**\n * Email capture state mutation helpers.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport type { CapturedEmail, EmailCtx } from './types.js';\n\n/** Cap retained captures so a runaway send loop cannot grow state unbounded. */\nconst MAX_RETAINED_EMAILS = 500;\n\nexport function record(\n ctx: EmailCtx,\n email: Omit<CapturedEmail, 'id' | 'receivedAt'>\n): CapturedEmail {\n const captured: CapturedEmail = {\n id: crypto.randomUUID(),\n receivedAt: new Date().toISOString(),\n ...email,\n };\n ctx.state.sentEmails.push(captured);\n if (ctx.state.sentEmails.length > MAX_RETAINED_EMAILS) {\n ctx.state.sentEmails.splice(0, ctx.state.sentEmails.length - MAX_RETAINED_EMAILS);\n }\n\n const recipientCount = email.to.length + email.cc.length + email.bcc.length;\n ctx.log(\n 'info',\n `[${email.provider}] captured email ${captured.id} for ${recipientCount} recipient(s)`\n );\n return captured;\n}\n","/**\n * Email address, MIME, and provider payload parsing helpers.\n *\n * @module\n */\n\nimport type { CapturedEmail } from './types.js';\n\nexport interface ParsedAddress {\n email: string;\n name?: string;\n}\n\nexport interface ParsedRawMime {\n from: ParsedAddress | null;\n to: string[];\n cc: string[];\n bcc: string[];\n subject: string | null;\n text: string | null;\n html: string | null;\n}\n\ntype JsonObject = Record<string, unknown>;\n\n/**\n * Parse a single address from a string (\"Name <a@b.com>\" / \"a@b.com\") or an\n * object ({ email, name }, as SendGrid uses).\n */\nexport function parseAddress(input: unknown): ParsedAddress | null {\n if (input && typeof input === 'object' && 'email' in input) {\n const email = String((input as { email: unknown }).email ?? '')\n .trim()\n .toLowerCase();\n if (!email) return null;\n const name = (input as { name?: unknown }).name;\n return { email, ...(name ? { name: String(name) } : {}) };\n }\n if (typeof input !== 'string') return null;\n const trimmed = input.trim();\n if (!trimmed) return null;\n const angle = /^\\s*(?:\"?([^\"<]*?)\"?\\s*)?<([^>]+)>\\s*$/.exec(trimmed);\n if (angle) {\n const name = angle[1]?.trim();\n return { email: angle[2].trim().toLowerCase(), ...(name ? { name } : {}) };\n }\n return { email: trimmed.toLowerCase() };\n}\n\n/**\n * Parse an address list that may be a string, an array of strings, or an array\n * of `{email,name}` objects.\n */\nexport function parseAddressList(input: unknown): { emails: string[]; first?: ParsedAddress } {\n const out: ParsedAddress[] = [];\n\n const pushString = (value: string) => {\n // This intentionally supports the provider payloads we emulate, not full RFC parsing.\n for (const part of value.split(',')) {\n const parsed = parseAddress(part);\n if (parsed) out.push(parsed);\n }\n };\n\n if (typeof input === 'string') {\n pushString(input);\n } else if (Array.isArray(input)) {\n for (const entry of input) {\n if (typeof entry === 'string') {\n pushString(entry);\n } else if (entry && typeof entry === 'object' && 'email' in entry) {\n const email = String((entry as { email: unknown }).email ?? '')\n .trim()\n .toLowerCase();\n if (email) {\n const name = (entry as { name?: unknown }).name;\n out.push({ email, ...(name ? { name: String(name) } : {}) });\n }\n }\n }\n }\n\n return { emails: out.map((a) => a.email), ...(out[0] ? { first: out[0] } : {}) };\n}\n\n/** Decode a base64 payload to a UTF-8 string. */\nexport function decodeBase64(data: string): string {\n return Buffer.from(data, 'base64').toString('utf-8');\n}\n\n/** Decode quoted-printable: soft line breaks plus `=XX` hex escapes. */\nfunction decodeQuotedPrintable(input: string): string {\n return input\n .replace(/=\\r?\\n/g, '')\n .replace(/=([0-9A-Fa-f]{2})/g, (_m, hex) => String.fromCharCode(parseInt(hex, 16)));\n}\n\nfunction decodeMimeBody(body: string, contentTransferEncoding: string): string {\n const cte = contentTransferEncoding.trim().toLowerCase();\n if (cte === 'base64') {\n return Buffer.from(body.replace(/\\s+/g, ''), 'base64').toString('utf-8');\n }\n if (cte === 'quoted-printable') return decodeQuotedPrintable(body);\n return body;\n}\n\n/**\n * Best-effort raw-MIME parse: header block plus first body part. Enough to\n * surface OTP and magic-link mail without pulling in a full MIME parser.\n */\nexport function parseRawMime(raw: string): ParsedRawMime {\n const norm = raw.replace(/\\r\\n/g, '\\n');\n const splitAt = norm.indexOf('\\n\\n');\n const headerBlock = splitAt >= 0 ? norm.slice(0, splitAt) : norm;\n const body = splitAt >= 0 ? norm.slice(splitAt + 2) : '';\n\n const unfolded = headerBlock.replace(/\\n[ \\t]+/g, ' ');\n const headers = new Map<string, string>();\n for (const line of unfolded.split('\\n')) {\n const m = /^([^:]+):\\s*(.*)$/.exec(line);\n if (m) headers.set(m[1].trim().toLowerCase(), m[2].trim());\n }\n\n const contentType = headers.get('content-type') ?? '';\n const isHtml = /text\\/html/i.test(contentType);\n const isMultipart = /multipart\\//i.test(contentType);\n const decodedBody = isMultipart\n ? body\n : decodeMimeBody(body, headers.get('content-transfer-encoding') ?? '');\n\n return {\n from: parseAddress(headers.get('from')),\n to: parseAddressList(headers.get('to')).emails,\n cc: parseAddressList(headers.get('cc')).emails,\n bcc: parseAddressList(headers.get('bcc')).emails,\n subject: headers.get('subject') ?? null,\n text: isHtml ? null : decodedBody || null,\n html: isHtml ? decodedBody || null : null,\n };\n}\n\nexport function isRecord(value: unknown): value is JsonObject {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nexport function safeParseJson(\n body: string | undefined\n): { ok: true; data: unknown } | { ok: false } {\n try {\n return { ok: true, data: JSON.parse(body ?? '{}') };\n } catch {\n return { ok: false };\n }\n}\n\nexport function extractGenericAttachments(\n input: unknown,\n nameKey: string,\n typeKey: string\n): CapturedEmail['attachments'] {\n if (!Array.isArray(input)) return [];\n return input.map((entry) => {\n const att = (entry ?? {}) as Record<string, unknown>;\n const filename = att[nameKey];\n const contentType = att[typeKey];\n return {\n ...(typeof filename === 'string' ? { filename } : {}),\n ...(typeof contentType === 'string' ? { contentType } : {}),\n };\n });\n}\n","/**\n * Mailosaur-compatible inbox over the email plugin's captured mail.\n *\n * With `email: { mailosaur: {} }` the plugin also owns `mailosaur.com`, the\n * host every official Mailosaur SDK calls, and answers the read side of its\n * REST API (`/api/messages*`, `/api/servers*`) from `state.sentEmails`. A\n * captured email belongs to server `<id>` when one of its recipients is\n * `<anything>@<id>.mailosaur.net`, Mailosaur's addressing scheme. Deleting\n * hides a message from the inbox only; `email.sent-emails` still returns it.\n *\n * Shapes follow the official `mailosaur` npm SDK (11.x): Basic auth with the\n * API key as the user name (any key is accepted), list results as\n * `{ items }`, 204 for deletes, and the SDK's 400 `{ errors: [{ field,\n * detail: [{ description }] }] }`. The SDK's wait-for (`messages.get`,\n * `search` with `timeout`) polls `POST /api/messages/search` client-side,\n * pausing for the `x-ms-delay` header between polls.\n *\n * Everything else on mailosaur.com (creating servers or messages, files,\n * previews, analysis, devices, usage) is not declared, so it answers 501.\n *\n * @module\n */\n\nimport type { EmulationRequest, EmulationResponse } from '../../plugin.js';\nimport { isRecord, safeParseJson } from './parsing.js';\nimport type { CapturedEmail, EmailCtx } from './types.js';\n\nexport const MAILOSAUR_API_HOST = 'mailosaur.com';\n\nconst SERVER_ID = /^[a-z0-9]+$/;\nconst SERVER_ADDRESS = new RegExp(`^[^@\\\\s]+@(${SERVER_ID.source.slice(1, -1)})\\\\.mailosaur\\\\.net$`);\nconst DEFAULT_ITEMS_PER_PAGE = 50;\nconst MAX_ITEMS_PER_PAGE = 1000;\n/** Polling pause the SDK reads between empty searches; mail is captured synchronously, so keep it short. */\nconst POLL_DELAY_MS = 250;\n\ninterface Address {\n name: string;\n email: string;\n}\n\ninterface Inboxed {\n server: string;\n email: CapturedEmail;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Inbox\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** The Mailosaur servers an email was delivered to, by its recipients' addresses. */\nfunction serversOf(email: CapturedEmail): string[] {\n const servers = new Set<string>();\n for (const address of [...email.to, ...email.cc, ...email.bcc]) {\n const match = SERVER_ADDRESS.exec(address.toLowerCase());\n if (match) servers.add(match[1]!);\n }\n return [...servers];\n}\n\nfunction hiddenKey(server: string, id: string): string {\n return `${server}/${id}`;\n}\n\n/** Every visible (server, email) pair, newest first. */\nfunction inbox(ctx: EmailCtx): Inboxed[] {\n const out: Inboxed[] = [];\n for (const email of ctx.state.sentEmails) {\n for (const server of serversOf(email)) {\n if (!ctx.state.mailosaurHidden.has(hiddenKey(server, email.id))) out.push({ server, email });\n }\n }\n return out.reverse();\n}\n\nfunction findMessage(ctx: EmailCtx, id: string): Inboxed | undefined {\n return inbox(ctx).find((entry) => entry.email.id === id);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Content extraction\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction decodeEntities(value: string): string {\n return value\n .replace(/&#x([0-9a-f]+);/gi, (_m, hex: string) => String.fromCodePoint(parseInt(hex, 16)))\n .replace(/&#(\\d+);/g, (_m, dec: string) => String.fromCodePoint(parseInt(dec, 10)))\n .replace(/ /g, ' ')\n .replace(/"/g, '\"')\n .replace(/'|'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&');\n}\n\n/** The text a reader sees in an HTML body: no head, style or script, no tags, entities decoded. */\nfunction visibleText(html: string): string {\n return decodeEntities(\n html\n .replace(/<(head|style|script)\\b[\\s\\S]*?<\\/\\1\\s*>/gi, ' ')\n .replace(/<br\\s*\\/?>|<\\/(p|div|tr|li|h[1-6])\\s*>/gi, '\\n')\n .replace(/<[^>]+>/g, ' ')\n );\n}\n\nfunction attribute(tag: string, name: string): string | null {\n const match = new RegExp(`\\\\s${name}\\\\s*=\\\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\\\s>]+))`, 'i').exec(tag);\n if (!match) return null;\n return decodeEntities(match[1] ?? match[2] ?? match[3] ?? '');\n}\n\nfunction htmlLinks(html: string): Array<{ href: string; text: string }> {\n const links: Array<{ href: string; text: string }> = [];\n for (const match of html.matchAll(/(<a\\b[^>]*>)([\\s\\S]*?)<\\/a\\s*>/gi)) {\n const href = attribute(match[1]!, 'href');\n if (href) links.push({ href, text: collapse(visibleText(match[2]!)) });\n }\n return links;\n}\n\nfunction htmlImages(html: string): Array<{ src: string; alt: string }> {\n const images: Array<{ src: string; alt: string }> = [];\n for (const match of html.matchAll(/<img\\b[^>]*>/gi)) {\n const src = attribute(match[0], 'src');\n if (src) images.push({ src, alt: attribute(match[0], 'alt') ?? '' });\n }\n return images;\n}\n\nconst URL_IN_TEXT = /https?:\\/\\/[^\\s<>\"']+/g;\n\nfunction textLinks(text: string): Array<{ href: string; text: string }> {\n return [...text.matchAll(URL_IN_TEXT)].map((match) => {\n const href = match[0].replace(/[).,;:!?\\]]+$/, '');\n return { href, text: href };\n });\n}\n\n/**\n * Verification codes in the order they appear: a standalone run of 4–8\n * digits, or 4–8 upper-case letters and digits holding at least one of each.\n * URLs are skipped, so ids inside links are not codes.\n */\nfunction extractCodes(text: string): Array<{ value: string }> {\n const seen = new Set<string>();\n const codes: Array<{ value: string }> = [];\n const withoutUrls = text.replace(URL_IN_TEXT, ' ');\n for (const match of withoutUrls.matchAll(/(?<![\\w-])([0-9]{4,8}|[A-Z0-9]{4,8})(?![\\w-])/g)) {\n const value = match[1]!;\n const isDigits = /^[0-9]+$/.test(value);\n if (!isDigits && !(/[0-9]/.test(value) && /[A-Z]/.test(value))) continue;\n if (seen.has(value)) continue;\n seen.add(value);\n codes.push({ value });\n }\n return codes;\n}\n\nfunction collapse(value: string): string {\n return value.replace(/\\s+/g, ' ').trim();\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Serialization\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction addresses(emails: string[]): Address[] {\n return emails.map((email) => ({ name: '', email }));\n}\n\nfunction fromAddresses(email: CapturedEmail): Address[] {\n return email.from ? [{ name: email.fromName ?? '', email: email.from }] : [];\n}\n\nfunction summaryText(email: CapturedEmail): string {\n const body = email.text ?? (email.html ? visibleText(email.html) : '');\n return collapse(body).slice(0, 200);\n}\n\nfunction messageSummary({ server, email }: Inboxed) {\n return {\n id: email.id,\n type: 'Email',\n server,\n from: fromAddresses(email),\n to: addresses(email.to),\n cc: addresses(email.cc),\n bcc: addresses(email.bcc),\n received: email.receivedAt,\n subject: email.subject ?? '',\n summary: summaryText(email),\n attachments: email.attachments.length,\n };\n}\n\nfunction message({ server, email }: Inboxed) {\n const html = email.html;\n const text = email.text;\n return {\n id: email.id,\n type: 'Email',\n server,\n from: fromAddresses(email),\n to: addresses(email.to),\n cc: addresses(email.cc),\n bcc: addresses(email.bcc),\n received: email.receivedAt,\n subject: email.subject ?? '',\n html: {\n body: html,\n links: html ? htmlLinks(html) : [],\n codes: html ? extractCodes(visibleText(html)) : [],\n images: html ? htmlImages(html) : [],\n },\n text: {\n body: text,\n links: text ? textLinks(text) : [],\n codes: text ? extractCodes(text) : [],\n },\n attachments: email.attachments.map((attachment, index) => ({\n id: `${email.id}-${index}`,\n contentType: attachment.contentType ?? 'application/octet-stream',\n fileName: attachment.filename ?? '',\n contentId: null,\n length: attachment.size ?? 0,\n url: '',\n })),\n metadata: {\n headers: [\n { field: 'From', value: email.fromName ? `${email.fromName} <${email.from}>` : email.from },\n { field: 'To', value: email.to.join(', ') },\n ...(email.cc.length ? [{ field: 'Cc', value: email.cc.join(', ') }] : []),\n { field: 'Subject', value: email.subject ?? '' },\n { field: 'Date', value: new Date(email.receivedAt).toUTCString() },\n ],\n ehlo: null,\n mailFrom: email.from,\n rcptTo: addresses([...email.to, ...email.cc, ...email.bcc]),\n },\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Request plumbing\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction invalid(field: string, description: string): EmulationResponse {\n return { status: 400, body: { errors: [{ field, detail: [{ description }] }] } };\n}\n\n/** Basic auth with the API key as the user name; any non-empty key is accepted. */\nfunction authorized(req: EmulationRequest): boolean {\n const match = /^Basic\\s+(\\S+)$/i.exec(req.headers.authorization ?? '');\n if (!match) return false;\n const decoded = Buffer.from(match[1]!, 'base64').toString('utf-8');\n return decoded.split(':')[0]!.length > 0;\n}\n\n/**\n * Wrap a handler: answer only HTTPS for mailosaur.com, and require Basic auth\n * like the real API. The plugin's routes are shared by every provider host, so\n * elsewhere these paths stay not-emulated. HTTPS only, because the emulator's\n * TLS listener is reached solely through the sandbox's /etc/hosts entry; its\n * plain-HTTP listener is the copy's public `emulation` port, where a forged\n * `Host: mailosaur.com` must not read the app's mail.\n */\nfunction onMailosaur(\n handler: (req: EmulationRequest, ctx: EmailCtx) => EmulationResponse\n): (req: EmulationRequest, ctx: EmailCtx) => EmulationResponse | null {\n return (req, ctx) => {\n if (req.url.protocol !== 'https:' || req.url.hostname.toLowerCase() !== MAILOSAUR_API_HOST) return null;\n if (!authorized(req)) return { status: 401, body: '' };\n return handler(req, ctx);\n };\n}\n\ntype ListQuery = { server: string; page: number; itemsPerPage: number; receivedAfter: number | null; received: boolean };\n\ntype Parsed<T> = { ok: true; value: T } | { ok: false; response: EmulationResponse };\n\nfunction rejected(field: string, description: string): { ok: false; response: EmulationResponse } {\n return { ok: false, response: invalid(field, description) };\n}\n\n/** The list/search query string; `page`, `itemsPerPage` and `dir` are what the SDK forwards from its options. */\nfunction listQuery(req: EmulationRequest): Parsed<ListQuery> {\n const params = req.url.searchParams;\n const server = params.get('server');\n if (!server) return rejected('server', 'The server field is required.');\n const page = Number(params.get('page') ?? 0);\n const itemsPerPage = Number(params.get('itemsPerPage') ?? DEFAULT_ITEMS_PER_PAGE);\n if (!Number.isInteger(page) || page < 0) return rejected('page', 'Page must be a non-negative integer.');\n if (!Number.isInteger(itemsPerPage) || itemsPerPage < 1 || itemsPerPage > MAX_ITEMS_PER_PAGE) {\n return rejected('itemsPerPage', `Items per page must be between 1 and ${MAX_ITEMS_PER_PAGE}.`);\n }\n // The SDK appends the ISO date unencoded, so a `+hh:mm` offset arrives as a space.\n const receivedAfterRaw = params.get('receivedAfter');\n let receivedAfter: number | null = null;\n if (receivedAfterRaw) {\n receivedAfter = Date.parse(receivedAfterRaw.replace(/ /g, '+'));\n if (Number.isNaN(receivedAfter)) return rejected('receivedAfter', 'Received after must be a date.');\n }\n const dir = params.get('dir') ?? 'Received';\n if (dir !== 'Received' && dir !== 'Sent') return rejected('dir', 'Direction must be Sent or Received.');\n return { ok: true, value: { server: server.toLowerCase(), page, itemsPerPage, receivedAfter, received: dir === 'Received' } };\n}\n\nfunction listed(ctx: EmailCtx, query: ListQuery, predicate: (email: CapturedEmail) => boolean) {\n // Captured mail is mail the app sent INTO Mailosaur: every message is a received one.\n const matches = query.received\n ? inbox(ctx).filter(\n (entry) =>\n entry.server === query.server &&\n (query.receivedAfter === null || Date.parse(entry.email.receivedAt) >= query.receivedAfter) &&\n predicate(entry.email)\n )\n : [];\n const start = query.page * query.itemsPerPage;\n return {\n status: 200,\n headers: { 'x-ms-delay': String(POLL_DELAY_MS) },\n body: { items: matches.slice(start, start + query.itemsPerPage).map(messageSummary) },\n };\n}\n\nconst CRITERIA_FIELDS = ['sentFrom', 'sentTo', 'subject', 'body'] as const;\n\nfunction criteriaPredicate(criteria: Record<string, unknown>): Parsed<(email: CapturedEmail) => boolean> {\n const checks: Array<(email: CapturedEmail) => boolean> = [];\n for (const field of CRITERIA_FIELDS) {\n const raw = criteria[field];\n if (raw === undefined || raw === null || raw === '') continue;\n if (typeof raw !== 'string') return rejected(field, `${field} must be a string.`);\n const value = raw.toLowerCase();\n if (field === 'sentFrom') checks.push((email) => email.from === value);\n if (field === 'sentTo') checks.push((email) => [...email.to, ...email.cc, ...email.bcc].includes(value));\n if (field === 'subject') checks.push((email) => (email.subject ?? '').toLowerCase().includes(value));\n if (field === 'body') {\n checks.push(\n (email) =>\n (email.text ?? '').toLowerCase().includes(value) || (email.html ?? '').toLowerCase().includes(value)\n );\n }\n }\n if (checks.length === 0) return rejected('criteria', 'Please provide at least one search criteria.');\n const match = criteria.match ?? 'ALL';\n if (match !== 'ALL' && match !== 'ANY') return rejected('match', 'Match must be ALL or ANY.');\n const value =\n match === 'ALL'\n ? (email: CapturedEmail) => checks.every((check) => check(email))\n : (email: CapturedEmail) => checks.some((check) => check(email));\n return { ok: true, value };\n}\n\nfunction server(ctx: EmailCtx, id: string) {\n const messages = inbox(ctx).filter((entry) => entry.server === id).length;\n return { id, name: id, users: [], messages };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Handlers\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** GET /api/messages?server= */\nexport const handleListMessages = onMailosaur((req, ctx) => {\n const query = listQuery(req);\n if (!query.ok) return query.response;\n return listed(ctx, query.value, () => true);\n});\n\n/** POST /api/messages/search?server= with `{ sentFrom, sentTo, subject, body, match }`. */\nexport const handleSearchMessages = onMailosaur((req, ctx) => {\n const query = listQuery(req);\n if (!query.ok) return query.response;\n const parsed = safeParseJson(req.body);\n if (!parsed.ok || !isRecord(parsed.data)) return invalid('criteria', 'The request body must be a JSON object.');\n const predicate = criteriaPredicate(parsed.data);\n if (!predicate.ok) return predicate.response;\n return listed(ctx, query.value, predicate.value);\n});\n\n/** GET /api/messages/:id */\nexport const handleGetMessage = onMailosaur((req, ctx) => {\n const found = findMessage(ctx, req.params.id!);\n return found ? { status: 200, body: message(found) } : { status: 404, body: '' };\n});\n\n/** DELETE /api/messages/:id: hides it from every server inbox it was in. */\nexport const handleDeleteMessage = onMailosaur((req, ctx) => {\n const id = req.params.id!;\n const entries = inbox(ctx).filter((entry) => entry.email.id === id);\n if (entries.length === 0) return { status: 404, body: '' };\n for (const entry of entries) ctx.state.mailosaurHidden.add(hiddenKey(entry.server, id));\n return { status: 204 };\n});\n\n/** DELETE /api/messages?server=: empties one server's inbox. */\nexport const handleDeleteAllMessages = onMailosaur((req, ctx) => {\n const id = req.url.searchParams.get('server')?.toLowerCase();\n if (!id) return invalid('server', 'The server field is required.');\n for (const entry of inbox(ctx)) {\n if (entry.server === id) ctx.state.mailosaurHidden.add(hiddenKey(id, entry.email.id));\n }\n return { status: 204 };\n});\n\n/** GET /api/servers: every server some captured email was addressed to, by name. */\nexport const handleListServers = onMailosaur((_req, ctx) => {\n const ids = new Set(ctx.state.sentEmails.flatMap(serversOf));\n return { status: 200, body: { items: [...ids].sort().map((id) => server(ctx, id)) } };\n});\n\n/** GET /api/servers/:id: any well-formed id is a server, empty until mail arrives. */\nexport const handleGetServer = onMailosaur((req, ctx) => {\n const id = req.params.id!.toLowerCase();\n return SERVER_ID.test(id) ? { status: 200, body: server(ctx, id) } : { status: 404, body: '' };\n});\n","/**\n * Shared email emulation types.\n *\n * @module\n */\n\nimport { z } from 'zod';\nimport type { PluginContext } from '../../plugin.js';\n\nexport type EmailProvider = 'ses' | 'sendgrid' | 'resend' | 'postmark' | 'mailgun';\n\n/** Zod schema of a definition's `emulation.email` block. */\nexport const emailConfigSchema = z.object({\n /** AWS SES regions whose API hosts to intercept (default ['us-east-1']). */\n sesRegions: z.array(z.string()).optional(),\n /** Extra custom hosts to intercept (e.g. a self-hosted provider API). */\n extraDomains: z.array(z.string()).optional(),\n /** Present: also serve Mailosaur's read API on mailosaur.com from the captured mail. */\n mailosaur: z.strictObject({}).optional(),\n});\nexport type EmailEmuConfig = z.infer<typeof emailConfigSchema>;\n\n/** Normalized capture of one outbound email, provider-agnostic. */\nexport interface CapturedEmail {\n /** Stable per-send id, used as the inbox dedup key (messageId). */\n id: string;\n provider: EmailProvider;\n from: string;\n fromName?: string;\n to: string[];\n cc: string[];\n bcc: string[];\n subject: string | null;\n text: string | null;\n html: string | null;\n /** Selected provider headers, with sensitive values redacted. */\n headers: Record<string, string>;\n attachments: Array<{ filename?: string; contentType?: string; size?: number }>;\n /** ISO-8601 capture time. */\n receivedAt: string;\n}\n\n/** Zod schema mirroring `CapturedEmail`, for validating operation outputs. */\nexport const capturedEmailSchema = z.object({\n id: z.string(),\n provider: z.enum(['ses', 'sendgrid', 'resend', 'postmark', 'mailgun']),\n from: z.string(),\n fromName: z.string().optional(),\n to: z.array(z.string()),\n cc: z.array(z.string()),\n bcc: z.array(z.string()),\n subject: z.string().nullable(),\n text: z.string().nullable(),\n html: z.string().nullable(),\n headers: z.record(z.string(), z.string()),\n attachments: z.array(\n z.object({\n filename: z.string().optional(),\n contentType: z.string().optional(),\n size: z.number().optional(),\n })\n ),\n receivedAt: z.string(),\n});\n\n/** Fixture is intentionally empty; there is no seed data, only captured state. */\nexport const emailFixtureSchema = z.object({}).passthrough();\nexport type EmailFixture = z.infer<typeof emailFixtureSchema>;\n\nexport interface EmailState {\n /** Every email sent since boot or last reset, used as the assertion surface. */\n sentEmails: CapturedEmail[];\n /** `<server>/<message id>` pairs deleted through the Mailosaur API: hidden from that inbox only. */\n mailosaurHidden: Set<string>;\n}\n\nexport type EmailCtx = PluginContext<EmailFixture, EmailState>;\n","/**\n * Shared OIDC provider core.\n *\n * The authorize / token / userinfo / discovery / JWKS logic behind the\n * persona-backed OIDC emulators. A provider is an {@link OidcFlavor}: plain\n * data (label, issuer, endpoints) plus the claims it adds beyond the standard\n * set. Every declared persona is an account; codes, access tokens and refresh\n * tokens are each bound to one persona.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport { z } from 'zod';\nimport type { EmulationRequest, EmulationResponse, PluginContext } from '../plugin.js';\nimport { generateKeyPair, signIdToken, buildJwks, type EphemeralKeyPair } from './jwt.js';\nimport {\n GrantStore,\n identityForHint,\n personaIdentities,\n personaIdentitySchema,\n renderAccountChooser,\n type PersonaDeclaration,\n type PersonaIdentity,\n} from '../persona-identity.js';\n\nexport interface OidcFixture {\n identities: PersonaIdentity[];\n}\n\nexport const oidcFixtureSchema = z.object({ identities: z.array(personaIdentitySchema).min(1) });\n\n/** Each declared persona is an account. Throws when there are none. */\nexport function oidcFixture(personas: Record<string, PersonaDeclaration>): OidcFixture {\n return { identities: personaIdentities(personas) };\n}\n\nexport interface OidcState {\n keyPair: EphemeralKeyPair;\n identities: PersonaIdentity[];\n /** Authorization codes (`emulated_code_`), single use. */\n grants: GrantStore;\n /** `emulated_at_<uuid>` -> sub */\n accessTokens: Map<string, string>;\n /** `emulated_rt_<uuid>` -> sub */\n refreshTokens: Map<string, string>;\n detectedClientId: string | null;\n /** Pre-computed JWKS response (key pair is stable for the container lifetime) */\n jwksResponse: object;\n}\n\nexport type OidcContext = PluginContext<OidcFixture, OidcState>;\n\ninterface OidcEndpoints {\n authorization_endpoint: string;\n token_endpoint: string;\n userinfo_endpoint: string;\n jwks_uri: string;\n}\n\n/** What differs between providers; everything else is shared. */\nexport interface OidcFlavor {\n /** Provider name shown on the account chooser. */\n label: string;\n issuer(ctx: OidcContext): string;\n /** Absolute URLs: the chooser is also served while the browser's page URL is the app's. */\n endpoints(ctx: OidcContext): OidcEndpoints;\n /** Claims added to the id_token and userinfo beyond the standard set: claim name -> value for an identity. */\n extraClaims: Record<string, (identity: PersonaIdentity) => unknown>;\n}\n\nexport function initializeOidcState(fixture: OidcFixture, clientId: string | null): OidcState {\n const keyPair = generateKeyPair();\n return {\n keyPair,\n identities: fixture.identities,\n grants: new GrantStore(),\n accessTokens: new Map(),\n refreshTokens: new Map(),\n detectedClientId: clientId,\n jwksResponse: buildJwks(keyPair),\n };\n}\n\nconst EMULATED_ACCESS_TOKEN_PREFIX = 'emulated_at_';\nconst EMULATED_REFRESH_TOKEN_PREFIX = 'emulated_rt_';\n\nfunction isHttpUrl(value: string): boolean {\n try {\n const { protocol } = new URL(value);\n return protocol === 'http:' || protocol === 'https:';\n } catch {\n return false;\n }\n}\n\n/** 302 back to the app with a code, 200 account chooser, or 400 without redirect_uri. */\nexport function authorize(flavor: OidcFlavor, ctx: OidcContext, url: URL): EmulationResponse {\n const redirectUri = url.searchParams.get('redirect_uri');\n if (!redirectUri || !isHttpUrl(redirectUri)) {\n ctx.log('warn', `Authorize rejected: redirect_uri is missing or not an http(s) URL`);\n return {\n status: 400,\n headers: { 'content-type': 'text/plain' },\n body: 'Invalid OAuth request: redirect_uri must be an http(s) URL',\n };\n }\n\n const loginHint = url.searchParams.get('login_hint');\n const identity = identityForHint(ctx.state.identities, loginHint);\n if (!identity) {\n if (loginHint) ctx.log('info', `login_hint ${loginHint} matched no persona; showing the chooser`);\n const authorizeUrl = flavor.endpoints(ctx).authorization_endpoint;\n return {\n status: 200,\n headers: { 'content-type': 'text/html; charset=utf-8' },\n body: renderAccountChooser({\n provider: flavor.label,\n accounts: ctx.state.identities.map((account) => {\n const query = new URLSearchParams(url.searchParams);\n query.set('login_hint', account.email);\n return {\n label: account.name,\n email: account.email,\n href: `${authorizeUrl}?${query.toString()}`,\n };\n }),\n }),\n };\n }\n\n const code = ctx.state.grants.issue({\n identity,\n clientId: url.searchParams.get('client_id'),\n redirectUri,\n nonce: url.searchParams.get('nonce'),\n });\n const callback = new URL(redirectUri);\n callback.searchParams.set('code', code);\n const state = url.searchParams.get('state');\n if (state) callback.searchParams.set('state', state);\n return { status: 302, headers: { location: callback.toString() }, body: '' };\n}\n\nfunction invalidGrant(description: string): EmulationResponse {\n return { status: 400, body: { error: 'invalid_grant', error_description: description } };\n}\n\nfunction identityBySub(ctx: OidcContext, sub: string | undefined): PersonaIdentity | null {\n return ctx.state.identities.find((identity) => identity.sub === sub) ?? null;\n}\n\nfunction bearerToken(req: EmulationRequest): string | undefined {\n const header = req.headers['authorization'] ?? '';\n return /^bearer\\s+(.+)$/i.exec(header)?.[1]?.trim();\n}\n\n/** The client_id from `Authorization: Basic base64(id:secret)` (RFC 6749 §2.3.1); malformed means absent. */\nfunction basicClientId(req: EmulationRequest): string | null {\n const header = req.headers['authorization'] ?? '';\n const credentials = /^basic\\s+(.+)$/i.exec(header)?.[1];\n if (!credentials) return null;\n const decoded = Buffer.from(credentials.trim(), 'base64').toString('utf8');\n const separator = decoded.indexOf(':');\n if (separator <= 0) return null;\n try {\n return decodeURIComponent(decoded.slice(0, separator).replace(/\\+/g, ' '));\n } catch {\n return null;\n }\n}\n\nfunction standardClaims(identity: PersonaIdentity) {\n return {\n sub: identity.sub,\n email: identity.email,\n email_verified: identity.emailVerified,\n name: identity.name,\n };\n}\n\n/** Evaluates the flavour's extra claims for one identity. */\nfunction evaluateExtraClaims(flavor: OidcFlavor, identity: PersonaIdentity): Record<string, unknown> {\n return Object.fromEntries(Object.entries(flavor.extraClaims).map(([name, claim]) => [name, claim(identity)]));\n}\n\nexport function handleToken(flavor: OidcFlavor, req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n const params = new URLSearchParams(req.body ?? '');\n const grantType = params.get('grant_type');\n // Plan Decision 14: the client secret is never checked.\n // The body client_id wins over HTTP Basic.\n const requestClientId = params.get('client_id') ?? basicClientId(req);\n const clientId = requestClientId ?? ctx.state.detectedClientId ?? 'unknown';\n\n // Track client_id for future requests\n if (!ctx.state.detectedClientId && clientId !== 'unknown') {\n ctx.state.detectedClientId = clientId;\n }\n\n if (grantType === 'authorization_code') {\n const grant = ctx.state.grants.take(params.get('code') ?? '');\n if (!grant) {\n ctx.log('warn', 'Token exchange with an unknown or already redeemed code');\n return invalidGrant('Invalid authorization code');\n }\n const redirectUri = params.get('redirect_uri');\n if (\n redirectUri !== grant.redirectUri ||\n (requestClientId && grant.clientId && requestClientId !== grant.clientId)\n ) {\n ctx.log('warn', 'Token exchange rejected: redirect_uri or client_id differs from the authorize request');\n return invalidGrant('Authorization code was issued for a different client or redirect_uri');\n }\n const { identity } = grant;\n const audience = requestClientId ?? grant.clientId ?? ctx.state.detectedClientId ?? 'unknown';\n\n const accessToken = `${EMULATED_ACCESS_TOKEN_PREFIX}${crypto.randomUUID()}`;\n const refreshToken = `${EMULATED_REFRESH_TOKEN_PREFIX}${crypto.randomUUID()}`;\n ctx.state.accessTokens.set(accessToken, identity.sub);\n ctx.state.refreshTokens.set(refreshToken, identity.sub);\n\n const idToken = signIdToken(\n {\n ...evaluateExtraClaims(flavor, identity),\n ...standardClaims(identity),\n iss: flavor.issuer(ctx),\n aud: audience,\n azp: audience,\n nonce: grant.nonce ?? undefined,\n },\n ctx.state.keyPair\n );\n\n ctx.log('info', `Issued tokens for ${identity.email}`);\n\n return {\n status: 200,\n body: {\n access_token: accessToken,\n token_type: 'Bearer',\n expires_in: 3600,\n refresh_token: refreshToken,\n scope: 'openid email profile',\n id_token: idToken,\n },\n };\n }\n\n if (grantType === 'refresh_token') {\n const sub = ctx.state.refreshTokens.get(params.get('refresh_token') ?? '');\n const identity = identityBySub(ctx, sub);\n if (!identity) {\n ctx.log('warn', 'Token refresh with an unknown refresh token');\n return invalidGrant('Invalid refresh token');\n }\n\n const accessToken = `${EMULATED_ACCESS_TOKEN_PREFIX}${crypto.randomUUID()}`;\n ctx.state.accessTokens.set(accessToken, identity.sub);\n ctx.log('info', `Refreshed token for ${identity.email}`);\n\n return {\n status: 200,\n body: {\n access_token: accessToken,\n token_type: 'Bearer',\n expires_in: 3600,\n scope: 'openid email profile',\n },\n };\n }\n\n return { status: 400, body: { error: 'unsupported_grant_type' } };\n}\n\nexport function handleUserinfo(flavor: OidcFlavor, req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n const token = bearerToken(req);\n const identity = identityBySub(ctx, token ? ctx.state.accessTokens.get(token) : undefined);\n if (!identity) return { status: 401, body: { error: 'invalid_token' } };\n return { status: 200, body: { ...evaluateExtraClaims(flavor, identity), ...standardClaims(identity) } };\n}\n\nexport function handleDiscovery(flavor: OidcFlavor, _req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n return {\n status: 200,\n body: {\n issuer: flavor.issuer(ctx),\n ...flavor.endpoints(ctx),\n response_types_supported: ['code'],\n grant_types_supported: ['authorization_code', 'refresh_token'],\n subject_types_supported: ['public'],\n id_token_signing_alg_values_supported: ['RS256'],\n scopes_supported: ['openid', 'email', 'profile'],\n token_endpoint_auth_methods_supported: ['client_secret_post', 'client_secret_basic', 'none'],\n // Advertised so PKCE-sending libraries proceed; the challenge is never verified (plan Decision 13).\n code_challenge_methods_supported: ['S256', 'plain'],\n claims_supported: [\n 'sub', 'iss', 'aud', 'iat', 'exp', 'nonce', 'email', 'email_verified', 'name',\n ...Object.keys(flavor.extraClaims),\n ],\n },\n };\n}\n\nexport function handleJwks(_req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n return {\n status: 200,\n headers: { 'cache-control': 'public, max-age=3600' },\n body: ctx.state.jwksResponse,\n };\n}\n","/**\n * JWT Utilities for OAuth Emulation\n *\n * Generates ephemeral RSA key pairs and signs JWTs for OpenID Connect id_tokens.\n * The corresponding public key is served via JWKS endpoints so apps that verify\n * JWT signatures via OIDC discovery will succeed.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Key Management\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface EphemeralKeyPair {\n privateKey: crypto.KeyObject;\n publicKey: crypto.KeyObject;\n kid: string;\n}\n\n/** Generate an RSA-2048 key pair for JWT signing. Called once on startup. */\nexport function generateKeyPair(): EphemeralKeyPair {\n const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {\n modulusLength: 2048,\n });\n const kid = crypto.randomUUID();\n return { privateKey, publicKey, kid };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// JWT Signing\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface IdTokenClaims {\n iss: string;\n aud: string;\n sub: string;\n email: string;\n email_verified?: boolean;\n name: string;\n given_name?: string;\n family_name?: string;\n picture?: string;\n nonce?: string;\n [key: string]: unknown;\n}\n\n/** Sign a JWT id_token with the ephemeral key pair. */\nexport function signIdToken(\n claims: IdTokenClaims,\n keyPair: EphemeralKeyPair\n): string {\n const now = Math.floor(Date.now() / 1000);\n\n const header = {\n alg: 'RS256',\n typ: 'JWT',\n kid: keyPair.kid,\n };\n\n const payload = {\n ...claims,\n iat: now,\n exp: now + 3600,\n };\n\n const headerB64 = base64url(JSON.stringify(header));\n const payloadB64 = base64url(JSON.stringify(payload));\n const signingInput = `${headerB64}.${payloadB64}`;\n\n const signature = crypto.sign('sha256', Buffer.from(signingInput), keyPair.privateKey);\n const signatureB64 = base64url(signature);\n\n return `${signingInput}.${signatureB64}`;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// JWKS\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Build a JWKS response containing the public key. */\nexport function buildJwks(keyPair: EphemeralKeyPair): object {\n const jwk = keyPair.publicKey.export({ format: 'jwk' });\n return {\n keys: [\n {\n ...jwk,\n kid: keyPair.kid,\n alg: 'RS256',\n use: 'sig',\n },\n ],\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction base64url(input: string | Buffer): string {\n const buf = typeof input === 'string' ? Buffer.from(input) : input;\n return buf.toString('base64url');\n}\n","/**\n * Provider-neutral persona identities: persona -> OIDC-style identity, the\n * one-time authorization-code store and the server-rendered account chooser.\n * Providers (Google today) import this; nothing here is provider specific.\n *\n * @module\n */\n\nimport { createHash, randomUUID } from 'node:crypto';\nimport { z } from 'zod';\n\nexport type PersonaDeclaration = { email: string };\n\n/** One declared persona as an OIDC-style identity. Serialisable: it is the plugin fixture. */\nexport const personaIdentitySchema = z.object({\n persona: z.string(),\n /** Stable, derived from `persona` only. */\n sub: z.string(),\n email: z.string(),\n emailVerified: z.literal(true),\n /** = persona */\n name: z.string(),\n});\n\nexport type PersonaIdentity = z.infer<typeof personaIdentitySchema>;\n\n/** `sub` is 21 decimal digits (Google's shape) from sha256(\"cofactor-persona:\" + name). */\nexport function personaSub(persona: string): string {\n const hex = createHash('sha256').update(`cofactor-persona:${persona}`).digest('hex').slice(0, 32);\n return BigInt(`0x${hex}`).toString().slice(0, 21).padStart(21, '0');\n}\n\n/** Throws on an empty set: a provider with no accounts cannot sign anyone in. */\nexport function personaIdentities(\n personas: Record<string, PersonaDeclaration>\n): PersonaIdentity[] {\n const entries = Object.entries(personas);\n if (entries.length === 0) {\n throw new Error('at least one persona is required: each persona is a provider account');\n }\n return entries.map(([persona, { email }]) => ({\n persona,\n sub: personaSub(persona),\n email,\n emailVerified: true,\n name: persona,\n }));\n}\n\n/** Case-insensitive email match; null for no/unknown hint (the caller shows the chooser). */\nexport function identityForHint(\n identities: PersonaIdentity[],\n hint: string | null\n): PersonaIdentity | null {\n if (!hint) return null;\n const wanted = hint.toLowerCase();\n return identities.find((identity) => identity.email.toLowerCase() === wanted) ?? null;\n}\n\nexport type AuthorizationGrant = {\n identity: PersonaIdentity;\n clientId: string | null;\n redirectUri: string;\n nonce: string | null;\n};\n\nconst CODE_PREFIX = 'emulated_code_';\n\n/** Issued-code store: `take` removes the grant (single use). */\nexport class GrantStore {\n private readonly grants = new Map<string, AuthorizationGrant>();\n\n issue(grant: AuthorizationGrant): string {\n const code = `${CODE_PREFIX}${randomUUID()}`;\n this.grants.set(code, grant);\n return code;\n }\n\n take(code: string): AuthorizationGrant | null {\n const grant = this.grants.get(code) ?? null;\n this.grants.delete(code);\n return grant;\n }\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/** Server-rendered chooser. `accounts[i].href` is the authorize URL with login_hint set. All values HTML-escaped. */\nexport function renderAccountChooser(input: {\n provider: string;\n accounts: { label: string; email: string; href: string }[];\n}): string {\n const provider = escapeHtml(input.provider);\n const items = input.accounts\n .map(\n (account) =>\n `<li><a href=\"${escapeHtml(account.href)}\"><strong>${escapeHtml(account.label)}</strong><br><span>${escapeHtml(account.email)}</span></a></li>`\n )\n .join('');\n return `<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Sign in with ${provider}</title><style>body{font-family:system-ui,sans-serif;max-width:24rem;margin:4rem auto;padding:0 1rem}ul{list-style:none;padding:0}li{border:1px solid #ccc;border-radius:.5rem;margin:.5rem 0}a{display:block;padding:.75rem 1rem;color:inherit;text-decoration:none}span{color:#555;font-size:.9rem}</style></head><body><h1>Choose an account</h1><p>to continue with ${provider} (sandbox emulator)</p><ul>${items}</ul></body></html>`;\n}\n","/**\n * Google OAuth 2.0 / OpenID Connect Emulation Plugin\n *\n * Emulates Google's OAuth authorization server for sandboxed apps.\n *\n * Every declared persona is a Google account. The authorize endpoint serves an\n * account chooser (or completes straight away for a matching `login_hint`);\n * codes, access tokens and refresh tokens are each bound to one persona.\n *\n * Sandbox-side: authorize, token exchange (POST /token), userinfo endpoint,\n * OIDC discovery, and JWKS endpoint. The Cofactor browser reaches authorize\n * through the control plane (`controlReads`).\n *\n * @module\n */\n\nimport type { EmulationPlugin, EmulationRequest, EmulationResponse } from '../plugin.js';\nimport {\n authorize,\n handleDiscovery,\n handleJwks,\n handleToken,\n handleUserinfo,\n initializeOidcState,\n oidcFixtureSchema,\n type OidcContext,\n type OidcFixture,\n type OidcFlavor,\n type OidcState,\n} from './oidc-core.js';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface GoogleOAuthConfig {\n /** The app's OAuth client ID (used in aud/azp claims). Optional — extracted from requests if not set. */\n clientId?: string;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Constants\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const GOOGLE_OAUTH_DOMAINS = [\n 'accounts.google.com',\n 'oauth2.googleapis.com',\n 'www.googleapis.com',\n 'openidconnect.googleapis.com',\n];\n\nconst GOOGLE_ISSUER = 'https://accounts.google.com';\n\nconst googleFlavor: OidcFlavor = {\n label: 'Google',\n issuer: () => GOOGLE_ISSUER,\n endpoints: () => ({\n authorization_endpoint: `${GOOGLE_ISSUER}/o/oauth2/v2/auth`,\n token_endpoint: 'https://oauth2.googleapis.com/token',\n userinfo_endpoint: 'https://www.googleapis.com/oauth2/v3/userinfo',\n jwks_uri: `${GOOGLE_ISSUER}/oauth2/v3/certs`,\n }),\n extraClaims: { given_name: (identity) => identity.name },\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Plugin\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const googleOAuthPlugin: EmulationPlugin<GoogleOAuthConfig, OidcFixture, OidcState> = {\n id: 'google-oauth',\n name: 'Google OAuth 2.0',\n version: '1.0.0',\n domains: GOOGLE_OAUTH_DOMAINS,\n needsBrowserIntercept: false,\n\n // ── Sandbox-side routes ──────────────────────────────────────────────────\n\n routes: [\n // Authorize (Host: accounts.google.com; in-VM clients reach it over :443)\n { method: 'GET', path: '/o/oauth2/v2/auth', handler: handleAuthorizeRoute },\n { method: 'GET', path: '/o/oauth2/auth', handler: handleAuthorizeRoute },\n\n // Token exchange\n {\n method: 'POST',\n path: '/token',\n handler: handleTokenExchange,\n },\n {\n method: 'POST',\n path: '/oauth2/v4/token',\n handler: handleTokenExchange,\n },\n\n // Userinfo\n {\n method: 'GET',\n path: '/oauth2/v3/userinfo',\n handler: handleUserinfoRoute,\n },\n {\n method: 'GET',\n path: '/oauth2/v2/userinfo',\n handler: handleUserinfoRoute,\n },\n {\n method: 'GET',\n path: '/userinfo/v2/me',\n handler: handleUserinfoRoute,\n },\n {\n method: 'GET',\n path: '/v1/userinfo',\n handler: handleUserinfoRoute,\n },\n\n // OIDC Discovery\n {\n method: 'GET',\n path: '/.well-known/openid-configuration',\n handler: handleOidcDiscovery,\n },\n\n // JWKS\n {\n method: 'GET',\n path: '/oauth2/v3/certs',\n handler: handleJwks,\n },\n ],\n\n // ── Control-plane reads ──────────────────────────────────────────────────\n\n // Guarded by the derived authorize key (control-plane.ts), for the Cofactor browser.\n controlReads: [{ path: 'authorize', handler: handleAuthorizeRoute }],\n\n fixtureSchema: oidcFixtureSchema,\n\n // ── Initialization ───────────────────────────────────────────────────────\n\n initialize(config, fixture) {\n return initializeOidcState(fixture, config.clientId ?? null);\n },\n};\n\nfunction handleAuthorizeRoute(req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n return authorize(googleFlavor, ctx, req.url);\n}\n\nfunction handleTokenExchange(req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n return handleToken(googleFlavor, req, ctx);\n}\nfunction handleUserinfoRoute(req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n return handleUserinfo(googleFlavor, req, ctx);\n}\nfunction handleOidcDiscovery(req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n return handleDiscovery(googleFlavor, req, ctx);\n}\n","/**\n * Esri ArcGIS REST Emulation Plugin\n *\n * Emulates the slice of the ArcGIS REST API a third-party connector uses to\n * query and edit hosted feature layers: the token endpoint, the portal health\n * check, the signed-in user, FeatureServer/layer metadata, `query`, and `applyEdits`.\n *\n * Host-routed: one configured host serves every tenant. A tenant is the first\n * path segment (`https://<host>/<tenant>/arcgis/rest/services`), where ArcGIS\n * Online puts its org id. State is per tenant, in memory, seeded through the\n * `seed-layer` operation, and dropped when idle past `tenantTtlMinutes` or older\n * than `tenantMaxAgeMinutes` (swept lazily on each request and seed, no timers).\n *\n * Like real ArcGIS, errors are HTTP 200 with an `{ error: { code, ... } }` body.\n * Paths are as forgiving as real ArcGIS: resources take a trailing slash, and an\n * operation (`generateToken`, `query`, ...) ignores any path after it. Every\n * request that matches nothing gets ArcGIS Online's `Invalid URL` answer from a\n * catch-all route and is recorded by the proxy, so the traffic of a real\n * connector shows what to implement next.\n *\n * Tokens and the credential are global, not per tenant: isolation between\n * tenants rests on the unguessable tenant name.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport type { EmulationPlugin, EmulationRoute } from '../../plugin.js';\nimport { tokensMatch } from '../../token-match.js';\nimport { EsriError, badParameter, errorResponse } from './errors.js';\nimport {\n applyLayerEdits,\n parseFeatures,\n parseIds,\n withoutCredentials,\n} from './layers.js';\nimport { flag, ok, readParams } from './params.js';\nimport { esriOperations } from './operations.js';\nimport { CURRENT_VERSION, layerMetadata, queryLayer, serviceMetadata } from './query.js';\nimport {\n configSchema,\n findLayer,\n guarded,\n logEdit,\n storeToken,\n presentedToken,\n sweep,\n type EsriConfig,\n type EsriFixture,\n type EsriState,\n type Handler,\n} from './tenants.js';\n\nexport type { EsriConfig, EsriFixture, EsriState };\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Routes\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst SERVICES = '/:tenant/arcgis/rest/services';\n/** The emulated portal's org id (`portals/self` id, the user's `orgId`). */\nconst ORG_ID = 'emulatedportal';\nconst FEATURE_SERVER = `${SERVICES}/:service/FeatureServer`;\nconst LAYER = `${FEATURE_SERVER}/:layer`;\n/** The longest token lifetime ArcGIS grants (14 days). */\nconst MAX_TOKEN_MINUTES = 20_160;\n\ntype EsriRoute = EmulationRoute<EsriFixture, EsriState>;\n\n/** A resource: either verb, with or without a trailing slash. */\nfunction resource(path: string, handler: Handler): EsriRoute[] {\n return [path, `${path}/`].flatMap((p): EsriRoute[] => [\n { method: 'GET', path: p, handler },\n { method: 'POST', path: p, handler },\n ]);\n}\n\n/** An operation: either verb, and like real ArcGIS any path after it is ignored (`query/`, `generateToken/x`). */\nfunction operation(path: string, handler: Handler): EsriRoute[] {\n return [\n { method: 'GET', path: `${path}/*`, handler },\n { method: 'POST', path: `${path}/*`, handler },\n ];\n}\n\nconst generateToken: Handler = (req, ctx) => {\n sweep(ctx.state);\n const p = readParams(req);\n const { config } = ctx.state;\n // Both comparisons always run so timing does not reveal which one failed.\n const userOk = tokensMatch(p.get('username') ?? '', config.username);\n const passOk = tokensMatch(p.get('password') ?? '', config.password);\n if (!userOk || !passOk) {\n return errorResponse(new EsriError(400, 'Unable to generate token.', ['Invalid username or password.']));\n }\n let ttlSeconds = config.tokenTtlSeconds;\n const expiration = p.get('expiration');\n if (expiration !== undefined && expiration !== '') {\n const minutes = Number(expiration);\n if (!Number.isFinite(minutes) || minutes <= 0) return errorResponse(badParameter('expiration'));\n ttlSeconds = Math.min(minutes, MAX_TOKEN_MINUTES) * 60;\n }\n const token = crypto.randomBytes(162).toString('base64url');\n const expires = Date.now() + ttlSeconds * 1000;\n storeToken(ctx.state, token, expires);\n return ok(p, { token, expires, ssl: true });\n};\n\nconst tokenViaGet: Handler = () =>\n errorResponse(new EsriError(405, 'Method not supported.', [], 'GWM_0005'));\n\nconst portalSelf: Handler = (req, ctx) =>\n ok(readParams(req), {\n id: ORG_ID,\n name: 'Emulated ArcGIS Portal',\n isPortal: false,\n urlKey: 'emulator',\n customBaseUrl: 'arcgis.com',\n portalHostname: ctx.state.config.host,\n supportsHostedServices: true,\n });\n\n/**\n * The signed-in user; a connection test can probe it to check its token. The errors match ArcGIS Online\n * (probed); the user is a minimal subset of its documented shape, extended when a client needs more.\n */\nconst communitySelf: Handler = (req, ctx) => {\n sweep(ctx.state);\n const p = readParams(req);\n const token = presentedToken(req, p);\n if (!token) return errorResponse(new EsriError(400, 'Not logged in.', [], 'COM_0019'));\n if (!ctx.state.tokens.has(token)) return errorResponse(new EsriError(498, 'Invalid token.'));\n const { username } = ctx.state.config;\n return ok(p, {\n username,\n id: 'emulateduser',\n fullName: 'Emulated User',\n email: `${username}@example.com`,\n orgId: ORG_ID,\n role: 'org_admin',\n disabled: false,\n });\n};\n\nconst restInfo: Handler = (req, ctx) =>\n ok(readParams(req), {\n currentVersion: CURRENT_VERSION,\n fullVersion: '11.2.0',\n owningSystemUrl: `https://${ctx.state.config.host}`,\n authInfo: {\n isTokenBasedSecurity: true,\n tokenServicesUrl: `https://${ctx.state.config.host}/sharing/rest/generateToken`,\n },\n });\n\nconst listServices = guarded((call) =>\n ok(call.p, {\n currentVersion: CURRENT_VERSION,\n folders: [],\n services: [...call.tenant.services.keys()].map((name) => ({ name, type: 'FeatureServer' })),\n })\n);\n\nconst getService = guarded((call) => {\n const layers = call.tenant.services.get(call.req.params['service']!);\n if (!layers) throw new EsriError(404, 'Service not found');\n return ok(call.p, serviceMetadata(layers));\n});\n\nconst getLayer = guarded((call) => ok(call.p, layerMetadata(findLayer(call))));\nconst queryHandler = guarded((call) => queryLayer(findLayer(call), call.p));\n\nconst applyEdits = guarded((call) => {\n const layer = findLayer(call);\n const { p } = call;\n const outcome = applyLayerEdits(\n layer,\n {\n adds: parseFeatures('adds', p.get('adds')),\n updates: parseFeatures('updates', p.get('updates')),\n deletes: parseIds('deletes', p.get('deletes')),\n },\n { useGlobalIds: flag(p, 'useGlobalIds'), rollbackOnFailure: flag(p, 'rollbackOnFailure', true) }\n );\n logEdit(call.tenant, {\n ts: new Date().toISOString(),\n source: 'connector',\n endpoint: 'applyEdits',\n service: call.req.params['service']!,\n layerId: layer.def.id,\n received: withoutCredentials(p.raw),\n results: outcome.results,\n rolledBack: !outcome.committed,\n });\n if (!outcome.committed) {\n return errorResponse(new EsriError(400, 'Unable to complete operation.', ['Operation rolled back.']));\n }\n return ok(p, outcome.results);\n});\n\n/** ArcGIS Online's answer to an unknown path. The request itself is in the proxy's log line and recorder. */\nconst catchAll: Handler = () => errorResponse(new EsriError(400, 'Invalid URL', [], 'GWM_0002'));\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Plugin\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const esriPlugin: EmulationPlugin<EsriConfig, EsriFixture, EsriState> = {\n id: 'esri',\n name: 'Esri ArcGIS REST API',\n version: '1.0.0',\n\n domains: (config) => [config.host.toLowerCase()],\n needsBrowserIntercept: false,\n\n routes: [\n // ── Token, portal health check, server info ─────────────────────────\n ...['', '/portal'].flatMap((prefix): EsriRoute[] => [\n // Not operation(): the token is POST only, a GET gets ArcGIS Online's refusal.\n { method: 'POST', path: `${prefix}/sharing/rest/generateToken/*`, handler: generateToken },\n { method: 'GET', path: `${prefix}/sharing/rest/generateToken/*`, handler: tokenViaGet },\n ...operation(`${prefix}/sharing/rest/portals/self`, portalSelf),\n ...operation(`${prefix}/sharing/rest/community/self`, communitySelf),\n ...operation(`${prefix}/sharing/rest/info`, restInfo),\n ]),\n ...resource('/arcgis/rest/info', restInfo),\n ...resource('/:tenant/arcgis/rest/info', restInfo),\n\n // ── Services, FeatureServer and layer metadata (token required) ─────\n ...resource(SERVICES, listServices),\n ...resource(FEATURE_SERVER, getService),\n ...resource(LAYER, getLayer),\n\n // ── Query and edits ─────────────────────────────────────────────────\n ...operation(`${LAYER}/query`, queryHandler),\n ...operation(`${LAYER}/applyEdits`, applyEdits),\n\n // ── Anything else: answered and recorded, so real traffic drives iteration\n { method: '*', path: '*', handler: catchAll },\n ],\n\n initialize(config) {\n return { config: configSchema.parse(config), tenants: new Map(), tokens: new Map() };\n },\n\n countActive(ctx, sinceMs) {\n sweep(ctx.state);\n return [...ctx.state.tenants.values()].filter((t) => t.touchedAt >= sinceMs).length;\n },\n\n controlReads: [\n {\n path: 'features',\n handler: (req, ctx) => {\n const q = req.url.searchParams;\n const layer = ctx.state.tenants\n .get(q.get('tenant') ?? '')\n ?.services.get(q.get('service') ?? '')\n ?.get(Number(q.get('layer')));\n if (!layer) return { status: 404, body: { error: 'Layer not found' } };\n return { status: 200, body: { features: layer.features } };\n },\n },\n {\n path: 'edits',\n handler: (req, ctx) => {\n const tenant = ctx.state.tenants.get(req.url.searchParams.get('tenant') ?? '');\n if (!tenant) return { status: 404, body: { error: 'Tenant not found' } };\n return { status: 200, body: { edits: tenant.edits } };\n },\n },\n ],\n\n operations: esriOperations,\n};\n","import { timingSafeEqual } from 'node:crypto';\n\n/** Constant-time bearer-token comparison. */\nexport function tokensMatch(provided: string, expected: string): boolean {\n const a = Buffer.from(provided);\n const b = Buffer.from(expected);\n if (a.length !== b.length) return false;\n return timingSafeEqual(a, b);\n}\n","/**\n * ArcGIS error envelope. Real ArcGIS answers errors as HTTP 200 with an `error` body.\n *\n * @module\n */\n\nimport type { EmulationResponse } from '../../plugin.js';\n\n/** Headers real ArcGIS Online sends on every JSON answer. */\nexport const JSON_HEADERS = {\n 'content-type': 'application/json;charset=utf-8',\n 'cache-control': 'no-cache',\n vary: 'Origin',\n 'x-content-type-options': 'nosniff',\n};\n\nexport class EsriError extends Error {\n constructor(\n readonly code: number,\n message: string,\n readonly details: string[] = [],\n /** ArcGIS Online's gateway code (`GWM_…`), sent only on the errors that carry one. */\n readonly messageCode?: string\n ) {\n super(message);\n }\n}\n\nexport function errorResponse(err: EsriError): EmulationResponse {\n // An absent messageCode is dropped when the body is serialized, as on real ArcGIS.\n return {\n status: 200,\n headers: JSON_HEADERS,\n body: { error: { code: err.code, messageCode: err.messageCode, message: err.message, details: err.details } },\n };\n}\n\nexport const badQuery = () =>\n new EsriError(400, 'Unable to complete operation.', ['Unable to perform query. Please check your parameters.']);\n\nexport const badParameter = (name: string) =>\n new EsriError(400, 'Unable to complete operation.', [`Invalid parameter: ${name}`]);\n","/**\n * Layer schema, features, and the edit semantics of applyEdits.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport { z } from 'zod';\nimport { isCredentialKey } from '../../credential-keys.js';\nimport { redactForLog } from '../../redact-json.js';\nimport { badParameter } from './errors.js';\nimport { parseDateLiteral, type Attributes } from './where.js';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Schema / State\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst fieldSchema = z.object({\n name: z.string().min(1),\n /** esriFieldType*, e.g. esriFieldTypeString */\n type: z.string().min(1),\n alias: z.string().optional(),\n nullable: z.boolean().default(true),\n editable: z.boolean().default(true),\n length: z.number().int().positive().optional(),\n});\ntype FieldDef = z.infer<typeof fieldSchema>;\n\nconst GEOMETRY_TYPES = [\n 'esriGeometryPoint',\n 'esriGeometryMultipoint',\n 'esriGeometryPolyline',\n 'esriGeometryPolygon',\n] as const;\n\nexport const layerDefSchema = z.object({\n id: z.number().int().nonnegative(),\n name: z.string().min(1),\n /** null makes the layer a table (no geometry). */\n geometryType: z.enum(GEOMETRY_TYPES).nullable(),\n fields: z.array(fieldSchema),\n objectIdField: z.string().min(1),\n globalIdField: z.string().min(1).optional(),\n maxRecordCount: z.number().int().positive().default(1000),\n});\nexport type LayerDef = z.infer<typeof layerDefSchema>;\n\nexport interface Feature {\n attributes: Attributes;\n geometry?: Record<string, unknown>;\n}\n\nexport interface LayerState {\n def: LayerDef;\n features: Feature[];\n nextObjectId: number;\n fieldsByLower: Map<string, FieldDef>;\n}\n\n/** One edit call as received, with what the emulator answered. */\nexport interface EditLogEntry {\n ts: string;\n /** `connector` for HTTP edits, `external` for the edit-feature operation. */\n source: 'connector' | 'external';\n endpoint: 'applyEdits' | 'edit-feature';\n service: string;\n layerId: number;\n /** Request params as received (credential keys removed). */\n received: Record<string, string>;\n results: unknown;\n rolledBack: boolean;\n}\n\nexport function createLayerState(def: LayerDef): LayerState {\n return {\n def,\n features: [],\n nextObjectId: 1,\n fieldsByLower: new Map(def.fields.map((f) => [f.name.toLowerCase(), f])),\n };\n}\n\nexport function fieldResolver(layer: LayerState): (name: string) => string | undefined {\n return (name) => layer.fieldsByLower.get(name.toLowerCase())?.name;\n}\n\nconst FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\nconst MAX_RECEIVED_VALUE = 4096;\nexport const MAX_FEATURES_PER_LAYER = 10_000;\n\n/** Request params safe to keep in the edit log: no credentials whatever their casing, long values truncated. */\nexport function withoutCredentials(raw: Record<string, string>): Record<string, string> {\n return Object.fromEntries(\n Object.entries(raw)\n .filter(([key]) => !isCredentialKey(key))\n .map(([key, value]) => {\n const safe = redactForLog(value);\n return [key, safe.length > MAX_RECEIVED_VALUE ? `${safe.slice(0, MAX_RECEIVED_VALUE)}…[truncated]` : safe];\n })\n );\n}\n\n/** Attribute keys in the layer's field-name casing, date strings as epoch ms, prototype keys dropped. */\nfunction canonicalAttributes(layer: LayerState, attributes: Attributes): Attributes {\n const out: Attributes = {};\n for (const [key, value] of Object.entries(attributes)) {\n if (FORBIDDEN_KEYS.has(key)) continue;\n const field = layer.fieldsByLower.get(key.toLowerCase());\n const isDate = field?.type === 'esriFieldTypeDate' && typeof value === 'string';\n out[field?.name ?? key] = isDate ? (parseDateLiteral(value) ?? value) : value;\n }\n return out;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Edits\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst FEATURE_NOT_FOUND = { code: 1019, description: 'Feature not found.' };\nconst DUPLICATE_GLOBAL_ID = { code: 1019, description: 'Duplicate GlobalID.' };\nconst LAYER_FULL = { code: 1019, description: `Layer is full (${MAX_FEATURES_PER_LAYER} features).` };\nconst INVALID_EDIT = { code: 1020, description: 'Invalid edit: missing identifier or attributes.' };\n\nconst MAX_IDS = 1000;\n\nfunction newGlobalId(): string {\n return `{${crypto.randomUUID().toUpperCase()}}`;\n}\n\nfunction normalizeGuid(value: unknown): string {\n return String(value).replace(/[{}]/g, '').toLowerCase();\n}\n\n/**\n * Append a feature; the ObjectID is the next free one unless a seed pins it.\n * A client-supplied GlobalID is kept only when `keepGlobalId`. Fails when it duplicates one or the layer is full.\n */\nexport function addFeature(\n layer: LayerState,\n input: Feature,\n opts: { objectId?: number; keepGlobalId: boolean }\n): { feature: Feature } | { error: { code: number; description: string } } {\n const { objectIdField, globalIdField } = layer.def;\n if (layer.features.length >= MAX_FEATURES_PER_LAYER) return { error: LAYER_FULL };\n const attributes = canonicalAttributes(layer, input.attributes);\n const objectId = opts.objectId ?? layer.nextObjectId;\n attributes[objectIdField] = objectId;\n if (globalIdField) {\n const supplied = attributes[globalIdField];\n attributes[globalIdField] = opts.keepGlobalId && typeof supplied === 'string' ? supplied : newGlobalId();\n const taken = layer.features.some(\n (f) => normalizeGuid(f.attributes[globalIdField]) === normalizeGuid(attributes[globalIdField])\n );\n if (taken) return { error: DUPLICATE_GLOBAL_ID };\n }\n layer.nextObjectId = Math.max(layer.nextObjectId, objectId + 1);\n const feature: Feature = { attributes, ...(input.geometry ? { geometry: input.geometry } : {}) };\n layer.features.push(feature);\n return { feature };\n}\n\nfunction idsOf(layer: LayerState, feature: Feature): { objectId: number; globalId: string | null } {\n const { objectIdField, globalIdField } = layer.def;\n return {\n objectId: feature.attributes[objectIdField] as number,\n globalId: globalIdField ? ((feature.attributes[globalIdField] as string | undefined) ?? null) : null,\n };\n}\n\nfunction findFeature(layer: LayerState, id: unknown, useGlobalIds: boolean): Feature | undefined {\n const { objectIdField, globalIdField } = layer.def;\n if (useGlobalIds && globalIdField) {\n return layer.features.find((f) => normalizeGuid(f.attributes[globalIdField]) === normalizeGuid(id));\n }\n return layer.features.find((f) => f.attributes[objectIdField] === Number(id));\n}\n\ninterface EditSet {\n adds?: Feature[];\n updates?: Feature[];\n deletes?: Array<string | number>;\n}\n\ninterface EditResult {\n objectId: number | null;\n globalId: string | null;\n success: boolean;\n error?: { code: number; description: string };\n}\n\ninterface EditOutcome {\n results: { addResults?: EditResult[]; updateResults?: EditResult[]; deleteResults?: EditResult[] };\n /** False when rollbackOnFailure undid the whole call. */\n committed: boolean;\n}\n\nfunction missing(id: unknown, useGlobalIds: boolean, error: EditResult['error']): EditResult {\n return {\n objectId: useGlobalIds ? null : Number(id),\n globalId: useGlobalIds ? String(id) : null,\n success: false,\n error,\n };\n}\n\n/**\n * Apply adds, then updates, then deletes to a working copy of the layer and commit it when every\n * edit succeeded, or when the caller opted out of rollback (then each edit stands on its own).\n */\nexport function applyLayerEdits(\n layer: LayerState,\n edits: EditSet,\n opts: { useGlobalIds: boolean; rollbackOnFailure: boolean }\n): EditOutcome {\n const { useGlobalIds } = opts;\n const { objectIdField, globalIdField } = layer.def;\n const work: LayerState = { ...layer, features: structuredClone(layer.features) };\n\n const addResults = edits.adds?.map((input): EditResult => {\n const added = addFeature(work, input, { keepGlobalId: useGlobalIds });\n if ('error' in added) return { objectId: null, globalId: null, success: false, error: added.error };\n return { ...idsOf(work, added.feature), success: true };\n });\n\n const updateResults = edits.updates?.map((input): EditResult => {\n const attributes = canonicalAttributes(work, input.attributes);\n const id = attributes[useGlobalIds && globalIdField ? globalIdField : objectIdField];\n if (id === undefined || id === null) return { objectId: null, globalId: null, success: false, error: INVALID_EDIT };\n const feature = findFeature(work, id, useGlobalIds);\n if (!feature) return missing(id, useGlobalIds, FEATURE_NOT_FOUND);\n // Delta update: only the sent fields change, and the identifiers never do.\n for (const [key, value] of Object.entries(attributes)) {\n if (key !== objectIdField && key !== globalIdField) feature.attributes[key] = value;\n }\n if (input.geometry) feature.geometry = input.geometry;\n return { ...idsOf(work, feature), success: true };\n });\n\n const deleteResults = edits.deletes?.map((id): EditResult => {\n const feature = findFeature(work, id, useGlobalIds);\n if (!feature) return missing(id, useGlobalIds, FEATURE_NOT_FOUND);\n work.features.splice(work.features.indexOf(feature), 1);\n return { ...idsOf(work, feature), success: true };\n });\n\n const all = [...(addResults ?? []), ...(updateResults ?? []), ...(deleteResults ?? [])];\n const committed = !opts.rollbackOnFailure || all.every((r) => r.success);\n if (committed) {\n layer.features = work.features;\n layer.nextObjectId = work.nextObjectId;\n }\n return { results: { addResults, updateResults, deleteResults }, committed };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Param parsing\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport function parseFeatures(name: string, value: string | undefined): Feature[] | undefined {\n if (value === undefined || value === '') return undefined;\n let parsed: unknown;\n try {\n parsed = JSON.parse(value);\n } catch {\n throw badParameter(name);\n }\n if (!Array.isArray(parsed)) throw badParameter(name);\n return parsed.map((item) => {\n if (typeof item !== 'object' || item === null) throw badParameter(name);\n const { attributes, geometry } = item as { attributes?: Attributes; geometry?: Record<string, unknown> };\n return { attributes: attributes ?? {}, ...(geometry ? { geometry } : {}) };\n });\n}\n\n/** `deletes` / `objectIds`: a JSON array or a comma-separated list, at most MAX_IDS. */\nexport function parseIds(name: string, value: string | undefined): Array<string | number> | undefined {\n if (value === undefined || value === '') return undefined;\n let ids: Array<string | number> | undefined;\n if (value.trim().startsWith('[')) {\n try {\n const parsed: unknown = JSON.parse(value);\n if (Array.isArray(parsed)) ids = parsed.map((v) => (typeof v === 'number' ? v : String(v)));\n } catch {\n // falls through to the bad-parameter error\n }\n } else {\n ids = value.split(',').map((v) => v.trim()).filter((v) => v !== '');\n }\n if (!ids || ids.length > MAX_IDS) throw badParameter(name);\n return ids;\n}\n","/** Normalised credential key names: lowercase with `-` and `_` removed, so `accessToken`, `access-token` and `access_token` match. */\nconst CREDENTIAL_KEYS: ReadonlySet<string> = new Set([\n 'token',\n 'password',\n 'passwd',\n 'secret',\n 'apikey',\n 'accesstoken',\n 'refreshtoken',\n 'idtoken',\n 'clientsecret',\n // AWS Secrets Manager writes (CreateSecret, PutSecretValue): the secret's value.\n 'secretstring',\n 'secretbinary',\n // AWS KMS Encrypt / GenerateDataKey: the plaintext being encrypted or the data key.\n 'plaintext',\n // Maximo native auth: the `_lpwd` password parameter, and MAXAUTH (base64 user:password) when sent as a parameter.\n 'lpwd',\n 'maxauth',\n]);\n\n/** Whether a parameter / JSON key holds a credential: its value is redacted from recordings and edit logs. */\nexport function isCredentialKey(key: string): boolean {\n return CREDENTIAL_KEYS.has(key.toLowerCase().replace(/[-_]/g, ''));\n}\n","import { isCredentialKey } from './credential-keys.js';\n\nconst MAX_REDACT_DEPTH = 64;\nexport const UNPARSEABLE_PAYLOAD = '[unparseable payload omitted]';\n\n/** Whether text looks like a JSON object or array payload. */\nexport function looksLikeJson(text: string): boolean {\n const trimmed = text.trimStart();\n return trimmed.startsWith('{') || trimmed.startsWith('[');\n}\n\n/** Walk parsed JSON, hiding credential-keyed values; anything deeper than the cap is hidden whole. */\nfunction redactNested(value: unknown, depth: number): unknown {\n if (depth > MAX_REDACT_DEPTH) return '[redacted]';\n if (Array.isArray(value)) return value.map((v) => redactNested(v, depth + 1));\n if (typeof value === 'object' && value !== null) {\n return Object.fromEntries(\n Object.entries(value).map(([key, v]) => [key, isCredentialKey(key) ? '[redacted]' : redactNested(v, depth + 1)])\n );\n }\n return value;\n}\n\n/**\n * A logged or recorded value: JSON payloads lose credential-keyed values at any depth; other text is kept.\n * It fails closed: JSON-looking text that cannot be parsed and walked is replaced, never kept as sent.\n */\nexport function redactForLog(text: string): string {\n if (!looksLikeJson(text)) return text;\n try {\n return JSON.stringify(redactNested(JSON.parse(text), 0));\n } catch {\n return UNPARSEABLE_PAYLOAD;\n }\n}\n","/**\n * Pure `where` clause compiler for the SQL-like filters ArcGIS clients send:\n * `1=1`, comparisons (= <> != < <= > >=), LIKE, IN, BETWEEN, IS [NOT] NULL,\n * NOT/AND/OR, parentheses, UPPER()/LOWER(), TIMESTAMP/DATE literals, and field names bare\n * or double-quoted (`\"WONUM\"`, standard SQL; matched case-insensitively like bare names).\n * Anything else, or a field the layer does not have, is a bad query.\n *\n * @module\n */\n\nimport { badQuery } from './errors.js';\n\nexport type Attributes = Record<string, unknown>;\ntype Predicate = (attrs: Attributes) => boolean;\ntype Operand = (attrs: Attributes) => unknown;\n\nconst MAX_WHERE_LENGTH = 4096;\nconst MAX_DEPTH = 32;\nconst MAX_LIKE_PATTERN = 256;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Values\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst DATE_LITERAL =\n /^(\\d{4})-(\\d{2})-(\\d{2})(?:[ T](\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d{1,3}))?)?)?\\s*(?:(Z)|([+-])(\\d{2}):?(\\d{2}))?$/i;\n\n/** `yyyy-mm-dd[ hh:mm[:ss[.fff]]][ Z|+hh:mm]` to epoch ms (no zone means UTC); null when it is not a date. */\nexport function parseDateLiteral(text: string): number | null {\n const m = DATE_LITERAL.exec(text.trim());\n if (!m) return null;\n const [month, day, hour, minute, second] = [m[2], m[3], m[4] ?? '0', m[5] ?? '0', m[6] ?? '0'].map(Number) as [\n number, number, number, number, number,\n ];\n if (month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 || minute > 59 || second > 59) return null;\n const fraction = (m[7] ?? '').padEnd(3, '0');\n const utc = Date.UTC(+m[1]!, +m[2]! - 1, +m[3]!, +(m[4] ?? 0), +(m[5] ?? 0), +(m[6] ?? 0), +fraction || 0);\n const offsetMinutes = m[9] ? (m[9] === '-' ? -1 : 1) * (+m[10]! * 60 + +m[11]!) : 0;\n const ms = utc - offsetMinutes * 60_000;\n return Number.isNaN(ms) ? null : ms;\n}\n\n/** Three-way compare; null when either side is null (SQL comparisons with NULL are never true). */\nfunction compareValues(left: unknown, right: unknown): number | null {\n if (left === null || left === undefined || right === null || right === undefined) return null;\n if (typeof left === 'number' || typeof right === 'number') {\n // An empty string is text, not zero.\n const l = left === '' ? NaN : Number(left);\n const r = right === '' ? NaN : Number(right);\n if (!Number.isNaN(l) && !Number.isNaN(r)) return l - r;\n }\n const l = String(left);\n const r = String(right);\n return l < r ? -1 : l > r ? 1 : 0;\n}\n\n/** Ordering for ORDER BY: nulls sort first ascending (so last descending). */\nexport function compareForSort(left: unknown, right: unknown): number {\n const leftNull = left === null || left === undefined;\n const rightNull = right === null || right === undefined;\n if (leftNull || rightNull) return leftNull === rightNull ? 0 : leftNull ? -1 : 1;\n return compareValues(left, right)!;\n}\n\n/**\n * SQL LIKE (`%` any run, `_` any one char, case-sensitive) without a RegExp: the two-pointer\n * walk with star backtracking is O(value x pattern), so no pattern can stall the host.\n */\nfunction likeMatcher(pattern: string): (value: string) => boolean {\n if (pattern.length > MAX_LIKE_PATTERN) throw badQuery();\n const p = pattern.replace(/%+/g, '%');\n return (s) => {\n let si = 0;\n let pi = 0;\n let star = -1;\n let mark = 0;\n while (si < s.length) {\n if (p[pi] === '%') {\n star = pi++;\n mark = si;\n } else if (pi < p.length && (p[pi] === '_' || p[pi] === s[si])) {\n pi++;\n si++;\n } else if (star !== -1) {\n pi = star + 1;\n si = ++mark;\n } else {\n return false;\n }\n }\n while (p[pi] === '%') pi++;\n return pi === p.length;\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Lexer\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** `field` is a double-quoted identifier: always a field name, never a keyword or function. */\ntype WhereToken = { kind: 'str' | 'num' | 'id' | 'field' | 'op' | 'punct'; value: string };\n\n/** Words after which a `-` starts a negative number rather than subtracting. */\nconst OPERATOR_WORDS = new Set(['AND', 'OR', 'NOT', 'BETWEEN', 'LIKE', 'IN', 'IS']);\n\nconst NUMBER = /-?\\d+(?:\\.\\d+)?/y;\nconst OPERATOR = /<=|>=|<>|!=|=|<|>/y;\nconst IDENTIFIER = /[A-Za-z_][A-Za-z0-9_.]*/y;\n\nfunction matchAt(re: RegExp, input: string, at: number): string | null {\n re.lastIndex = at;\n return re.exec(input)?.[0] ?? null;\n}\n\n/** A `quote`-delimited token starting at `start` (a doubled quote is a literal one): its value and the index after it. */\nfunction readQuoted(input: string, start: number, quote: string): { value: string; end: number } {\n let value = '';\n let i = start + 1;\n for (;;) {\n const close = input.indexOf(quote, i);\n if (close === -1) throw badQuery();\n value += input.substring(i, close);\n if (input[close + 1] !== quote) return { value, end: close + 1 };\n value += quote;\n i = close + 2;\n }\n}\n\n/** Linear in the input length: every step advances the index. */\nfunction tokenize(input: string): WhereToken[] {\n const tokens: WhereToken[] = [];\n let i = 0;\n while (i < input.length) {\n const ch = input[i]!;\n if (ch === ' ' || ch === '\\t' || ch === '\\n' || ch === '\\r') {\n i++;\n } else if (ch === \"'\" || ch === '\"') {\n const { value, end } = readQuoted(input, i, ch);\n // ArcGIS rejects an empty quoted identifier.\n if (ch === '\"' && value === '') throw badQuery();\n tokens.push({ kind: ch === \"'\" ? 'str' : 'field', value });\n i = end;\n } else if (ch === '(' || ch === ')' || ch === ',') {\n tokens.push({ kind: 'punct', value: ch });\n i++;\n } else {\n const prev = tokens[tokens.length - 1];\n const afterValue =\n prev !== undefined &&\n (prev.kind === 'num' ||\n prev.kind === 'str' ||\n prev.kind === 'field' ||\n (prev.kind === 'punct' && prev.value === ')') ||\n (prev.kind === 'id' && !OPERATOR_WORDS.has(prev.value.toUpperCase())));\n const number = matchAt(NUMBER, input, i);\n const op = matchAt(OPERATOR, input, i);\n const id = matchAt(IDENTIFIER, input, i);\n if (number && (ch !== '-' || !afterValue)) {\n tokens.push({ kind: 'num', value: number });\n i += number.length;\n } else if (op) {\n tokens.push({ kind: 'op', value: op });\n i += op.length;\n } else if (id) {\n tokens.push({ kind: 'id', value: id });\n i += id.length;\n } else {\n throw badQuery();\n }\n }\n }\n return tokens;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Parser\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst COMPARATORS: Record<string, (c: number) => boolean> = {\n '=': (c) => c === 0,\n '<>': (c) => c !== 0,\n '!=': (c) => c !== 0,\n '<': (c) => c < 0,\n '<=': (c) => c <= 0,\n '>': (c) => c > 0,\n '>=': (c) => c >= 0,\n};\n\nconst isNull = (value: unknown) => value === null || value === undefined;\n\nexport function compileWhere(where: string, resolveField: (name: string) => string | undefined): Predicate {\n if (where.length > MAX_WHERE_LENGTH) throw badQuery();\n const tokens = tokenize(where);\n let pos = 0;\n let depth = 0;\n\n const peek = () => tokens[pos];\n const isKeyword = (token: WhereToken | undefined, word: string) =>\n token?.kind === 'id' && token.value.toUpperCase() === word;\n const eatKeyword = (word: string) => {\n if (!isKeyword(peek(), word)) return false;\n pos++;\n return true;\n };\n const eatPunct = (value: string) => {\n const token = peek();\n if (token?.kind !== 'punct' || token.value !== value) return false;\n pos++;\n return true;\n };\n\n function operand(): Operand {\n const token = tokens[pos++];\n if (!token) throw badQuery();\n if (token.kind === 'str') return () => token.value;\n if (token.kind === 'num') return () => Number(token.value);\n if (token.kind === 'field') return fieldOperand(token.value);\n if (token.kind !== 'id') throw badQuery();\n const upper = token.value.toUpperCase();\n if ((upper === 'TIMESTAMP' || upper === 'DATE') && peek()?.kind === 'str') {\n const ms = parseDateLiteral(tokens[pos++]!.value);\n if (ms === null) throw badQuery();\n return () => ms;\n }\n if ((upper === 'UPPER' || upper === 'LOWER') && eatPunct('(')) {\n const inner = operand();\n if (!eatPunct(')')) throw badQuery();\n return (attrs) => {\n const value = inner(attrs);\n if (isNull(value)) return null;\n return upper === 'UPPER' ? String(value).toUpperCase() : String(value).toLowerCase();\n };\n }\n return fieldOperand(token.value);\n }\n\n function fieldOperand(name: string): Operand {\n const field = resolveField(name);\n if (!field) throw badQuery();\n return (attrs) => attrs[field];\n }\n\n function comparison(): Predicate {\n const left = operand();\n const next = peek();\n if (next?.kind === 'op') {\n pos++;\n const right = operand();\n const check = COMPARATORS[next.value]!;\n return (attrs) => {\n const c = compareValues(left(attrs), right(attrs));\n return c !== null && check(c);\n };\n }\n if (eatKeyword('IS')) {\n const negate = eatKeyword('NOT');\n if (!eatKeyword('NULL')) throw badQuery();\n return (attrs) => isNull(left(attrs)) !== negate;\n }\n const negate = eatKeyword('NOT');\n if (eatKeyword('LIKE')) {\n // A literal pattern is compiled once; a computed one per row.\n const literal = peek()?.kind === 'str' ? likeMatcher(peek()!.value) : null;\n const right = operand();\n return (attrs) => {\n const value = left(attrs);\n if (isNull(value)) return false;\n const match = literal ?? likeMatcher(String(right(attrs)));\n return match(String(value)) !== negate;\n };\n }\n if (eatKeyword('BETWEEN')) {\n const low = operand();\n if (!eatKeyword('AND')) throw badQuery();\n const high = operand();\n return (attrs) => {\n const value = left(attrs);\n const lo = compareValues(value, low(attrs));\n const hi = compareValues(value, high(attrs));\n if (lo === null || hi === null) return false;\n return (lo >= 0 && hi <= 0) !== negate;\n };\n }\n if (eatKeyword('IN')) {\n if (!eatPunct('(')) throw badQuery();\n const items = [operand()];\n while (eatPunct(',')) items.push(operand());\n if (!eatPunct(')')) throw badQuery();\n return (attrs) => {\n const value = left(attrs);\n if (isNull(value)) return false;\n return items.some((item) => compareValues(value, item(attrs)) === 0) !== negate;\n };\n }\n throw badQuery();\n }\n\n function unary(): Predicate {\n if (++depth > MAX_DEPTH) throw badQuery();\n try {\n if (eatKeyword('NOT')) {\n const inner = unary();\n return (attrs) => !inner(attrs);\n }\n if (eatPunct('(')) {\n const inner = or();\n if (!eatPunct(')')) throw badQuery();\n return inner;\n }\n return comparison();\n } finally {\n depth--;\n }\n }\n\n function and(): Predicate {\n const parts = [unary()];\n while (eatKeyword('AND')) parts.push(unary());\n return (attrs) => parts.every((part) => part(attrs));\n }\n\n function or(): Predicate {\n const parts = [and()];\n while (eatKeyword('OR')) parts.push(and());\n return (attrs) => parts.some((part) => part(attrs));\n }\n\n const predicate = or();\n if (pos !== tokens.length) throw badQuery();\n return predicate;\n}\n","/**\n * Request params: query string plus urlencoded form body, names case-insensitive.\n *\n * @module\n */\n\nimport { JSON_HEADERS } from './errors.js';\nimport type { EmulationRequest, EmulationResponse } from '../../plugin.js';\n\nexport interface Params {\n raw: Record<string, string>;\n get(name: string): string | undefined;\n}\n\nexport function readParams(req: EmulationRequest): Params {\n const raw: Record<string, string> = {};\n req.url.searchParams.forEach((value, key) => {\n raw[key] = value;\n });\n if (req.body) {\n new URLSearchParams(req.body).forEach((value, key) => {\n raw[key] = value;\n });\n }\n const lower = new Map(Object.entries(raw).map(([key, value]) => [key.toLowerCase(), value]));\n return { raw, get: (name) => lower.get(name.toLowerCase()) };\n}\n\n/** A boolean param; 'True' and 'true' are the same. */\nexport function flag(p: Params, name: string, whenAbsent = false): boolean {\n const value = p.get(name);\n return value === undefined ? whenAbsent : value.toLowerCase() === 'true';\n}\n\n/** `f=pjson` pretty-prints; every other format is compact JSON. */\nexport function ok(p: Params, body: object): EmulationResponse {\n if (p.get('f')?.toLowerCase() === 'pjson') {\n return { status: 200, headers: JSON_HEADERS, body: JSON.stringify(body, null, 2) };\n }\n return { status: 200, headers: JSON_HEADERS, body };\n}\n","/**\n * Esri emulator operations: seed a tenant's layer, simulate a GIS user's edit, drop a tenant.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport { z } from 'zod';\nimport { redactForLog } from '../../redact-json.js';\nimport { OperationInputError, type EmulationOperationDef } from '../../plugin.js';\nimport {\n addFeature,\n applyLayerEdits,\n createLayerState,\n layerDefSchema,\n type LayerState,\n} from './layers.js';\nimport { createTenant, logEdit, sweep, type EsriCtx, type EsriFixture, type EsriState } from './tenants.js';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Operations\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Names become path segments; a leading `_` would collide with `/_emulation`. */\nconst nameSchema = z.string().regex(/^[A-Za-z0-9][A-Za-z0-9_-]*$/);\n\nconst seedInput = z.object({\n /** Omit to create a fresh random tenant; a named tenant must already exist (to add another layer to it). */\n tenant: nameSchema.optional(),\n service: nameSchema.optional(),\n layer: layerDefSchema,\n features: z.array(\n z.object({\n attributes: z.record(z.string(), z.unknown()),\n geometry: z.record(z.string(), z.unknown()).optional(),\n })\n ),\n});\n\nconst seedOutput = z.object({\n tenant: z.string(),\n service: z.string(),\n layer: z.number(),\n baseUrl: z.string(),\n layerUrl: z.string(),\n});\n\nconst editFeatureInput = z.object({\n tenant: nameSchema,\n service: nameSchema,\n layer: z.number().int().nonnegative(),\n objectId: z.number().int(),\n attributes: z.record(z.string(), z.unknown()),\n});\n\nconst dropTenantInput = z.object({ tenant: nameSchema });\n\nfunction randomName(prefix: string): string {\n return `${prefix}${crypto.randomBytes(6).toString('hex')}`;\n}\n\nexport const esriOperations: EmulationOperationDef<EsriFixture, EsriState>[] = [\n {\n id: 'seed-layer',\n description:\n 'Create (or replace) a layer with features. Without a tenant, creates a fresh random tenant; a named tenant must already exist.',\n input: seedInput,\n output: seedOutput,\n handler: (ctx: EsriCtx, raw) => {\n const input = raw as z.infer<typeof seedInput>;\n sweep(ctx.state);\n const tenantName = input.tenant ?? randomName('t');\n const tenant = input.tenant ? ctx.state.tenants.get(input.tenant) : createTenant(ctx.state, tenantName);\n if (!tenant) throw new OperationInputError(`Tenant not found: ${input.tenant} (omit tenant to create one)`);\n tenant.touchedAt = Date.now();\n\n const layer = createLayerState(input.layer);\n for (const seeded of input.features) {\n const supplied = seeded.attributes[layer.def.objectIdField];\n const added = addFeature(layer, seeded, {\n objectId: typeof supplied === 'number' ? supplied : undefined,\n keepGlobalId: true,\n });\n if ('error' in added) throw new OperationInputError(`Cannot seed features: ${added.error.description}`);\n }\n\n const serviceName = input.service ?? randomName('svc');\n const layers = tenant.services.get(serviceName) ?? new Map<number, LayerState>();\n layers.set(layer.def.id, layer);\n tenant.services.set(serviceName, layers);\n\n const baseUrl = `https://${ctx.state.config.host}/${tenantName}/arcgis/rest/services`;\n return {\n tenant: tenantName,\n service: serviceName,\n layer: layer.def.id,\n baseUrl,\n layerUrl: `${baseUrl}/${serviceName}/FeatureServer/${layer.def.id}`,\n };\n },\n },\n {\n id: 'edit-feature',\n description: 'Simulate a GIS user editing a feature: merges the attributes and logs the edit with source \"external\".',\n input: editFeatureInput,\n output: z.object({ objectId: z.number() }),\n handler: (ctx: EsriCtx, raw) => {\n const input = raw as z.infer<typeof editFeatureInput>;\n sweep(ctx.state);\n const tenant = ctx.state.tenants.get(input.tenant);\n const layer = tenant?.services.get(input.service)?.get(input.layer);\n if (!tenant || !layer) {\n throw new OperationInputError(`Layer not found: ${input.tenant}/${input.service}/${input.layer}`);\n }\n const outcome = applyLayerEdits(\n layer,\n { updates: [{ attributes: { ...input.attributes, [layer.def.objectIdField]: input.objectId } }] },\n { useGlobalIds: false, rollbackOnFailure: true }\n );\n if (!outcome.committed) throw new OperationInputError(`Feature not found: ${input.objectId}`);\n tenant.touchedAt = Date.now();\n logEdit(tenant, {\n ts: new Date().toISOString(),\n source: 'external',\n endpoint: 'edit-feature',\n service: input.service,\n layerId: input.layer,\n received: { objectId: String(input.objectId), attributes: redactForLog(JSON.stringify(input.attributes)) },\n results: outcome.results,\n rolledBack: false,\n });\n return { objectId: input.objectId };\n },\n },\n {\n id: 'drop-tenant',\n description: 'Drop a tenant and everything in it (flow cleanup).',\n input: dropTenantInput,\n output: z.object({ dropped: z.boolean() }),\n handler: (ctx: EsriCtx, raw) => {\n const input = raw as z.infer<typeof dropTenantInput>;\n return { dropped: ctx.state.tenants.delete(input.tenant) };\n },\n },\n];\n","/**\n * Emulation Plugin Interface\n *\n * Defines the contract for emulation plugins that intercept external service\n * traffic in sandboxed test environments. Each plugin is a self-contained module\n * that declares which domains to intercept and how to respond.\n *\n * Plugins can have two components:\n * 1. Sandbox-side (always): HTTP handlers for server-to-server calls (token exchange, API calls)\n * 2. Browser-side (optional): Playwright context.route() handlers for browser-level interception (OAuth redirects)\n *\n * @module\n */\n\nimport type { ZodType } from 'zod';\nimport type { EnvContractEntry } from './env-contract.js';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Request / Response\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** An HTTP request as seen by the emulation router. */\nexport interface EmulationRequest {\n method: string;\n url: URL;\n headers: Record<string, string>;\n body?: string;\n /** Path parameters extracted by the router (e.g., { issueKey: 'PROJ-123' }) */\n params: Record<string, string>;\n}\n\n/** An HTTP response returned by a plugin handler. */\nexport interface EmulationResponse {\n status: number;\n headers?: Record<string, string>;\n /** String body or object (auto-serialized to JSON with Content-Type: application/json) */\n body?: string | object;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Plugin Context\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Runtime context provided to plugin route handlers.\n * Contains fixture data and mutable state that persists across requests\n * within a sandbox's lifetime.\n */\nexport interface PluginContext<TFixture = unknown, TState = unknown> {\n /** Immutable fixture data configured for this emulation instance */\n fixture: TFixture;\n /** Mutable state that persists across requests (e.g., created Jira issues) */\n state: TState;\n /** Sandbox instance ID */\n sandboxId: string;\n /** Resolved env-contract values (e.g., signingSecret) shared with the sandboxed app */\n env: Record<string, string>;\n log: (level: 'debug' | 'info' | 'warn' | 'error', msg: string) => void;\n instance: {\n /** Public origin of each public port of this copy, by port name (e.g. `emulation`, `web`). */\n publicOrigins: Record<string, string>;\n /** The copy's control-plane secret (EmulationInstanceConfig.controlPlane.token). Plugins must never log or echo it. */\n controlToken: string;\n };\n}\n\n/** Thrown by an operation handler for input the caller got wrong; the control plane answers 400 with the message. */\nexport class OperationInputError extends Error {}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Routes\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Route handler function. Return null to pass through to the real service. */\nexport type RouteHandler<TFixture = unknown, TState = unknown> = (\n req: EmulationRequest,\n ctx: PluginContext<TFixture, TState>\n) => EmulationResponse | null | Promise<EmulationResponse | null>;\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | '*';\n\n/** A declared sandbox-side route that the plugin handles. */\nexport interface EmulationRoute<TFixture = unknown, TState = unknown> {\n method: HttpMethod;\n /** Path pattern with express-style params (e.g., /rest/api/3/issue/:issueKey); a trailing `/*` also matches any further path */\n path: string;\n /** Handler function */\n handler: RouteHandler<TFixture, TState>;\n}\n\n/**\n * Minimal abstraction over Playwright's Route object.\n * Identical to ContextRouteHandle in @chatsdet/browser-core — defined here\n * to avoid a hard dependency from the emulation package to browser-core.\n */\nexport interface BrowserRouteHandle {\n fulfill(opts: {\n status?: number;\n headers?: Record<string, string>;\n body?: string;\n }): Promise<void>;\n continue(): Promise<void>;\n request(): {\n url(): string;\n method(): string;\n postData(): string | null;\n };\n}\n\n/** Browser-side route declaration for Playwright context.route(). */\nexport interface BrowserRoute<TFixture = unknown> {\n /** URL pattern for Playwright context.route() (glob or regex) */\n urlPattern: string | RegExp;\n handler: (route: BrowserRouteHandle, fixture: TFixture) => Promise<void>;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Control-Plane Declarations\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * An inbound event the emulator can fire INTO the sandboxed app\n * (e.g., a signed Slack `app_mention` webhook). `build` produces the full\n * signed HTTP request; signing (HMAC etc.) happens inside `build` using the\n * resolved env-contract values, at fire time, so timestamp windows hold.\n */\nexport interface InboundEventDef {\n /** Event identifier (e.g., 'app-mention') */\n id: string;\n description: string;\n /** Zod schema for the fire params */\n paramsSchema: ZodType;\n build(opts: {\n params: unknown;\n env: Record<string, string>;\n targetPath: string;\n /** Current fixture of the plugin (for defaults like team ids) */\n fixture: unknown;\n }): {\n method: string;\n /** Request path on the app (defaults to targetPath) */\n path: string;\n headers: Record<string, string>;\n body: string;\n };\n}\n\n/**\n * A read-only control endpoint the plugin exposes for assertions\n * (served as GET /_emulation/plugins/:pluginId/<path>).\n */\nexport interface ControlReadDef<TFixture = unknown, TState = unknown> {\n /** Path segment under the plugin's control namespace (e.g., 'posted-messages') */\n path: string;\n handler: (\n req: EmulationRequest,\n ctx: PluginContext<TFixture, TState>\n ) => EmulationResponse;\n}\n\n/**\n * A typed operation the plugin exposes for generic invocation via\n * `POST /_emulation/plugins/:pluginId/operations/:opId` — the framework\n * consumers (Cofactor actions, tests) call generically as `<plugin>.<op>`\n * without knowing the plugin's internals. Distinct from `ControlReadDef`\n * (GET-only, no input) and `ActionInterfaceDef` (a contract implemented\n * outside the emulator) — an operation is both declared AND executed here.\n */\nexport interface EmulationOperationDef<TFixture = unknown, TState = unknown> {\n /** Lowercase kebab id, unique per plugin, e.g. 'sent-emails' */\n id: string;\n description: string;\n /** Zod schema of the operation input object */\n input: ZodType;\n /** Zod schema of the result object */\n output: ZodType;\n /** Handler receives the validated input */\n handler: (\n ctx: PluginContext<TFixture, TState>,\n input: unknown\n ) => unknown | Promise<unknown>;\n}\n\n/**\n * A predefined sandbox-action contract the plugin publishes. The emulator\n * does NOT create actions — the template owner implements each interface as\n * a normal sandbox_action (only they know app specifics like webhook paths),\n * starting from `scaffoldScript`.\n */\nexport interface ActionInterfaceDef {\n /** Action slug the implementation must use (lowercase alphanumeric + hyphens) */\n slug: string;\n label: string;\n description: string;\n /** JSON Schema for the action's params */\n inputSchema: Record<string, unknown>;\n /** JSON Schema for the action's outputs */\n outputSchema: Record<string, unknown>;\n /**\n * Bash starting point for the implementation. May reference\n * $EMULATION_BASE_URL and $EMULATION_CONTROL_TOKEN (exported by the action\n * runner) and must print the JSON result as the last stdout line.\n */\n scaffoldScript: string;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Plugin Interface\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * The core plugin interface. Each emulation (Google OAuth, Jira, Stripe, etc.)\n * implements this as a self-contained module.\n *\n * Type parameters:\n * - TConfig: Plugin-specific configuration (e.g., tenant name, client IDs)\n * - TFixture: Seed data for the emulation (e.g., users, issues, projects)\n * - TState: Mutable runtime state derived from fixture data\n */\nexport interface EmulationPlugin<\n TConfig = unknown,\n TFixture = unknown,\n TState = unknown,\n> {\n /** Unique plugin identifier (e.g., 'google-oauth', 'jira', 'stripe') */\n readonly id: string;\n\n /** Human-readable name */\n readonly name: string;\n\n /** Version string */\n readonly version: string;\n\n /**\n * Domains this plugin intercepts.\n * Used for Docker network aliases (DNS override) and TLS cert generation.\n *\n * Can be a static list or a function of config for tenant-specific domains\n * (e.g., `(config) => [\\`${config.tenant}.atlassian.net\\`]`).\n */\n domains: string[] | ((config: TConfig) => string[]);\n\n /** Serve requests whose Host is not a registered domain (the copy's public emulator address). */\n readonly servesPublicOrigin?: boolean;\n\n /** Sandbox-side endpoint handlers */\n routes: EmulationRoute<TFixture, TState>[];\n\n /** Whether this plugin needs browser-side intercepts (e.g., OAuth redirects) */\n readonly needsBrowserIntercept: boolean;\n\n /**\n * Browser-side routes for Playwright context.route().\n * Only called when `needsBrowserIntercept` is true.\n */\n getBrowserRoutes?(fixture: TFixture): BrowserRoute<TFixture>[];\n\n /**\n * Initialize mutable runtime state from config and fixture data.\n * Called once when the emulation service starts, and again when the\n * control plane replaces the fixture.\n *\n * `env` carries resolved env-contract values (absent for plugins without\n * a contract, or when invoked by pre-contract callers).\n */\n initialize(config: TConfig, fixture: TFixture, env?: Record<string, string>): TState;\n\n /**\n * Zod schema of the plugin's config (a definition's `emulation.<id>` block).\n * When present, definition validation reports config problems at their path\n * instead of the emulator failing at boot. Plugins whose config is a few\n * loose options omit it.\n */\n configSchema?: ZodType;\n\n /**\n * Whether string values in this plugin's config may hold `${params.NAME}`\n * and `${secrets.NAME}`, resolved inside the sandbox at prepare (see the\n * sandbox helper's `emulation-refs.ts`). Only for plugins whose domains and\n * env contract never depend on a referenced value: the API computes those\n * from the unresolved config.\n */\n readonly configReferences?: boolean;\n\n /** Default fixture data for quick setup */\n defaultFixture?: TFixture;\n\n /** Zod schema validating TFixture (drives control-plane fixture writes) */\n fixtureSchema?: ZodType<TFixture>;\n\n /** Logical values shared between emulator and app (resolved at provision) */\n envContract?: EnvContractEntry[];\n\n /** Inbound events the control plane can fire into the app */\n inboundEvents?: InboundEventDef[];\n\n /** Read-only control endpoints for assertions */\n controlReads?: ControlReadDef<TFixture, TState>[];\n\n /**\n * How many tenants (isolated state partitions) were used at or after `sinceMs`\n * (epoch ms). Feeds the control plane's `/_emulation/active` idle gate; plugins\n * without tenants omit it.\n */\n countActive?(ctx: PluginContext<TFixture, TState>, sinceMs: number): number;\n\n /** Typed operations invocable generically as `<pluginId>.<opId>` */\n operations?: EmulationOperationDef<TFixture, TState>[];\n\n /** Predefined sandbox-action contracts for template owners to implement */\n actionInterfaces?: ActionInterfaceDef[];\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Resolve domains from a plugin given its config. */\nexport function resolvePluginDomains<TConfig>(\n plugin: Pick<EmulationPlugin<TConfig>, 'domains'>,\n config: TConfig\n): string[] {\n return typeof plugin.domains === 'function'\n ? plugin.domains(config)\n : plugin.domains;\n}\n","/**\n * Esri emulator config, per-tenant state, token store and expiry.\n *\n * @module\n */\n\nimport { z } from 'zod';\nimport {\n OperationInputError,\n type EmulationRequest,\n type EmulationResponse,\n type PluginContext,\n type RouteHandler,\n} from '../../plugin.js';\nimport { EsriError, errorResponse } from './errors.js';\nimport type { EditLogEntry, LayerState } from './layers.js';\nimport { readParams, type Params } from './params.js';\n\nexport const configSchema = z.object({\n /** Public hostname the connector is pointed at (Service Base URL and Token URL). */\n host: z.string().min(1),\n /** The username/password the connector's connection is configured with. Make the password long and random. */\n username: z.string().min(1),\n password: z.string().min(24),\n /** Lifetime of a generated token unless the request asks for `expiration`. */\n tokenTtlSeconds: z.number().int().positive().default(3600),\n /** A tenant untouched for this long is dropped. */\n tenantTtlMinutes: z.number().positive().default(360),\n /** A tenant older than this is dropped however recently it was used; bounds memory and lets the idle gate settle. */\n tenantMaxAgeMinutes: z.number().positive().default(1440),\n});\n\nexport type EsriConfig = z.input<typeof configSchema>;\n\n/** Tenants are created through operations, never through the fixture. */\nexport type EsriFixture = Record<string, never>;\n\nconst EDIT_LOG_LIMIT = 1000;\nconst MAX_TENANTS = 100;\nconst MAX_TOKENS = 1000;\n\ninterface TenantState {\n services: Map<string, Map<number, LayerState>>;\n edits: EditLogEntry[];\n createdAt: number;\n touchedAt: number;\n}\n\nexport interface EsriState {\n config: z.output<typeof configSchema>;\n tenants: Map<string, TenantState>;\n /** token -> expiry (epoch ms). Tokens and the credential are global, not per tenant. */\n tokens: Map<string, number>;\n}\n\nexport type EsriCtx = PluginContext<EsriFixture, EsriState>;\nexport type Handler = RouteHandler<EsriFixture, EsriState>;\n\n/** Drop tenants idle past the TTL or older than the max age, and expired tokens. */\nexport function sweep(state: EsriState): void {\n const now = Date.now();\n const idleMs = state.config.tenantTtlMinutes * 60_000;\n const maxAgeMs = state.config.tenantMaxAgeMinutes * 60_000;\n for (const [name, tenant] of state.tenants) {\n if (now - tenant.touchedAt > idleMs || now - tenant.createdAt > maxAgeMs) state.tenants.delete(name);\n }\n for (const [token, expires] of state.tokens) {\n if (expires <= now) state.tokens.delete(token);\n }\n}\n\nexport function createTenant(state: EsriState, name: string): TenantState {\n if (state.tenants.size >= MAX_TENANTS) {\n throw new OperationInputError(`Too many tenants (${MAX_TENANTS}); drop one with drop-tenant first`);\n }\n const now = Date.now();\n const tenant: TenantState = { services: new Map(), edits: [], createdAt: now, touchedAt: now };\n state.tenants.set(name, tenant);\n return tenant;\n}\n\nexport function findLayer(call: TenantCall): LayerState {\n const layers = call.tenant.services.get(call.req.params['service']!);\n if (!layers) throw new EsriError(404, 'Service not found');\n const layer = layers.get(Number(call.req.params['layer']));\n if (!layer) throw new EsriError(400, 'Invalid or missing input parameters.');\n return layer;\n}\n\nexport function logEdit(tenant: TenantState, entry: EditLogEntry): void {\n tenant.edits.push(entry);\n if (tenant.edits.length > EDIT_LOG_LIMIT) tenant.edits.shift();\n}\n\n/** Remember a token; beyond MAX_TOKENS the oldest are forgotten. */\nexport function storeToken(state: EsriState, token: string, expires: number): void {\n state.tokens.set(token, expires);\n for (const oldest of state.tokens.keys()) {\n if (state.tokens.size <= MAX_TOKENS) break;\n state.tokens.delete(oldest);\n }\n}\n\nfunction bearer(value: string | undefined): string | undefined {\n const match = value ? /^bearer\\s+(.+)$/i.exec(value) : null;\n return match?.[1]?.trim();\n}\n\n/** The token a request presents: `token` param, Authorization, or X-Esri-Authorization. */\nexport function presentedToken(req: EmulationRequest, p: Params): string | undefined {\n return p.get('token') || bearer(req.headers['authorization']) || bearer(req.headers['x-esri-authorization']);\n}\n\ninterface TenantCall {\n req: EmulationRequest;\n ctx: EsriCtx;\n p: Params;\n tenantName: string;\n tenant: TenantState;\n}\n\n/** Token check, tenant lookup and touch, and EsriError -> error-body conversion for `/:tenant/...` routes. */\nexport function guarded(fn: (call: TenantCall) => EmulationResponse): Handler {\n return (req, ctx) => {\n const state = ctx.state;\n sweep(state);\n const p = readParams(req);\n try {\n const token = presentedToken(req, p);\n if (!token) throw new EsriError(499, 'Token Required');\n if (!state.tokens.has(token)) throw new EsriError(498, 'Invalid token.');\n const tenantName = req.params['tenant']!;\n const tenant = state.tenants.get(tenantName);\n if (!tenant) throw new EsriError(404, 'Item does not exist or is inaccessible.');\n tenant.touchedAt = Date.now();\n return fn({ req, ctx, p, tenantName, tenant });\n } catch (err) {\n if (err instanceof EsriError) return errorResponse(err);\n throw err;\n }\n };\n}\n","/**\n * Service/layer metadata and the `query` operation.\n *\n * @module\n */\n\nimport type { EmulationResponse } from '../../plugin.js';\nimport { badParameter, badQuery } from './errors.js';\nimport { fieldResolver, parseIds, type LayerDef, type LayerState } from './layers.js';\nimport { flag, ok, type Params } from './params.js';\nimport { compareForSort, compileWhere } from './where.js';\n\nexport const CURRENT_VERSION = 11.2;\nconst SPATIAL_REFERENCE = { wkid: 4326, latestWkid: 4326 };\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Metadata\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction layerSummary(layer: LayerState) {\n return {\n id: layer.def.id,\n name: layer.def.name,\n parentLayerId: -1,\n defaultVisibility: true,\n subLayerIds: null,\n geometryType: layer.def.geometryType ?? undefined,\n };\n}\n\nfunction fieldMetadata(def: LayerDef) {\n return def.fields.map((f) => ({\n name: f.name,\n type: f.type,\n alias: f.alias ?? f.name,\n nullable: f.nullable,\n editable: f.editable,\n ...(f.length !== undefined ? { length: f.length } : {}),\n }));\n}\n\nexport function serviceMetadata(layers: Map<number, LayerState>) {\n const all = [...layers.values()];\n return {\n currentVersion: CURRENT_VERSION,\n serviceDescription: '',\n hasVersionedData: false,\n supportsDisconnectedEditing: false,\n hasStaticData: false,\n maxRecordCount: Math.max(...all.map((l) => l.def.maxRecordCount)),\n supportedQueryFormats: 'JSON',\n capabilities: 'Query,Create,Update,Delete,Editing',\n spatialReference: SPATIAL_REFERENCE,\n layers: all.filter((l) => l.def.geometryType !== null).map(layerSummary),\n tables: all.filter((l) => l.def.geometryType === null).map(layerSummary),\n };\n}\n\nexport function layerMetadata(layer: LayerState) {\n const { def } = layer;\n return {\n currentVersion: CURRENT_VERSION,\n id: def.id,\n name: def.name,\n type: def.geometryType === null ? 'Table' : 'Feature Layer',\n geometryType: def.geometryType ?? undefined,\n objectIdField: def.objectIdField,\n globalIdField: def.globalIdField ?? '',\n uniqueIdField: { name: def.objectIdField, isSystemMaintained: true },\n hasAttachments: false,\n hasStaticData: false,\n isDataVersioned: false,\n supportedQueryFormats: 'JSON',\n supportsApplyEditsWithGlobalIds: def.globalIdField !== undefined,\n supportsPagination: true,\n supportsAdvancedQueries: true,\n advancedQueryCapabilities: {\n supportsPagination: true,\n supportsOrderBy: true,\n supportsAdvancedQueries: true,\n supportsStatistics: false,\n supportsDistinct: false,\n supportsCountDistinct: false,\n },\n capabilities: 'Query,Create,Update,Delete,Editing',\n maxRecordCount: def.maxRecordCount,\n fields: fieldMetadata(def),\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Query\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Query features this emulator does not implement; asking for one is an error, not a silent no-op.\n * The spatial companions of `geometry` (geometryType, spatialRel, inSR, distance, units) are absent:\n * real ArcGIS ignores them unless `geometry` is given, and the ArcGIS SDKs send defaults for them on\n * every query. A real spatial filter still fails here, on `geometry`.\n */\nconst UNSUPPORTED_PARAMS = [\n 'geometry',\n 'outStatistics',\n 'groupByFieldsForStatistics',\n 'returnDistinctValues',\n 'returnExtentOnly',\n 'time',\n 'having',\n 'returnZ',\n 'returnM',\n];\nconst UNSUPPORTED_FORMATS = new Set(['geojson', 'pbf', 'html']);\n\nfunction rejectUnsupported(p: Params): void {\n for (const name of UNSUPPORTED_PARAMS) {\n const value = p.get(name);\n if (value !== undefined && value !== '' && value.toLowerCase() !== 'false') throw badParameter(name);\n }\n // `none` is the default; `standard` and `tile` change paging limits, which this emulator does not model.\n const resultType = p.get('resultType')?.toLowerCase();\n if (resultType && resultType !== 'none') throw badParameter('resultType');\n if (UNSUPPORTED_FORMATS.has((p.get('f') ?? '').toLowerCase())) throw badParameter('f');\n}\n\nexport function queryLayer(layer: LayerState, p: Params): EmulationResponse {\n const { def } = layer;\n const resolve = fieldResolver(layer);\n rejectUnsupported(p);\n\n const predicate = compileWhere(p.get('where')?.trim() || '1=1', resolve);\n const ids = parseIds('objectIds', p.get('objectIds'));\n const objectIds = ids && new Set(ids.map(Number));\n\n const sorts = (p.get('orderByFields') ?? '')\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)\n .map((spec) => {\n const [name = '', direction = 'ASC'] = spec.split(/\\s+/);\n const field = resolve(name);\n const dir = direction.toUpperCase();\n if (!field || (dir !== 'ASC' && dir !== 'DESC')) throw badQuery();\n return { field, sign: dir === 'DESC' ? -1 : 1 };\n });\n sorts.push({ field: def.objectIdField, sign: 1 });\n\n const matched = layer.features\n .filter((f) => predicate(f.attributes) && (!objectIds || objectIds.has(f.attributes[def.objectIdField] as number)))\n .sort((a, b) => {\n for (const { field, sign } of sorts) {\n const c = compareForSort(a.attributes[field], b.attributes[field]);\n if (c !== 0) return c * sign;\n }\n return 0;\n });\n\n if (flag(p, 'returnCountOnly')) return ok(p, { count: matched.length });\n if (flag(p, 'returnIdsOnly')) {\n return ok(p, {\n objectIdFieldName: def.objectIdField,\n objectIds: matched.map((f) => f.attributes[def.objectIdField]),\n });\n }\n\n // No outFields means no attributes, per the Esri Query docs.\n const outFieldsParam = p.get('outFields')?.trim();\n const outFields =\n outFieldsParam === '*'\n ? def.fields.map((f) => f.name)\n : (outFieldsParam ? outFieldsParam.split(',').map((s) => s.trim()) : []).map((name) => {\n const field = resolve(name);\n if (!field) throw badQuery();\n return field;\n });\n\n const offset = Math.max(0, Math.floor(Number(p.get('resultOffset'))) || 0);\n const requested = p.get('resultRecordCount') ? Math.floor(Number(p.get('resultRecordCount'))) : NaN;\n const limit = Number.isFinite(requested) ? Math.min(Math.max(requested, 1), def.maxRecordCount) : def.maxRecordCount;\n const page = matched.slice(offset, offset + limit);\n const returnGeometry = flag(p, 'returnGeometry', true);\n\n return ok(p, {\n objectIdFieldName: def.objectIdField,\n globalIdFieldName: def.globalIdField ?? '',\n geometryType: def.geometryType ?? undefined,\n spatialReference: SPATIAL_REFERENCE,\n fields: fieldMetadata(def).filter((f) => outFields.includes(f.name)),\n features: page.map((f) => ({\n attributes: Object.fromEntries(outFields.map((name) => [name, f.attributes[name] ?? null])),\n ...(returnGeometry && f.geometry ? { geometry: f.geometry } : {}),\n })),\n exceededTransferLimit: offset + limit < matched.length,\n });\n}\n","/**\n * Jira Cloud API Emulation Plugin\n *\n * Emulates the Jira REST API v3 the app talks to: the OAuth token endpoint\n * (`auth.atlassian.com`), the 3LO gateway (`api.atlassian.com/ex/jira/<cloudId>`)\n * and the tenant host (`<tenant>.atlassian.net`). Sandbox-side only — Jira is an\n * API service, so no browser interception is needed.\n *\n * State is mutable (created issues, labels, comments and registered webhooks\n * persist for the copy's lifetime). Like Jira, the emulator delivers webhooks to\n * the URLs the app registered through `POST /rest/api/3/webhook`, so nothing\n * app-specific lives here. Operations let a flow drive it: `add-label` tags an\n * issue and delivers `jira:issue_updated` to the registered subscribers. Unlike\n * Slack's `inboundEvents`, operations here may make outbound deliveries to the app.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport { z } from 'zod';\nimport type {\n EmulationPlugin,\n EmulationRequest,\n EmulationResponse,\n EmulationRoute,\n PluginContext,\n} from '../plugin.js';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- parsing untrusted API input\nfunction safeParseJson(body: string | undefined): { ok: true; data: any } | { ok: false; error: EmulationResponse } {\n try {\n return { ok: true, data: JSON.parse(body ?? '{}') };\n } catch {\n return { ok: false, error: { status: 400, body: { errorMessages: ['Invalid JSON body'] } } };\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface JiraConfig {\n /** Tenant subdomain (e.g., 'acme' for acme.atlassian.net) */\n tenant: string;\n}\n\nexport interface JiraUser {\n accountId: string;\n displayName: string;\n emailAddress: string;\n}\n\n/** Atlassian Document Format node — descriptions and comments are ADF in API v3. */\nexport interface AdfNode {\n type: string;\n text?: string;\n content?: AdfNode[];\n version?: number;\n}\n\nexport interface JiraComment {\n id: string;\n author: JiraUser;\n body: AdfNode;\n created: string;\n}\n\nexport interface JiraIssue {\n id: string;\n key: string;\n projectKey: string;\n summary: string;\n description?: AdfNode;\n status: { name: string };\n assignee?: JiraUser;\n reporter?: JiraUser;\n issuetype: { name: string };\n priority?: { name: string };\n created: string;\n updated: string;\n labels: string[];\n comments: JiraComment[];\n attachments: string[];\n}\n\nexport interface JiraProject {\n id: string;\n key: string;\n name: string;\n}\n\n/** Fixture issues give plain-text descriptions; the emulator converts them to ADF. */\nexport interface JiraFixtureIssue\n extends Omit<JiraIssue, 'description' | 'labels' | 'comments' | 'attachments'> {\n description?: string;\n labels?: string[];\n}\n\nexport interface JiraFixture {\n projects: JiraProject[];\n issues: JiraFixtureIssue[];\n users?: JiraUser[];\n}\n\n/** A subscriber the app registered with `POST /rest/api/3/webhook`. */\ninterface JiraWebhook {\n id: number;\n url: string;\n events: string[];\n /** From the `project = \"KEY\"` clause of the registration's `jqlFilter`; null delivers for every project. */\n projectKey: string | null;\n}\n\nexport interface JiraState {\n projects: Map<string, JiraProject>;\n issues: Map<string, JiraIssue>;\n users: Map<string, JiraUser>;\n webhooks: Map<number, JiraWebhook>;\n /** Per-project counter for auto-assigning issue keys */\n issueCounter: Record<string, number>;\n /** Next numeric issue id (Jira ids are numeric strings) */\n nextIssueId: number;\n nextCommentId: number;\n nextWebhookId: number;\n tenant: string;\n}\n\ntype JiraCtx = PluginContext<JiraFixture, JiraState>;\n\nconst EMULATED_USER: JiraUser = {\n accountId: 'emulated',\n displayName: 'Emulated User',\n emailAddress: 'emulated@test.com',\n};\n\nconst ISSUE_UPDATED = 'jira:issue_updated';\n/** The app's webhook handler answers fast (it enqueues a job); keep this below the executor's 30s operation timeout. */\nconst WEBHOOK_TIMEOUT_MS = 15_000;\nconst WEBHOOK_TTL_MS = 30 * 24 * 60 * 60 * 1000;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// ADF helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction textToAdf(text: string): AdfNode {\n return {\n type: 'doc',\n version: 1,\n content: text\n .split(/\\n{2,}/)\n .map((para) => ({ type: 'paragraph', content: [{ type: 'text', text: para }] })),\n };\n}\n\nconst ADF_BLOCKS = new Set(['paragraph', 'heading', 'bulletList', 'orderedList', 'listItem', 'blockquote', 'codeBlock']);\n\nfunction adfToText(node: AdfNode | undefined): string {\n if (!node) return '';\n if (typeof node.text === 'string') return node.text;\n const inner = (node.content ?? []).map(adfToText).join('');\n return ADF_BLOCKS.has(node.type) ? `${inner}\\n` : inner;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Operations\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst createIssueInput = z\n .object({ projectKey: z.string(), summary: z.string(), description: z.string().optional() })\n .strict();\n\nconst addLabelInput = z\n .object({ issueKey: z.string(), label: z.string().regex(/^\\S+$/, 'labels cannot contain spaces') })\n .strict();\n\nconst issueKeyInput = z.object({ issueKey: z.string() }).strict();\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Routes\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * The app reaches Jira through the 3LO gateway (`/ex/jira/<cloudId>/rest/...`);\n * the tenant host serves the same API at the bare `/rest/...` path.\n */\nfunction restRoutes(\n method: EmulationRoute<JiraFixture, JiraState>['method'],\n path: string,\n handler: EmulationRoute<JiraFixture, JiraState>['handler']\n): EmulationRoute<JiraFixture, JiraState>[] {\n return ['', '/ex/jira/:cloudId'].map((prefix) => ({ method, path: `${prefix}/rest/api/3${path}`, handler }));\n}\n\nexport const jiraPlugin: EmulationPlugin<JiraConfig, JiraFixture, JiraState> = {\n id: 'jira',\n name: 'Jira Cloud API',\n version: '2.0.0',\n\n domains: (config) => [`${config.tenant}.atlassian.net`, 'api.atlassian.com', 'auth.atlassian.com'],\n needsBrowserIntercept: false,\n\n routes: [\n // ── OAuth token refresh (auth.atlassian.com) ────────────────────────\n {\n method: 'POST',\n path: '/oauth/token',\n handler: () => ({\n status: 200,\n body: {\n access_token: `emulated-access-${crypto.randomBytes(8).toString('hex')}`,\n refresh_token: 'emulated-refresh',\n expires_in: 3600,\n scope: 'read:jira-work write:jira-work offline_access',\n token_type: 'Bearer',\n },\n }),\n },\n\n // ── Projects ─────────────────────────────────────────────────────────\n ...restRoutes('GET', '/project', (_req, ctx: JiraCtx) => ({\n status: 200,\n body: Array.from(ctx.state.projects.values()),\n })),\n ...restRoutes('GET', '/project/search', (_req, ctx: JiraCtx) => {\n const values = Array.from(ctx.state.projects.values());\n return { status: 200, body: { values, total: values.length, isLast: true } };\n }),\n ...restRoutes('GET', '/project/:projectKey', (req, ctx: JiraCtx) => {\n const project = ctx.state.projects.get(req.params.projectKey);\n if (!project) return { status: 404, body: { errorMessages: ['Project not found'] } };\n return { status: 200, body: project };\n }),\n\n // ── Issues ───────────────────────────────────────────────────────────\n // Before /issue/:issueKey, which would take \"createmeta\" for an issue key. The app's\n // Jira settings page reads the issue types of the project it files tickets into.\n ...restRoutes('GET', '/issue/createmeta', (_req, ctx: JiraCtx) => ({\n status: 200,\n body: {\n projects: Array.from(ctx.state.projects.values()).map((project) => ({\n key: project.key,\n issuetypes: [{ id: '10001', name: 'Task', subtask: false }],\n })),\n },\n })),\n ...restRoutes('GET', '/issue/:issueKey', handleGetIssue),\n ...restRoutes('POST', '/issue', handleCreateIssue),\n ...restRoutes('PUT', '/issue/:issueKey', handleUpdateIssue),\n ...restRoutes('POST', '/issue/:issueKey/comment', handleAddComment),\n ...restRoutes('POST', '/issue/:issueKey/attachments', handleAddAttachment),\n\n // ── Transitions ──────────────────────────────────────────────────────\n ...restRoutes('GET', '/issue/:issueKey/transitions', () => ({\n status: 200,\n body: {\n transitions: [\n { id: '11', name: 'To Do' },\n { id: '21', name: 'In Progress' },\n { id: '31', name: 'Done' },\n ],\n },\n })),\n ...restRoutes('POST', '/issue/:issueKey/transitions', handleTransition),\n\n // ── Search ───────────────────────────────────────────────────────────\n ...restRoutes('POST', '/search', handleSearch),\n ...restRoutes('GET', '/search', handleSearch),\n ...restRoutes('POST', '/search/jql', handleSearch),\n\n // ── Webhooks (the app registers its own delivery URL) ────────────────\n ...restRoutes('POST', '/webhook', handleRegisterWebhooks),\n ...restRoutes('DELETE', '/webhook', handleDeleteWebhooks),\n ...restRoutes('PUT', '/webhook/refresh', () => ({\n status: 200,\n body: { expirationDate: new Date(Date.now() + WEBHOOK_TTL_MS).toISOString() },\n })),\n\n // ── Users / server info ──────────────────────────────────────────────\n ...restRoutes('GET', '/myself', (_req, ctx: JiraCtx) => ({\n status: 200,\n body: ctx.state.users.values().next().value ?? EMULATED_USER,\n })),\n ...restRoutes('GET', '/serverInfo', () => ({\n status: 200,\n body: {\n baseUrl: 'https://emulated.atlassian.net',\n version: '1001.0.0-SNAPSHOT',\n deploymentType: 'Cloud',\n scmInfo: 'emulated',\n },\n })),\n ],\n\n operations: [\n {\n id: 'create-issue',\n description: 'Create an issue (no webhook is delivered).',\n input: createIssueInput,\n output: z.object({ key: z.string(), id: z.string() }),\n handler: (ctx: JiraCtx, raw) => {\n const input = raw as z.infer<typeof createIssueInput>;\n if (!ctx.state.projects.has(input.projectKey)) {\n throw new Error(`Project ${input.projectKey} not found`);\n }\n const issue = createIssue(ctx, {\n projectKey: input.projectKey,\n summary: input.summary,\n description: input.description ? textToAdf(input.description) : undefined,\n });\n return { key: issue.key, id: issue.id };\n },\n },\n {\n id: 'add-label',\n description:\n 'Add a label to an issue and deliver jira:issue_updated to the webhooks the app registered for the issue\\'s project, as Jira does when a person tags a ticket. The label is committed only after every subscriber accepts the delivery. Fails if the label is already present or no webhook is registered.',\n input: addLabelInput,\n output: z.object({ labels: z.string() }),\n handler: async (ctx: JiraCtx, raw) => {\n const input = raw as z.infer<typeof addLabelInput>;\n const issue = requireIssue(ctx, input.issueKey);\n if (issue.labels.includes(input.label)) {\n // A changelog with identical from/to strings is not a tag event — the app would ignore it.\n throw new Error(`Issue ${issue.key} already has the label '${input.label}'`);\n }\n // Commit only once every subscriber accepted the delivery, so a failed step can be retried for real.\n await deliverIssueUpdated(ctx, issue, [...issue.labels, input.label]);\n // The delivery awaited the network; merge into the issue as it is now, not the array read before.\n const current = requireIssue(ctx, issue.key);\n if (current.labels.includes(input.label)) {\n throw new Error(`Issue ${current.key} already has the label '${input.label}'`);\n }\n current.labels = [...current.labels, input.label];\n current.updated = new Date().toISOString();\n return { labels: current.labels.join(' ') };\n },\n },\n {\n id: 'get-issue',\n description: 'Read an issue: its labels (space-separated) and how many attachments the app uploaded.',\n input: issueKeyInput,\n output: z.object({ labels: z.string(), attachmentCount: z.number() }),\n handler: (ctx: JiraCtx, raw) => {\n const issue = requireIssue(ctx, (raw as z.infer<typeof issueKeyInput>).issueKey);\n return { labels: issue.labels.join(' '), attachmentCount: issue.attachments.length };\n },\n },\n {\n id: 'get-comments',\n description: 'Read the comments the app wrote on an issue; lastCommentText is the newest as plain text.',\n input: issueKeyInput,\n output: z.object({ commentCount: z.number(), lastCommentText: z.string() }),\n handler: (ctx: JiraCtx, raw) => {\n const issue = requireIssue(ctx, (raw as z.infer<typeof issueKeyInput>).issueKey);\n return {\n commentCount: issue.comments.length,\n lastCommentText: adfToText(issue.comments.at(-1)?.body),\n };\n },\n },\n ],\n\n initialize(config, fixture) {\n const projects = new Map(fixture.projects.map((p) => [p.key, p]));\n const issues = new Map<string, JiraIssue>(\n fixture.issues.map((i) => [\n i.key,\n {\n ...i,\n description: i.description ? textToAdf(i.description) : undefined,\n labels: i.labels ?? [],\n comments: [],\n attachments: [],\n },\n ])\n );\n const users = new Map((fixture.users ?? []).map((u) => [u.accountId, u]));\n\n const issueCounter: Record<string, number> = {};\n let maxId = 10000;\n for (const issue of fixture.issues) {\n const num = parseInt(issue.key.split('-')[1] ?? '', 10);\n if (!isNaN(num)) {\n issueCounter[issue.projectKey] = Math.max(issueCounter[issue.projectKey] ?? 0, num);\n }\n const id = parseInt(issue.id, 10);\n if (!isNaN(id)) maxId = Math.max(maxId, id);\n }\n\n return {\n projects,\n issues,\n users,\n webhooks: new Map(),\n issueCounter,\n nextIssueId: maxId + 1,\n nextCommentId: 10000,\n nextWebhookId: 1,\n tenant: config.tenant,\n };\n },\n\n defaultFixture: {\n projects: [{ id: '10000', key: 'TEST', name: 'Test Project' }],\n issues: [\n {\n id: '10001',\n key: 'TEST-1',\n projectKey: 'TEST',\n summary: 'Sample issue',\n description: 'This is a sample issue for testing.',\n status: { name: 'To Do' },\n issuetype: { name: 'Task' },\n priority: { name: 'Medium' },\n created: new Date().toISOString(),\n updated: new Date().toISOString(),\n },\n ],\n users: [{ accountId: '100001', displayName: 'Test User', emailAddress: 'test@example.com' }],\n },\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// State helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Jira resolves an issue by key or by numeric id interchangeably. */\nfunction findIssue(state: JiraState, keyOrId: string): JiraIssue | undefined {\n const byKey = state.issues.get(keyOrId);\n if (byKey) return byKey;\n for (const issue of state.issues.values()) {\n if (issue.id === keyOrId) return issue;\n }\n return undefined;\n}\n\nfunction requireIssue(ctx: JiraCtx, keyOrId: string): JiraIssue {\n const issue = findIssue(ctx.state, keyOrId);\n if (!issue) throw new Error(`Issue ${keyOrId} not found`);\n return issue;\n}\n\nfunction createIssue(\n ctx: JiraCtx,\n input: {\n projectKey: string;\n summary: string;\n description?: AdfNode;\n labels?: string[];\n issuetype?: { name: string };\n assignee?: JiraUser;\n reporter?: JiraUser;\n priority?: { name: string };\n }\n): JiraIssue {\n const counter = (ctx.state.issueCounter[input.projectKey] ?? 0) + 1;\n ctx.state.issueCounter[input.projectKey] = counter;\n const key = `${input.projectKey}-${counter}`;\n const now = new Date().toISOString();\n\n const issue: JiraIssue = {\n id: String(ctx.state.nextIssueId++),\n key,\n projectKey: input.projectKey,\n summary: input.summary,\n description: input.description,\n status: { name: 'To Do' },\n issuetype: input.issuetype ?? { name: 'Task' },\n priority: input.priority ?? { name: 'Medium' },\n assignee: input.assignee,\n reporter: input.reporter,\n labels: input.labels ?? [],\n comments: [],\n attachments: [],\n created: now,\n updated: now,\n };\n\n ctx.state.issues.set(key, issue);\n ctx.log('info', `Created issue ${key}: ${issue.summary}`);\n return issue;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Webhook delivery\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Drop the URL (whole, then its userinfo, path and query) and each query value on its own from\n * text that may echo it. The app puts its webhook secret in the query; an error body might echo\n * the whole URL or just the value.\n */\nfunction redactQuery(text: string, url: URL): string {\n // Longest first: the href contains everything below it.\n let redacted = text;\n for (const part of [url.href, url.username && `${url.username}:${url.password}@`, url.pathname.length > 1 ? url.pathname : '', url.search]) {\n if (part) redacted = redacted.split(part).join('');\n }\n for (const value of url.searchParams.values()) {\n // Short values (\"a=1\") would mangle ordinary text; secrets in the query are long tokens.\n if (value.length < 8) continue;\n for (const form of new Set([value, encodeURIComponent(value)])) redacted = redacted.split(form).join('[redacted]');\n }\n return redacted;\n}\n\n/**\n * Deliver `jira:issue_updated` with a `labels` changelog item to every webhook\n * the app registered for it, in parallel. Jira sends labels in the changelog as\n * space-separated strings. Throws when none is registered, or when any delivery\n * fails (one error naming each failing target's origin), so a flow fails at the\n * step that tagged the ticket instead of timing out later. Delivery to several\n * subscribers is not transactional: those that succeeded have already been told.\n * Errors never include the target's path or query string.\n */\nasync function deliverIssueUpdated(ctx: JiraCtx, issue: JiraIssue, labelsAfter: string[]): Promise<void> {\n // Like Jira, deliver only to subscribers whose event list and project filter cover this issue.\n const subscribers = [...ctx.state.webhooks.values()].filter(\n (hook) => hook.events.includes(ISSUE_UPDATED) && (hook.projectKey === null || hook.projectKey === issue.projectKey)\n );\n if (subscribers.length === 0) {\n throw new Error(\n `No webhook is registered for ${ISSUE_UPDATED} on project ${issue.projectKey}; the app must register one with POST /rest/api/3/webhook before an issue can be tagged`\n );\n }\n\n const basePayload = {\n timestamp: Date.now(),\n webhookEvent: ISSUE_UPDATED,\n issue_event_type_name: 'issue_generic',\n user: EMULATED_USER,\n issue: {\n id: issue.id,\n key: issue.key,\n fields: {\n summary: issue.summary,\n status: { name: issue.status.name, statusCategory: { key: issue.status.name === 'Done' ? 'done' : 'new' } },\n labels: labelsAfter,\n project: { key: issue.projectKey },\n },\n },\n changelog: {\n id: crypto.randomUUID(),\n items: [\n {\n field: 'labels',\n fieldtype: 'jira',\n from: null,\n to: null,\n fromString: issue.labels.join(' '),\n toString: labelsAfter.join(' '),\n },\n ],\n },\n };\n\n const payload = {\n ...basePayload,\n matchedWebhookIds: subscribers.map((hook) => hook.id),\n };\n\n const results = await Promise.allSettled(subscribers.map((hook) => deliverTo(ctx, hook, issue.key, payload)));\n const failures = results.flatMap((result) => (result.status === 'rejected' ? [errorMessage(result.reason)] : []));\n if (failures.length > 0) throw new Error(failures.join('; '));\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/** POST one delivery. Errors name the target's origin only and never echo its query string. */\nasync function deliverTo(ctx: JiraCtx, hook: JiraWebhook, issueKey: string, payload: object): Promise<void> {\n const target = new URL(hook.url);\n const where = target.origin;\n let res: Response;\n try {\n res = await fetch(hook.url, {\n method: 'POST',\n // A redirect would resend the payload (and the secret in the query) to a host the app never registered.\n redirect: 'manual',\n headers: {\n 'content-type': 'application/json',\n 'x-atlassian-webhook-identifier': crypto.randomUUID(),\n // Real Jira does not send this header (the event is only in the body's `webhookEvent`).\n // The app's Jira provider reads it to classify deliveries, so the emulator sets it.\n 'x-atlassian-webhook-event': ISSUE_UPDATED,\n },\n body: JSON.stringify(payload),\n signal: AbortSignal.timeout(WEBHOOK_TIMEOUT_MS),\n });\n } catch (err) {\n throw new Error(`Webhook delivery to ${where} failed: ${redactQuery(errorMessage(err), target)}`);\n }\n if (!res.ok) {\n let text = '';\n try {\n text = await res.text();\n } catch {\n // The body aborted mid-read; the status and target are still worth reporting.\n }\n // Redact before truncating, so a secret straddling the cut can't leave a prefix behind.\n throw new Error(\n `App rejected the ${ISSUE_UPDATED} webhook at ${where} (${res.status}): ${redactQuery(text, target).slice(0, 300)}`\n );\n }\n await res.body?.cancel();\n ctx.log('info', `Delivered ${ISSUE_UPDATED} for ${issueKey} to ${where} (${res.status})`);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Route Handlers\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction jiraBaseUrl(tenant: string): string {\n return `https://${tenant}.atlassian.net`;\n}\n\nfunction formatIssueResponse(issue: JiraIssue, baseUrl: string): object {\n return {\n id: issue.id,\n key: issue.key,\n self: `${baseUrl}/rest/api/3/issue/${issue.key}`,\n fields: {\n summary: issue.summary,\n description: issue.description ?? null,\n status: issue.status,\n assignee: issue.assignee ?? null,\n reporter: issue.reporter ?? null,\n issuetype: issue.issuetype,\n priority: issue.priority ?? { name: 'Medium' },\n created: issue.created,\n updated: issue.updated,\n labels: issue.labels,\n project: { key: issue.projectKey },\n },\n };\n}\n\nconst notFound = (key: string): EmulationResponse => ({\n status: 404,\n body: { errorMessages: [`Issue ${key} not found`] },\n});\n\nfunction handleGetIssue(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const issue = findIssue(ctx.state, req.params.issueKey);\n if (!issue) return notFound(req.params.issueKey);\n return { status: 200, body: formatIssueResponse(issue, jiraBaseUrl(ctx.state.tenant)) };\n}\n\nfunction handleCreateIssue(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return parsed.error;\n const fields = parsed.data.fields ?? {};\n const projectKey = fields.project?.key;\n\n if (!projectKey || !ctx.state.projects.has(projectKey)) {\n return { status: 400, body: { errorMessages: [`Project ${projectKey} not found`] } };\n }\n\n const issue = createIssue(ctx, {\n projectKey,\n summary: fields.summary ?? '',\n // The app sends an ADF document; keep it verbatim.\n description: fields.description ?? undefined,\n labels: fields.labels ?? [],\n issuetype: fields.issuetype,\n assignee: fields.assignee ?? undefined,\n reporter: fields.reporter ?? undefined,\n priority: fields.priority ?? undefined,\n });\n\n return {\n status: 201,\n body: { id: issue.id, key: issue.key, self: `${jiraBaseUrl(ctx.state.tenant)}/rest/api/3/issue/${issue.key}` },\n };\n}\n\nfunction handleUpdateIssue(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const issue = findIssue(ctx.state, req.params.issueKey);\n if (!issue) return notFound(req.params.issueKey);\n\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return parsed.error;\n const fields = parsed.data.fields ?? {};\n\n if (fields.summary !== undefined) issue.summary = fields.summary;\n if (fields.description !== undefined) issue.description = fields.description;\n if (fields.assignee !== undefined) issue.assignee = fields.assignee;\n if (fields.priority !== undefined) issue.priority = fields.priority;\n if (fields.labels !== undefined) issue.labels = fields.labels;\n issue.updated = new Date().toISOString();\n\n ctx.log('info', `Updated issue ${issue.key}`);\n return { status: 204 };\n}\n\nfunction handleTransition(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const issue = findIssue(ctx.state, req.params.issueKey);\n if (!issue) return notFound(req.params.issueKey);\n\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return parsed.error;\n\n const transitionNames = new Map([\n ['11', 'To Do'],\n ['21', 'In Progress'],\n ['31', 'Done'],\n ]);\n const newStatus = transitionNames.get(String(parsed.data.transition?.id));\n if (newStatus) {\n issue.status = { name: newStatus };\n issue.updated = new Date().toISOString();\n ctx.log('info', `Transitioned ${issue.key} to ${newStatus}`);\n }\n\n return { status: 204 };\n}\n\nfunction handleAddComment(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const issue = findIssue(ctx.state, req.params.issueKey);\n if (!issue) return notFound(req.params.issueKey);\n\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return parsed.error;\n const body = parsed.data.body;\n const comment: JiraComment = {\n id: String(ctx.state.nextCommentId++),\n author: EMULATED_USER,\n body: typeof body === 'string' ? textToAdf(body) : body,\n created: new Date().toISOString(),\n };\n issue.comments.push(comment);\n issue.updated = comment.created;\n ctx.log('info', `Comment ${comment.id} added to ${issue.key}`);\n return { status: 201, body: comment };\n}\n\n/** Records that an attachment arrived; the multipart body itself is not retained. */\nfunction handleAddAttachment(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const issue = findIssue(ctx.state, req.params.issueKey);\n if (!issue) return notFound(req.params.issueKey);\n const id = `att-${issue.attachments.length + 1}`;\n issue.attachments.push(id);\n return {\n status: 200,\n body: [{ id, filename: id, content: `${jiraBaseUrl(ctx.state.tenant)}/secure/attachment/${id}` }],\n };\n}\n\n/** `POST /rest/api/3/webhook` — one subscriber per entry in `webhooks`, all delivering to `url`. */\nfunction handleRegisterWebhooks(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return parsed.error;\n const { url, webhooks } = parsed.data as {\n url?: unknown;\n webhooks?: Array<{ events?: unknown; jqlFilter?: unknown }>;\n };\n if (typeof url !== 'string' || !URL.canParse(url) || !Array.isArray(webhooks)) {\n return { status: 400, body: { errorMessages: ['Body must be {url, webhooks: [{events}]}'] } };\n }\n const protocol = new URL(url).protocol;\n if (protocol !== 'http:' && protocol !== 'https:') {\n return { status: 400, body: { errorMessages: [`Webhook url must be http or https, got ${protocol}`] } };\n }\n\n const webhookRegistrationResult = webhooks.map((entry) => {\n const events = Array.isArray(entry.events) ? entry.events.filter((e): e is string => typeof e === 'string') : [];\n const jqlFilter = typeof entry.jqlFilter === 'string' ? entry.jqlFilter : '';\n const projectKey = /project\\s*=\\s*\"?([A-Z][A-Z0-9_]*)\"?/i.exec(jqlFilter)?.[1] ?? null;\n const id = ctx.state.nextWebhookId++;\n ctx.state.webhooks.set(id, { id, url, events, projectKey });\n ctx.log('info', `Registered webhook ${id} (${events.join(', ')}) -> ${new URL(url).origin}`);\n return { createdWebhookId: id };\n });\n return { status: 200, body: { webhookRegistrationResult } };\n}\n\n/** `DELETE /rest/api/3/webhook` with `{webhookIds}`. */\nfunction handleDeleteWebhooks(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return parsed.error;\n const ids: unknown[] = Array.isArray(parsed.data.webhookIds) ? parsed.data.webhookIds : [];\n for (const id of ids) ctx.state.webhooks.delete(Number(id));\n return { status: 202 };\n}\n\n/**\n * Search understands exactly the clause the app generates for the Tickets page:\n * `labels = \"<label>\"`. Any other JQL returns every issue.\n */\nfunction handleSearch(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const parsed = req.method === 'POST' ? safeParseJson(req.body) : { ok: true as const, data: {} };\n if (!parsed.ok) return parsed.error;\n const jql: string = parsed.data.jql ?? req.url.searchParams.get('jql') ?? '';\n const labelMatch = /labels\\s*=\\s*(?:\"((?:[^\"\\\\]|\\\\.)*)\"|(\\S+))/i.exec(jql);\n const label = labelMatch ? (labelMatch[1] ?? labelMatch[2]) : undefined;\n\n const issues = Array.from(ctx.state.issues.values()).filter((i) => (label ? i.labels.includes(label) : true));\n const baseUrl = jiraBaseUrl(ctx.state.tenant);\n\n return {\n status: 200,\n body: {\n startAt: 0,\n maxResults: issues.length,\n total: issues.length,\n isLast: true,\n issues: issues.map((i) => formatIssueResponse(i, baseUrl)),\n },\n };\n}\n","/**\n * Maximo Stub\n *\n * A slice of the IBM Maximo (MAS) MBO REST API, enough for a connector to test its\n * connection, list entities, read records and create or update them with AddChange:\n *\n * - `GET /<root>/restapi/mbo/<OBJECT>`, where `<root>` is any single segment (the\n * context root a connector is configured with, such as a run-unique `maximo-<x>`).\n * - Objects: `MAXOBJECT` (the catalogue), `MAXOBJECTCFG` (the catalogue's configuration\n * table, which a Maximo client's entity picker queries with\n * `_uw=INTERNAL=0 AND ISVIEW=0 AND PERSISTENT=1`), `MAXATTRIBUTE` (attribute metadata),\n * `CLASSSTRUCTURE` (a small classification hierarchy), and seeded `ORGANIZATION`,\n * `WORKORDER`, `ASSET`, `LOCATIONS`, `SR` (maximo-stub-data.ts).\n * - Query parameters, as in the Maximo 7.6 REST API guide (\"Integrating data with\n * external applications\", REST API chapter): attribute filters (`status=APPR` is a\n * contains match, `status=~eq~APPR` or `_exactmatch=1` exact; number and yes/no\n * attributes by equality), ANDed unless\n * `_opmodeor=1`; `_uw` (a where clause of `ATTR = 'v'` clauses joined by `and`);\n * `_orderby`/`_orderbyasc`/`_orderbydesc` (comma-separated attributes);\n * `_rsStart`/`_maxItems` paging; `_compact`; and `_dropnulls=0` (or `false`), which adds the\n * attributes a row has no value for (null, `{}` when not compact). Responses are\n * always JSON (`_format` is accepted and ignored; real Maximo defaults to XML).\n * - Like Maximo, which errors only on a bad URI or resource, other parameters are\n * ignored: any other `_` system parameter (session and presentation ones such as\n * `_lid`/`_lpwd`, `_tc`, `_verbose`; `_includecols`/`_excludecols`/`_field` are\n * accepted but every attribute is returned), `lean` (an OSLC API parameter), and a filter\n * on an attribute the object lacks or with an empty value. A connector's\n * connection check can carry any of them; the recorder still shows them.\n * - What the emulator cannot evaluate answers 400/404 rather than silently\n * returning the wrong rows: an unknown object (404), another filter operator,\n * QBE value syntax (`=`, `!=`, `<`, `>` prefixes, `,` lists, `%`/`*`), a\n * modifier on an attribute such as `status.ormode`, other where syntax, a where clause\n * or order-by on an attribute the object lacks (Maximo turns both into SQL, where\n * that column is an error), a filter value that does not parse on a number\n * or yes/no attribute, a bad paging value.\n * - Response: `{\"<OBJECT>MboSet\": {rsStart, rsCount, rsTotal, \"<OBJECT>\": [...]}}`;\n * with `_compact=1` each row is plain `{ATTR: value}`, otherwise\n * `{rowstamp, Attributes: {ATTR: {content: value}}}`, where the object's unique id\n * (WORKORDERID, ASSETID, LOCATIONSID, TICKETUID) is `{content: value, resourceid: true}`.\n * The marker is the contract an observed MAS connector requires (it builds the\n * record's URI from the marked attribute); the guide documents only that compact\n * drops per-field metadata (\"_format and _compact parameters\") and that a record's\n * URI ID is its unique id (\"GET method\"), not the marker itself. Both shapes are\n * served because connectors ask for both; every write reply uses them too.\n * - `POST /<root>/restapi/mbo/<OBJECT>` on `WORKORDER`, `ASSET`, `LOCATIONS` or `SR`\n * (the objects with a unique id) writes the attributes in its form body (system\n * parameters such as `_action` may be in the query or the body):\n * `_action=AddChange` updates the row with the same primary key (WONUM+SITEID on\n * WORKORDER) or creates one, `_action=Change` only updates, and no `_action` (or\n * `Add`) only creates (actions are case-insensitive; any other is 400). It answers\n * 200 with the saved row as `{\"<OBJECT>\": row}` in the shape above, with a new\n * rowstamp on every save, the way Maximo returns the record it saved (IBM support,\n * \"Creating a Work Order and approving it using Maximo REST\", reads\n * `WORKORDER.WORKORDERID` from the reply). Like Maximo, a new row gets the next unique\n * id (WORKORDERID, ...) and its site's ORGID. A new WORKORDER defaults to STATUS=WAPPR\n * when STATUS is omitted. A missing key attribute, an unknown\n * attribute, site or site/ORGID pair, the read-only unique id, and an over-long or\n * unparseable value are 400, and Change on a missing row is 404. A WORKORDER STATUS\n * outside the WOSTATUS domain (WAPPR, APPR, WSCH, WMATL, WPCOND, INPRG, COMP, CLOSE, CAN,\n * HISTEDIT; IBM \"Work order statuses\") is 400 with Maximo's BMXAA4190E \"Status <value> is not\n * in the value list.\" and stores nothing. That is the only status rule modelled: IBM\n * documents a status change through the changeStatus web method (IBM support, \"Creating a\n * Work Order and approving it using Maximo REST\": \"you cannot just update the Work Order\"),\n * but no source says what a plain Add or Change that sets STATUS does, so the stub still\n * stores an in-domain STATUS as sent and does not check status transitions. ASSET,\n * LOCATIONS and SR STATUS values are not checked either. Saved rows are kept\n * per `<root>`, so each run-unique root is its own data partition: reads of that root return\n * them in place of the seeded row with the same key, or after the seeded rows. A root\n * holds at most 1,000 saved rows and the host at most 100 roots (a new root past that\n * replaces the least recently used one); a root is dropped 6 hours after its last\n * request or 24 hours after its first write, and reports as\n * active to the idle gate (`GET /_emulation/active`) while in use.\n * - `POST /<root>/restapi/mbo/<OBJECT>/<id>` (the object's unique id, e.g. WORKORDERID) updates that\n * row in place with the form body's attributes, as `_action=Change` does, with or without\n * `x-method-override: PATCH`. An unknown id is 404 (as Change on a missing row), and a body\n * that changes a key attribute (WONUM, SITEID) is 400.\n * - `POST /<osRoot>/api/os/mxapiwo/<id>` with `x-method-override: PATCH` takes\n * a JSON body containing `status` and `statusdate`, applies the WOSTATUS/date\n * validation and updates that saved work order, then returns 204. A SITEID query\n * parameter must match when supplied. This is the status-only OSLC slice, not\n * arbitrary object-structure updates or encoded OSLC resource identifiers.\n * Assigned WORKORDERIDs are host-unique because this path has no MBO tenant root;\n * roots partition test data and share the host's API-key authorization.\n * a missing saved id is 404 and an ambiguous seeded id is 409. The owning MBO\n * root retains its rows and expiry rules. Invalid inputs store nothing.\n * https://ibm-maximo-dev.github.io/maximo-restapi-documentation/crud/create_and_update/\n *\n * Every request needs the configured API key in the `apikey` header or query\n * parameter, as on MAS; otherwise HTTP 401 with Maximo's BMXAA7901E error. Any\n * other authenticated request records as unmatched in `GET /_emulation/requests`:\n * other reads get 404, and other writes (outside `<root>/restapi/mbo/<OBJECT>`) get\n * HTTP 200 `{}` and are not stored. Requests the MBO routes reject (400/404 above)\n * record as matched; find them by status.\n *\n * @module\n */\n\nimport { z } from 'zod';\nimport type { EmulationPlugin, EmulationRequest, EmulationResponse, RouteHandler } from '../plugin.js';\nimport { tokensMatch } from '../token-match.js';\nimport {\n CLASSSTRUCTURE_RECORDS,\n MAXATTRIBUTE_RECORDS,\n MAXOBJECT_RECORDS,\n MAXOBJECTCFG_RECORDS,\n MBO_OBJECTS,\n type AttributeDef,\n type MboObjectDef,\n type MboRecord,\n type MboValue,\n} from './maximo-stub-data.js';\n\nconst configSchema = z.object({\n host: z.string().min(1),\n /** The API key a connector must send; on a public host make it long and random. */\n apiKey: z.string().min(24),\n});\ntype MaximoStubConfig = z.infer<typeof configSchema>;\n/** A row as served: its values and its rowstamp. */\ntype Row = { row: MboRecord; rowstamp: string };\n/** One root's saved rows, by object then primary key. */\ntype RootState = { objects: Map<string, Map<string, Row>>; createdAt: number; touchedAt: number };\ntype MaximoStubState = {\n apiKey: string;\n roots: Map<string, RootState>;\n nextRowstamp: number;\n nextWorkOrderId: number;\n};\ntype Handler = RouteHandler<Record<string, never>, MaximoStubState>;\n\n/** Metadata objects, whose attribute set is their seeded columns. */\nconst METADATA: readonly [string, readonly MboRecord[]][] = [\n ['MAXOBJECT', MAXOBJECT_RECORDS],\n ['MAXOBJECTCFG', MAXOBJECTCFG_RECORDS],\n ['MAXATTRIBUTE', MAXATTRIBUTE_RECORDS],\n ['CLASSSTRUCTURE', CLASSSTRUCTURE_RECORDS],\n];\n\nconst RECORDS: ReadonlyMap<string, readonly MboRecord[]> = new Map([\n ...METADATA,\n ...MBO_OBJECTS.map((o): [string, readonly MboRecord[]] => [o.name, o.records]),\n]);\n\nconst columns = (rows: readonly MboRecord[]) => new Set(rows.flatMap((r) => Object.keys(r)));\n\n/** Seeded rows as served: a synthetic rowstamp from their place, stable across requests. */\nconst SEEDED: ReadonlyMap<string, readonly Row[]> = new Map(\n [...RECORDS].map(([name, rows]) => [name, rows.map((row, i): Row => ({ row, rowstamp: String(1000 + i) }))])\n);\n\n/**\n * Each business object's unique id attribute, the one Maximo marks `resourceid` in a\n * non-compact row. Each served object has exactly one BIGINT column (WORKORDERID,\n * ASSETID, ...) and it is the unique id; a BIGINT foreign key would break this. Objects whose served columns hold\n * no unique id (ORGANIZATION and the metadata objects) have none.\n */\nconst UNIQUE_IDS: ReadonlyMap<string, string> = new Map(\n MBO_OBJECTS.flatMap((o): [string, string][] => {\n const id = o.attributes.find((a) => a.type === 'BIGINT');\n return id ? [[o.name, id.name]] : [];\n })\n);\n\n/** Each object's attribute names: `_uw` and order-by on any other name are rejected, attribute filters ignored. */\nconst ATTRIBUTES: ReadonlyMap<string, ReadonlySet<string>> = new Map([\n ...METADATA.map(([name, rows]): [string, ReadonlySet<string>] => [name, columns(rows)]),\n ...MBO_OBJECTS.map((o): [string, ReadonlySet<string>] => [o.name, new Set(o.attributes.map((a) => a.name))]),\n]);\n\nclass MaximoError extends Error {\n constructor(\n readonly status: number,\n message: string,\n /** The BMXAA message id, for errors that mirror a real Maximo message */\n readonly reasonCode?: string\n ) {\n super(message);\n }\n}\n\nconst errorBody = (status: number, message: string, reasonCode?: string): EmulationResponse => ({\n status,\n body: { Error: { ...(reasonCode ? { reasonCode } : {}), message, statusCode: String(status) } },\n});\n\n/** MAS answers a missing or wrong API key with this generic login error. */\nconst UNAUTHORIZED = errorBody(\n 401,\n 'BMXAA7901E - You cannot log in at this time. Contact the system administrator.',\n 'BMXAA7901E'\n);\n\n/** A query parameter by name, case-insensitive. */\nfunction queryParam(req: EmulationRequest, name: string): string | undefined {\n const want = name.toLowerCase();\n for (const [key, value] of req.url.searchParams) if (key.toLowerCase() === want) return value;\n return undefined;\n}\n\n/** Wrap a handler so it first checks the API key (header, else query parameter). */\nfunction authed(handler: Handler): Handler {\n return (req, ctx) => {\n const provided = req.headers['apikey'] ?? queryParam(req, 'apikey') ?? '';\n return tokensMatch(provided, ctx.state.apiKey) ? handler(req, ctx) : UNAUTHORIZED;\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Filtering\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype Predicate = (row: MboRecord) => boolean;\n\nconst text = (v: MboValue | undefined) => (v === undefined ? undefined : String(v).toLowerCase());\n\n/** A boolean system parameter: `1`/`true` on, `0`/`false` off, otherwise unset. */\nfunction flag(raw: string | undefined): boolean | undefined {\n const v = raw?.toLowerCase();\n return v === '1' || v === 'true' ? true : v === '0' || v === 'false' ? false : undefined;\n}\n\nconst isAttribute = (object: string, attr: string) => ATTRIBUTES.get(object)!.has(attr);\n\n/** For `_uw` and order-by: Maximo puts both in SQL, where an unknown column is an error. */\nfunction knownAttribute(object: string, name: string): string {\n const attr = name.toUpperCase();\n if (!isAttribute(object, attr)) throw new MaximoError(400, `Unknown attribute ${attr.slice(0, 64)} on ${object}`);\n return attr;\n}\n\n/** Yes/no values Maximo accepts in a filter. */\nconst YES_NO: ReadonlyMap<string, boolean> = new Map([\n ['1', true], ['y', true], ['true', true],\n ['0', false], ['n', false], ['false', false],\n]);\n\n/**\n * An attribute's value type, from its seeded values: Maximo compares numbers and yes/no\n * attributes by equality, never as a contains match.\n */\nfunction kindOf(object: string, attr: string): 'number' | 'boolean' | 'text' {\n const value = RECORDS.get(object)!.find((row) => row[attr] !== undefined)?.[attr];\n return typeof value === 'number' ? 'number' : typeof value === 'boolean' ? 'boolean' : 'text';\n}\n\n/** `attr` equals `raw`: numerically, as yes/no, or as case-insensitive text by the attribute's type. */\nfunction equals(object: string, attr: string, raw: string): Predicate {\n const kind = kindOf(object, attr);\n if (kind === 'number') {\n const want = Number(raw);\n if (raw.trim() === '' || !Number.isFinite(want)) throw new MaximoError(400, `Invalid number for ${attr}`);\n return (row) => row[attr] === want;\n }\n if (kind === 'boolean') {\n const want = YES_NO.get(raw.toLowerCase());\n if (want === undefined) throw new MaximoError(400, `Invalid yes/no value for ${attr}; expected 1, 0, Y, N, true or false`);\n return (row) => row[attr] === want;\n }\n const want = raw.toLowerCase();\n return (row) => text(row[attr]) === want;\n}\n\n/** QBE value syntax Maximo evaluates (`=APPR`, `!=`, `>5`, `APPR,WAPPR` as OR, `%`/`*` wildcards); the emulator does not. */\nconst QBE_SYNTAX = /^[=!<>]|[,%*]/;\n\n/**\n * On a text attribute `status=APPR` contains-matches like Maximo's default;\n * `status=~eq~APPR`, or any plain filter under `_exactmatch=1`, is exact. Number and\n * yes/no attributes always compare by equality. Undefined when Maximo's QBE ignores the\n * filter: an attribute the object lacks, or an empty value.\n */\nfunction attributeFilter(object: string, name: string, raw: string, exact: boolean): Predicate | undefined {\n const attr = name.toUpperCase();\n if (raw.startsWith('~') && !raw.startsWith('~eq~')) {\n throw new MaximoError(400, 'Unsupported filter operator in emulator; only ~eq~ is served');\n }\n const value = raw.startsWith('~eq~') ? raw.slice(4) : raw;\n if (!isAttribute(object, attr) || value === '') return undefined;\n if (QBE_SYNTAX.test(value)) throw new MaximoError(400, 'Unsupported QBE value syntax in emulator; send a plain value or ~eq~');\n if (exact || raw.startsWith('~eq~') || kindOf(object, attr) !== 'text') return equals(object, attr, value);\n const want = value.toLowerCase();\n return (row) => text(row[attr])?.includes(want) ?? false;\n}\n\n/** One `ATTR = 'v'` (or `= 12`) clause, then `and` or the end. Sticky, so `and` inside a quoted value is part of it. */\nconst CLAUSE = /\\s*([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*('(?:[^']|'')*'|-?\\d+(?:\\.\\d+)?)\\s*(?:(and)\\b|$)/iy;\nconst UNSUPPORTED_UW = \"Unsupported _uw in emulator; only ATTR = 'value' clauses joined by and are served\";\n\n/** `_uw`: `ATTR = 'v'` clauses joined by `and`, case-insensitive. */\nfunction whereFilter(object: string, uw: string): Predicate {\n const clauses: Predicate[] = [];\n CLAUSE.lastIndex = 0;\n for (;;) {\n const m = CLAUSE.exec(uw);\n if (!m) throw new MaximoError(400, UNSUPPORTED_UW);\n const attr = knownAttribute(object, m[1]!);\n const literal = m[2]!;\n clauses.push(equals(object, attr, literal.startsWith(\"'\") ? literal.slice(1, -1).replace(/''/g, \"'\") : literal));\n if (!m[3]) break;\n }\n return (row) => clauses.every((c) => c(row));\n}\n\nfunction nonNegativeInt(req: EmulationRequest, name: string): number | undefined {\n const raw = queryParam(req, name);\n if (raw === undefined || raw === '') return undefined;\n if (!/^\\d{1,9}$/.test(raw)) throw new MaximoError(400, `Invalid ${name}; expected a non-negative integer`);\n return Number(raw);\n}\n\ntype Comparator = (a: MboRecord, b: MboRecord) => number;\n\n/**\n * A missing value sorts as the greatest, so last ascending and first descending, like SQL\n * NULLs on Oracle and DB2. Numbers compare numerically; anything else (including a number\n * against a string) as text by code unit, like a binary collation, so the order does not\n * depend on the host locale.\n */\nfunction compareValues(a: MboValue | undefined, b: MboValue | undefined): number {\n if (a === undefined || b === undefined) return a === b ? 0 : a === undefined ? 1 : -1;\n if (typeof a === 'number' && typeof b === 'number') return a - b;\n const x = String(a);\n const y = String(b);\n return x < y ? -1 : x > y ? 1 : 0;\n}\n\n/**\n * `_orderby`/`_orderbyasc` (ascending) and `_orderbydesc`, each a comma-separated attribute\n * list. Keys apply in the order they appear in the query string (the guide does not say how\n * the lists combine). The sort is stable, so ties keep seed order.\n */\nfunction orderBy(req: EmulationRequest, object: string): Comparator | undefined {\n const keys: { attr: string; sign: number }[] = [];\n for (const [key, value] of req.url.searchParams) {\n const name = key.toLowerCase();\n const sign = name === '_orderby' || name === '_orderbyasc' ? 1 : name === '_orderbydesc' ? -1 : 0;\n if (sign === 0) continue;\n for (const part of value.split(',')) if (part.trim()) keys.push({ attr: knownAttribute(object, part.trim()), sign });\n }\n if (keys.length === 0) return undefined;\n return (a, b) => {\n for (const { attr, sign } of keys) {\n const c = compareValues(a[attr], b[attr]);\n if (c !== 0) return sign * c;\n }\n return 0;\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Saved rows\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst MAX_ROWS_PER_ROOT = 1000;\nconst MAX_ROOTS = 100;\nconst ROOT_IDLE_MS = 6 * 3_600_000;\nconst ROOT_MAX_AGE_MS = 24 * 3_600_000;\n\ninterface WritableObject {\n def: MboObjectDef;\n attributes: ReadonlyMap<string, AttributeDef>;\n keyAttributes: readonly string[];\n /** The unique id Maximo assigns (the object's BIGINT attribute); read-only. */\n idAttribute: string;\n /** Seeded rows by primary key. */\n seededByKey: ReadonlyMap<string, Row>;\n seededMaxId: number;\n}\n\nconst primaryKey = (keyAttributes: readonly string[], row: Readonly<Record<string, MboValue | undefined>>) =>\n JSON.stringify(keyAttributes.map((a) => row[a] ?? null));\n\n/** The objects writes are served for: business objects with a unique id. */\nconst WRITABLE: ReadonlyMap<string, WritableObject> = new Map(\n MBO_OBJECTS.flatMap((def): [string, WritableObject][] => {\n const idAttribute = UNIQUE_IDS.get(def.name);\n if (!idAttribute) return [];\n const keyAttributes = def.attributes.filter((a) => a.keySeq !== undefined).map((a) => a.name);\n const seeded = SEEDED.get(def.name)!;\n return [\n [\n def.name,\n {\n def,\n attributes: new Map(def.attributes.map((a) => [a.name, a])),\n keyAttributes,\n idAttribute,\n seededByKey: new Map(seeded.map((r) => [primaryKey(keyAttributes, r.row), r])),\n seededMaxId: Math.max(0, ...seeded.map((r) => Number(r.row[idAttribute] ?? 0))),\n },\n ],\n ];\n })\n);\n\n/** Each site's organization, from the seeded rows. */\nconst SITE_ORGS: ReadonlyMap<string, MboValue> = new Map(\n MBO_OBJECTS.flatMap((o) => o.records).flatMap((r) => (r['SITEID'] && r['ORGID'] ? [[String(r['SITEID']), r['ORGID']] as const] : []))\n);\n\n/** Drop roots idle past the TTL or older than the max age. */\nfunction sweep(state: MaximoStubState): void {\n const now = Date.now();\n for (const [name, root] of state.roots) {\n if (now - root.touchedAt > ROOT_IDLE_MS || now - root.createdAt > ROOT_MAX_AGE_MS) state.roots.delete(name);\n }\n}\n\n/**\n * An object's rows for one root: the seeded rows, each replaced by the row saved under\n * its key, then the other saved rows.\n */\nfunction rowsFor(state: MaximoStubState, root: string, object: string): readonly Row[] {\n const seeded = SEEDED.get(object)!;\n const saved = state.roots.get(root)?.objects.get(object);\n const writable = WRITABLE.get(object);\n if (!saved || !writable) return seeded;\n const rows = seeded.map((r) => saved.get(primaryKey(writable.keyAttributes, r.row)) ?? r);\n for (const [key, r] of saved) if (!writable.seededByKey.has(key)) rows.push(r);\n return rows;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Query Records\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * `allAttributes` (`_dropnulls=0`) adds the attributes the row has no value for. Not compact,\n * the unique id attribute also carries `resourceid: true`, the field metadata compact drops.\n */\nfunction serialize(\n { row, rowstamp }: Row,\n compact: boolean,\n allAttributes: ReadonlySet<string> | undefined,\n uniqueId: string | undefined\n): object {\n const nulls = allAttributes ? [...allAttributes].filter((a) => !(a in row)) : [];\n if (compact) return { ...row, ...Object.fromEntries(nulls.map((a) => [a, null])) };\n const attributes = Object.fromEntries([\n ...Object.entries(row).map(([k, v]) => [k, k === uniqueId ? { content: v, resourceid: true } : { content: v }]),\n ...nulls.map((a) => [a, {}]),\n ]);\n return { rowstamp, Attributes: attributes };\n}\n\n/** The `_compact` and `_dropnulls` options of a response. */\nfunction serializer(req: EmulationRequest, object: string): (row: Row) => object {\n const compact = flag(queryParam(req, '_compact')) === true;\n // Maximo drops null attributes unless `_dropnulls=0`.\n const allAttributes = flag(queryParam(req, '_dropnulls')) === false ? ATTRIBUTES.get(object) : undefined;\n const uniqueId = UNIQUE_IDS.get(object);\n return (row) => serialize(row, compact, allAttributes, uniqueId);\n}\n\nfunction queryRecords(req: EmulationRequest, state: MaximoStubState): EmulationResponse {\n const object = req.params['object']!.toUpperCase();\n if (!RECORDS.has(object)) throw new MaximoError(404, `Unsupported object in emulator: ${object.slice(0, 64)}`);\n const records = rowsFor(state, req.params['root']!, object);\n\n const exact = flag(queryParam(req, '_exactmatch')) === true;\n const where: Predicate[] = [];\n const attributeFilters: Predicate[] = [];\n for (const [key, value] of req.url.searchParams) {\n const name = key.toLowerCase();\n if (name === '_uw') where.push(whereFilter(object, value));\n // Other `_` system parameters and the API key are not row filters.\n else if (!name.startsWith('_') && name !== 'apikey') {\n // `status.ormode=1` and other modifiers on an attribute change how its filters combine;\n // other dotted names (`oslc.select`, an unknown attribute's modifier) are ignored like unknown attributes.\n if (name.includes('.') && isAttribute(object, name.split('.')[0]!.toUpperCase())) {\n throw new MaximoError(400, `Unsupported attribute modifier in emulator: ${name.slice(0, 64)}`);\n }\n const filter = attributeFilter(object, key, value, exact);\n if (filter) attributeFilters.push(filter);\n }\n }\n // `_opmodeor=1` ORs the attribute filters; `_uw` is always ANDed with them. With no\n // filter left (all ignored), every row matches, as with no filter at all.\n const or = flag(queryParam(req, '_opmodeor')) === true;\n const matchAttributes: Predicate = (row) =>\n attributeFilters.length === 0 || (or ? attributeFilters.some((f) => f(row)) : attributeFilters.every((f) => f(row)));\n const indexed = records.filter(({ row }) => matchAttributes(row) && where.every((f) => f(row)));\n const compare = orderBy(req, object);\n if (compare) indexed.sort((a, b) => compare(a.row, b.row));\n\n const rsStart = nonNegativeInt(req, '_rsStart') ?? 0;\n const maxItems = nonNegativeInt(req, '_maxItems');\n const page = indexed.slice(rsStart, maxItems === undefined ? undefined : rsStart + maxItems);\n return {\n status: 200,\n body: {\n [`${object}MboSet`]: {\n rsStart,\n rsCount: page.length,\n rsTotal: indexed.length,\n [object]: page.map(serializer(req, object)),\n },\n },\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Writes\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** A form value as the attribute's type stores it; undefined clears the attribute. */\nfunction attributeValue(object: string, def: AttributeDef, raw: string): MboValue | undefined {\n if (raw === '') return undefined;\n if (def.type === 'INTEGER') {\n const n = Number(raw);\n if (raw.trim() === '' || !Number.isInteger(n)) throw new MaximoError(400, `Invalid integer for ${def.name}`);\n return n;\n }\n if (def.type === 'YORN') {\n const yes = YES_NO.get(raw.toLowerCase());\n if (yes === undefined) throw new MaximoError(400, `Invalid yes/no value for ${def.name}; expected 1, 0, Y, N, true or false`);\n return yes;\n }\n if (def.type === 'DATETIME') {\n if (Number.isNaN(Date.parse(raw))) throw new MaximoError(400, `Invalid date for ${def.name}`);\n return raw;\n }\n const value = def.type === 'UPPER' ? raw.toUpperCase() : raw;\n if (value.length > def.length) throw new MaximoError(400, `${def.name} on ${object} is longer than ${def.length} characters`);\n // Maximo's message for a value outside the attribute's domain is BMXAA4190E \"<title> <value> is not\n // in the value list.\", as in IBM support 7027815 (\"BMXAA4190E - Status BOBA is not in the value\n // list.\") and APAR IJ31643 (\"BMXAA4190E - Type CAUSE is not in the value list.\").\n if (def.domain && !def.domain.has(value)) {\n throw new MaximoError(400, `BMXAA4190E - ${def.title} ${value.slice(0, 64)} is not in the value list.`, 'BMXAA4190E');\n }\n return value;\n}\n\n/** `_action` (case-insensitive): which of a missing and an existing row it may save. */\nconst WRITE_MODES: ReadonlyMap<string, { create: boolean; update: boolean }> = new Map([\n ['', { create: true, update: false }],\n ['add', { create: true, update: false }],\n ['change', { create: false, update: true }],\n ['addchange', { create: true, update: true }],\n]);\n\nfunction writeRecord(req: EmulationRequest, state: MaximoStubState): EmulationResponse {\n const object = req.params['object']!.toUpperCase();\n const writable = WRITABLE.get(object);\n if (!writable) throw new MaximoError(404, `Unsupported object in emulator: ${object.slice(0, 64)}`);\n // Like Maximo (servlet parameters), system parameters may come in the query or the form body.\n const form = new URLSearchParams(req.body ?? '');\n // Id route (`.../<OBJECT>/<id>`): always a Change of that row; `_action` and `x-method-override` are ignored.\n const id = req.params['id'];\n const target = id === undefined ? undefined : rowsFor(state, req.params['root']!, object).find((r) => String(r.row[writable.idAttribute]) === id);\n if (id !== undefined && !target) throw new MaximoError(404, `No ${object} record with ${writable.idAttribute} ${id.slice(0, 64)}`);\n const action = id !== undefined ? 'Change' : (queryParam(req, '_action') ?? form.get('_action') ?? '');\n const mode = WRITE_MODES.get(action.toLowerCase());\n if (!mode) throw new MaximoError(400, `Unsupported _action in emulator: ${action.slice(0, 64)}`);\n\n const changes = new Map<string, MboValue | undefined>();\n for (const [key, raw] of form) {\n // System parameters (`_format`, `_lid`, ...) and the API key are not attributes.\n if (key.startsWith('_') || key.toLowerCase() === 'apikey') continue;\n const def = writable.attributes.get(key.toUpperCase());\n if (!def) throw new MaximoError(400, `Unknown attribute ${key.toUpperCase().slice(0, 64)} on ${object}`);\n if (def.name === writable.idAttribute) throw new MaximoError(400, `${def.name} on ${object} is read-only`);\n changes.set(def.name, attributeValue(object, def, raw));\n }\n if (target) {\n for (const name of writable.keyAttributes) {\n if (changes.has(name) && changes.get(name) !== target.row[name]) throw new MaximoError(400, `${name} on ${object} cannot be changed`);\n changes.set(name, target.row[name]);\n }\n }\n for (const name of writable.keyAttributes) {\n if (changes.get(name) === undefined) {\n throw new MaximoError(400, `A value is required for the ${writable.attributes.get(name)!.title} field on the ${object} object.`);\n }\n }\n\n const rootName = req.params['root']!;\n const saved = state.roots.get(rootName)?.objects.get(object);\n const key = primaryKey(writable.keyAttributes, Object.fromEntries(changes));\n const existing = saved?.get(key) ?? writable.seededByKey.get(key);\n if (existing && !mode.update) throw new MaximoError(400, `A ${object} record with this key already exists`);\n if (!existing && !mode.create) throw new MaximoError(404, `No ${object} record with this key`);\n const row: Record<string, MboValue> = { ...existing?.row };\n for (const [name, value] of changes) {\n if (value === undefined) delete row[name];\n else row[name] = value;\n }\n if (writable.def.siteOrgType === 'SITE' && row['SITEID'] !== undefined) {\n const site = String(row['SITEID']);\n const org = SITE_ORGS.get(site);\n if (org === undefined) throw new MaximoError(400, `Site ${site.slice(0, 64)} is not valid`);\n if (row['ORGID'] !== undefined && row['ORGID'] !== org) throw new MaximoError(400, `Site ${site} is not in organization ${String(row['ORGID']).slice(0, 64)}`);\n row['ORGID'] = org;\n }\n if (!existing) {\n // Maximo's out-of-the-box initial work-order status (IBM, \"Work order statuses\").\n if (object === 'WORKORDER' && !changes.has('STATUS')) row['STATUS'] = 'WAPPR';\n const savedIds = [...(saved?.values() ?? [])].map((r) => Number(r.row[writable.idAttribute] ?? 0));\n row[writable.idAttribute] = object === 'WORKORDER' ? state.nextWorkOrderId++ : Math.max(writable.seededMaxId, ...savedIds) + 1;\n }\n\n const result = saveRecord(state, rootName, object, key, row);\n return { status: 200, body: { [object]: serializer(req, object)(result) } };\n}\n\n/** Save through the same tenant limits and rowstamp rules for attribute and web-method writes. */\nfunction saveRecord(state: MaximoStubState, rootName: string, object: string, key: string, row: Readonly<MboRecord>): Row {\n const root = state.roots.get(rootName);\n if (!root?.objects.get(object)?.has(key)) {\n const rootRows = root ? [...root.objects.values()].reduce((n, m) => n + m.size, 0) : 0;\n if (rootRows >= MAX_ROWS_PER_ROOT) throw new MaximoError(400, `Emulator write limit reached (${MAX_ROWS_PER_ROOT} rows per root)`);\n }\n const result: Row = { row, rowstamp: String(state.nextRowstamp++) };\n const now = Date.now();\n let target = root;\n if (!target) {\n // At the limit, a new root replaces the least recently used one rather than failing every new run.\n if (state.roots.size >= MAX_ROOTS) {\n const [lru] = [...state.roots].reduce((a, b) => (b[1].touchedAt < a[1].touchedAt ? b : a));\n state.roots.delete(lru);\n }\n state.roots.set(rootName, (target = { objects: new Map(), createdAt: now, touchedAt: now }));\n }\n let objectRows = target.objects.get(object);\n if (!objectRows) target.objects.set(object, (objectRows = new Map()));\n objectRows.set(key, result);\n target.touchedAt = now;\n return result;\n}\n\n/** The status-only OSLC update emitted after an MBO AddChange, on a separate API path. */\nfunction updateOslcStatus(req: EmulationRequest, state: MaximoStubState): EmulationResponse {\n if (req.headers['x-method-override']?.toUpperCase() !== 'PATCH') {\n throw new MaximoError(400, 'OSLC status updates require x-method-override: PATCH');\n }\n let body: unknown;\n try {\n body = JSON.parse(req.body ?? '');\n } catch {\n throw new MaximoError(400, 'Invalid JSON status update');\n }\n const parsed = z.object({ status: z.string().min(1), statusdate: z.string().min(1) }).strict().safeParse(body);\n if (!parsed.success) throw new MaximoError(400, 'Expected status and statusdate in the OSLC status update');\n const writable = WRITABLE.get('WORKORDER')!;\n const status = attributeValue('WORKORDER', writable.attributes.get('STATUS')!, parsed.data.status)!;\n const date = attributeValue('WORKORDER', writable.attributes.get('STATUSDATE')!, parsed.data.statusdate)!;\n const id = req.params['id']!;\n const matches: { root: string; key: string; value: Row }[] = [];\n for (const [root, tenant] of state.roots) {\n for (const [key, value] of tenant.objects.get('WORKORDER') ?? []) {\n if (String(value.row['WORKORDERID']) === id) matches.push({ root, key, value });\n }\n }\n if (matches.length === 0) throw new MaximoError(404, `No saved WORKORDER resource ${id.slice(0, 64)}`);\n if (matches.length !== 1) throw new MaximoError(409, 'WORKORDER id is ambiguous across emulator roots');\n const match = matches[0]!;\n const site = queryParam(req, 'SITEID');\n if (site !== undefined && site !== match.value.row['SITEID']) throw new MaximoError(404, 'WORKORDER is not in the requested site');\n saveRecord(state, match.root, 'WORKORDER', match.key, { ...match.value.row, STATUS: status, STATUSDATE: date });\n return { status: 204 };\n}\n\n/** Sweep idle roots, mark this one used, and answer MaximoError as Maximo's error body. */\nfunction mbo(handler: (req: EmulationRequest, state: MaximoStubState) => EmulationResponse): Handler {\n return authed((req, ctx) => {\n sweep(ctx.state);\n const rootName = req.params['root'];\n const root = rootName === undefined ? undefined : ctx.state.roots.get(rootName);\n if (root) root.touchedAt = Date.now();\n try {\n return handler(req, ctx.state);\n } catch (err) {\n if (err instanceof MaximoError) return errorBody(err.status, err.message, err.reasonCode);\n throw err;\n }\n });\n}\n\n/**\n * Anything else records as unmatched, so real traffic shows what to add next. A read\n * outside the served slice gets 404 rather than an empty answer. A write gets 200 `{}`\n * and is not stored: tests drive a connector's writes into the stub and assert on the\n * request log, so the connector must not fail the run on them.\n */\nconst recordOnly = authed((req) =>\n req.method === 'GET'\n ? errorBody(404, `Unsupported request in emulator: GET ${req.url.pathname.slice(0, 200)}`)\n : { status: 200, body: {} }\n);\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Plugin\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const maximoStubPlugin: EmulationPlugin<MaximoStubConfig, Record<string, never>, MaximoStubState> = {\n id: 'maximo-stub',\n name: 'Maximo MBO REST Stub',\n version: '1.8.0',\n\n domains: (config) => [config.host.toLowerCase()],\n needsBrowserIntercept: false,\n\n routes: [\n { method: 'GET', path: '/:root/restapi/mbo/:object', handler: mbo(queryRecords) },\n { method: 'POST', path: '/:root/restapi/mbo/:object', handler: mbo(writeRecord) },\n { method: 'POST', path: '/:root/restapi/mbo/:object/:id', handler: mbo(writeRecord) },\n { method: 'POST', path: '/:osRoot/api/os/mxapiwo/:id', handler: mbo(updateOslcStatus) },\n { method: '*', path: '*', handler: recordOnly },\n ],\n\n initialize: (config) => ({\n apiKey: configSchema.parse(config).apiKey,\n roots: new Map(),\n // Above every seeded row's rowstamp (1000 + its place).\n nextRowstamp: 100_000,\n // The fixed OSLC path carries no MBO tenant root, so assigned ids must be host-unique.\n nextWorkOrderId: WRITABLE.get('WORKORDER')!.seededMaxId + 1,\n }),\n\n countActive(ctx, sinceMs) {\n sweep(ctx.state);\n return [...ctx.state.roots.values()].filter((r) => r.touchedAt >= sinceMs).length;\n },\n};\n","/**\n * Inline catalogue and seeded records for the Maximo stub (maximo-stub.ts).\n * Neutral example data only: organization ACME, site SITE1.\n *\n * @module\n */\n\n/** A Maximo attribute value as the MBO REST API serializes it in JSON. */\nexport type MboValue = string | number | boolean;\n/** One MBO row, keyed by upper-case attribute name. */\nexport type MboRecord = Readonly<Record<string, MboValue>>;\n\nexport interface AttributeDef {\n name: string;\n /** MAXATTRIBUTE.MAXTYPE (ALN, UPPER, INTEGER, DECIMAL, DATETIME, YORN, ...) */\n type: string;\n length: number;\n required: boolean;\n title: string;\n /** MAXATTRIBUTE.PRIMARYKEYCOLSEQNO, for primary-key columns only */\n keySeq?: number;\n /** The values a write may set, for an attribute bound to a domain the stub models (see WOSTATUS); compared with the stored (for UPPER, upper-cased) value */\n domain?: ReadonlySet<string>;\n}\n\nexport interface MboObjectDef {\n name: string;\n description: string;\n /** MAXOBJECT.SITEORGTYPE */\n siteOrgType: 'SITE' | 'ORG' | 'SYSTEM';\n /** MAXOBJECTCFG.SERVICENAME: the MAXSERVICE owning the object's Java package (psdi.app.site → SITE, psdi.app.ticket → TICKET) */\n service: string;\n attributes: readonly AttributeDef[];\n records: readonly MboRecord[];\n}\n\nconst attr = (name: string, type: string, length: number, required: boolean, title: string, keySeq?: number): AttributeDef => ({\n name,\n type,\n length,\n required,\n title,\n ...(keySeq === undefined ? {} : { keySeq }),\n});\n\n/**\n * WOSTATUS, the synonym domain WORKORDER.STATUS is bound to: its internal values, as IBM\n * documents them (\"Work order statuses\", Maximo Asset Management 7.6.1.2). A real site may\n * add synonyms for these values; the stub serves only the out-of-the-box ones, whose\n * default synonym is the internal value itself.\n */\nconst WOSTATUS: ReadonlySet<string> = new Set(['WAPPR', 'APPR', 'WSCH', 'WMATL', 'WPCOND', 'INPRG', 'COMP', 'CLOSE', 'CAN', 'HISTEDIT']);\n\nconst SITE = { ORGID: 'ACME', SITEID: 'SITE1' };\n\n/** The business objects the stub serves, in MAXOBJECT order. */\nexport const MBO_OBJECTS: readonly MboObjectDef[] = [\n {\n name: 'ORGANIZATION',\n description: 'Organizations',\n siteOrgType: 'SYSTEM',\n service: 'SITE',\n attributes: [\n attr('ORGID', 'UPPER', 8, true, 'Organization', 1),\n attr('DESCRIPTION', 'ALN', 100, false, 'Description'),\n attr('ACTIVE', 'YORN', 1, true, 'Active'),\n attr('BASECURRENCY1', 'UPPER', 8, true, 'Base Currency 1'),\n ],\n records: [{ ORGID: 'ACME', DESCRIPTION: 'Acme Utilities', ACTIVE: true, BASECURRENCY1: 'USD' }],\n },\n {\n name: 'WORKORDER',\n description: 'Work Orders',\n siteOrgType: 'SITE',\n service: 'WORKORDER',\n attributes: [\n attr('WONUM', 'UPPER', 25, true, 'Work Order', 1),\n attr('SITEID', 'UPPER', 8, true, 'Site', 2),\n attr('ORGID', 'UPPER', 8, true, 'Organization'),\n attr('DESCRIPTION', 'ALN', 100, false, 'Description'),\n { ...attr('STATUS', 'UPPER', 16, true, 'Status'), domain: WOSTATUS },\n attr('STATUSDATE', 'DATETIME', 10, false, 'Status Date'),\n attr('WORKTYPE', 'UPPER', 5, false, 'Work Type'),\n attr('ASSETNUM', 'UPPER', 25, false, 'Asset'),\n attr('LOCATION', 'UPPER', 50, false, 'Location'),\n attr('WOPRIORITY', 'INTEGER', 12, false, 'Priority'),\n attr('REPORTDATE', 'DATETIME', 10, false, 'Reported Date'),\n attr('WORKORDERID', 'BIGINT', 19, true, 'Work Order ID'),\n ],\n records: [\n { WONUM: '1001', ...SITE, DESCRIPTION: 'Inspect main pump', STATUS: 'APPR', WORKTYPE: 'PM', ASSETNUM: 'PUMP-100', LOCATION: 'PLANT-A', WOPRIORITY: 2, REPORTDATE: '2026-01-05T08:00:00-05:00', WORKORDERID: 501 },\n { WONUM: '1002', ...SITE, DESCRIPTION: 'Replace valve seal', STATUS: 'WAPPR', WORKTYPE: 'CM', ASSETNUM: 'VALVE-200', LOCATION: 'PLANT-A', WOPRIORITY: 1, REPORTDATE: '2026-01-06T09:30:00-05:00', WORKORDERID: 502 },\n { WONUM: '1003', ...SITE, DESCRIPTION: 'Lubricate conveyor bearings', STATUS: 'APPR', WORKTYPE: 'PM', ASSETNUM: 'CONV-300', LOCATION: 'PLANT-B', WOPRIORITY: 3, REPORTDATE: '2026-01-07T10:15:00-05:00', WORKORDERID: 503 },\n { WONUM: '1004', ...SITE, DESCRIPTION: 'Repair hydrant leak', STATUS: 'INPRG', WORKTYPE: 'EM', ASSETNUM: 'HYD-400', LOCATION: 'STREET-12', WOPRIORITY: 1, REPORTDATE: '2026-01-08T14:45:00-05:00', WORKORDERID: 504 },\n { WONUM: '1005', ...SITE, DESCRIPTION: 'Calibrate flow meter', STATUS: 'COMP', WORKTYPE: 'PM', ASSETNUM: 'METER-500', LOCATION: 'PLANT-B', WOPRIORITY: 3, REPORTDATE: '2026-01-09T07:20:00-05:00', WORKORDERID: 505 },\n ],\n },\n {\n name: 'ASSET',\n description: 'Assets',\n siteOrgType: 'SITE',\n service: 'ASSET',\n attributes: [\n attr('ASSETNUM', 'UPPER', 25, true, 'Asset', 1),\n attr('SITEID', 'UPPER', 8, true, 'Site', 2),\n attr('ORGID', 'UPPER', 8, true, 'Organization'),\n attr('DESCRIPTION', 'ALN', 100, false, 'Description'),\n attr('STATUS', 'UPPER', 20, true, 'Status'),\n attr('LOCATION', 'UPPER', 50, false, 'Location'),\n attr('SERIALNUM', 'ALN', 64, false, 'Serial #'),\n attr('ASSETID', 'BIGINT', 19, true, 'Asset ID'),\n ],\n records: [\n { ASSETNUM: 'PUMP-100', ...SITE, DESCRIPTION: 'Main water pump', STATUS: 'OPERATING', LOCATION: 'PLANT-A', SERIALNUM: 'SN-1001', ASSETID: 201 },\n { ASSETNUM: 'VALVE-200', ...SITE, DESCRIPTION: 'Isolation valve', STATUS: 'OPERATING', LOCATION: 'PLANT-A', SERIALNUM: 'SN-2002', ASSETID: 202 },\n { ASSETNUM: 'CONV-300', ...SITE, DESCRIPTION: 'Conveyor belt line 3', STATUS: 'OPERATING', LOCATION: 'PLANT-B', SERIALNUM: 'SN-3003', ASSETID: 203 },\n { ASSETNUM: 'HYD-400', ...SITE, DESCRIPTION: 'Fire hydrant', STATUS: 'BROKEN', LOCATION: 'STREET-12', SERIALNUM: 'SN-4004', ASSETID: 204 },\n { ASSETNUM: 'METER-500', ...SITE, DESCRIPTION: 'Booster pump flow meter', STATUS: 'NOT READY', LOCATION: 'PLANT-B', SERIALNUM: 'SN-5005', ASSETID: 205 },\n ],\n },\n {\n name: 'LOCATIONS',\n description: 'Locations',\n siteOrgType: 'SITE',\n service: 'LOCATION',\n attributes: [\n attr('LOCATION', 'UPPER', 50, true, 'Location', 1),\n attr('SITEID', 'UPPER', 8, true, 'Site', 2),\n attr('ORGID', 'UPPER', 8, true, 'Organization'),\n attr('DESCRIPTION', 'ALN', 100, false, 'Description'),\n attr('TYPE', 'UPPER', 16, true, 'Type'),\n attr('STATUS', 'UPPER', 20, true, 'Status'),\n attr('LOCATIONSID', 'BIGINT', 19, true, 'Locations ID'),\n ],\n records: [\n { LOCATION: 'PLANT-A', ...SITE, DESCRIPTION: 'Treatment plant A', TYPE: 'OPERATING', STATUS: 'OPERATING', LOCATIONSID: 301 },\n { LOCATION: 'PLANT-B', ...SITE, DESCRIPTION: 'Treatment plant B', TYPE: 'OPERATING', STATUS: 'OPERATING', LOCATIONSID: 302 },\n { LOCATION: 'STREET-12', ...SITE, DESCRIPTION: '12th Street distribution', TYPE: 'OPERATING', STATUS: 'OPERATING', LOCATIONSID: 303 },\n ],\n },\n {\n name: 'SR',\n description: 'Service Requests',\n siteOrgType: 'SITE',\n service: 'TICKET',\n attributes: [\n attr('TICKETID', 'UPPER', 10, true, 'Service Request', 1),\n attr('CLASS', 'UPPER', 16, true, 'Class', 2),\n attr('SITEID', 'UPPER', 8, false, 'Site'),\n attr('ORGID', 'UPPER', 8, false, 'Organization'),\n attr('DESCRIPTION', 'ALN', 100, false, 'Summary'),\n attr('STATUS', 'UPPER', 10, true, 'Status'),\n attr('REPORTEDBY', 'UPPER', 30, false, 'Reported By'),\n attr('REPORTDATE', 'DATETIME', 10, false, 'Reported Date'),\n attr('TICKETUID', 'BIGINT', 19, true, 'Ticket ID'),\n ],\n records: [\n { TICKETID: 'SR-2001', CLASS: 'SR', ...SITE, DESCRIPTION: 'Low water pressure on Elm St', STATUS: 'NEW', REPORTEDBY: 'JDOE', REPORTDATE: '2026-01-10T11:00:00-05:00', TICKETUID: 401 },\n { TICKETID: 'SR-2002', CLASS: 'SR', ...SITE, DESCRIPTION: 'Streetlight out near park', STATUS: 'QUEUED', REPORTEDBY: 'ASMITH', REPORTDATE: '2026-01-11T16:20:00-05:00', TICKETUID: 402 },\n ],\n },\n];\n\n/** MAXOBJECT rows: the object catalogue a connector's entity picker lists. */\nexport const MAXOBJECT_RECORDS: readonly MboRecord[] = MBO_OBJECTS.map((o) => ({\n OBJECTNAME: o.name,\n DESCRIPTION: o.description,\n ENTITYNAME: o.name,\n SITEORGTYPE: o.siteOrgType,\n PERSISTENT: true,\n}));\n\n/**\n * MAXOBJECTCFG rows: the object configuration table behind MAXOBJECT. A Maximo client's\n * entity picker lists it with `_uw=INTERNAL=0 AND ISVIEW=0 AND PERSISTENT=1`; every\n * served object is a persistent, non-internal table.\n */\nexport const MAXOBJECTCFG_RECORDS: readonly MboRecord[] = MBO_OBJECTS.map((o) => ({\n OBJECTNAME: o.name,\n DESCRIPTION: o.description,\n ENTITYNAME: o.name,\n SERVICENAME: o.service,\n SITEORGTYPE: o.siteOrgType,\n PERSISTENT: true,\n ISVIEW: false,\n INTERNAL: false,\n}));\n\n/**\n * CLASSSTRUCTURE rows: a small classification hierarchy for the seeded assets. HIERARCHYPATH\n * joins the CLASSIFICATIONIDs from the top with ` \\ ` (the form Maximo shows for a classification).\n */\nexport const CLASSSTRUCTURE_RECORDS: readonly MboRecord[] = [\n { CLASSSTRUCTUREID: '1001', CLASSIFICATIONID: 'PUMP', DESCRIPTION: 'Pumps', HIERARCHYPATH: 'PUMP', HASCHILDREN: true, ORGID: 'ACME' },\n { CLASSSTRUCTUREID: '1002', CLASSIFICATIONID: 'CENTRIFUGAL', DESCRIPTION: 'Centrifugal pumps', HIERARCHYPATH: 'PUMP \\\\ CENTRIFUGAL', PARENT: '1001', HASCHILDREN: false, ORGID: 'ACME' },\n { CLASSSTRUCTUREID: '1003', CLASSIFICATIONID: 'VALVE', DESCRIPTION: 'Valves', HIERARCHYPATH: 'VALVE', HASCHILDREN: false, ORGID: 'ACME' },\n { CLASSSTRUCTUREID: '1004', CLASSIFICATIONID: 'HYDRANT', DESCRIPTION: 'Fire hydrants', HIERARCHYPATH: 'HYDRANT', HASCHILDREN: false, ORGID: 'ACME' },\n];\n\n/** MAXATTRIBUTE rows: each object's attribute metadata. */\nexport const MAXATTRIBUTE_RECORDS: readonly MboRecord[] = MBO_OBJECTS.flatMap((o) =>\n o.attributes.map((a) => ({\n OBJECTNAME: o.name,\n ATTRIBUTENAME: a.name,\n MAXTYPE: a.type,\n LENGTH: a.length,\n REQUIRED: a.required,\n TITLE: a.title,\n PERSISTENT: true,\n ...(a.keySeq === undefined ? {} : { PRIMARYKEYCOLSEQNO: a.keySeq }),\n }))\n);\n","import { createHmac } from 'node:crypto';\n\nexport const GOOGLE_AUTHORIZE_LABEL = 'cofactor-google-authorize';\n\n/**\n * A key derived from the control token for one narrow purpose: base64url(HMAC-SHA256(key = controlToken, msg = label)).\n * It can be handed to a remote browser executor without exposing the control token.\n */\nexport function scopedKey(controlToken: string, label: string): string {\n return createHmac('sha256', controlToken).update(label).digest('base64url');\n}\n","/**\n * Per-copy sign-in gate for the `oidc` emulator.\n *\n * Both values derive from the copy's control token (nothing new is stored):\n * the sign-in key travels in the \"Open sign-in\" link; the gate value is the\n * cookie a browser holds after opening it, and the bearer automated paths\n * send. They differ so the key in a URL is never the cookie. The raw control\n * token is never accepted by the gate.\n *\n * @module\n */\n\nimport { scopedKey } from './authorize-key.js';\nimport { tokensMatch } from './token-match.js';\n\nexport const GATE_COOKIE = 'cofactor_oidc_gate';\n\nexport function signInKey(controlToken: string): string {\n return scopedKey(controlToken, 'cofactor-oidc-sign-in');\n}\n\nexport function gateCookieValue(controlToken: string): string {\n return scopedKey(controlToken, 'cofactor-oidc-gate');\n}\n\nexport function signInUrl(emulationOrigin: string, controlToken: string): string {\n return `${emulationOrigin}/oidc/enter?key=${signInKey(controlToken)}`;\n}\n\n/**\n * True for a Cookie header carrying `GATE_COOKIE=<gateCookieValue>`, or\n * `Authorization: Bearer <gateCookieValue>`. `headers` are keyed lowercase.\n */\nexport function gateAllows(headers: Record<string, string>, controlToken: string): boolean {\n const expected = gateCookieValue(controlToken);\n\n const authorization = headers['authorization'] ?? '';\n if (authorization.startsWith('Bearer ') && tokensMatch(authorization.slice('Bearer '.length).trim(), expected)) {\n return true;\n }\n\n for (const pair of (headers['cookie'] ?? '').split(';')) {\n const separator = pair.indexOf('=');\n if (separator < 0) continue;\n if (pair.slice(0, separator).trim() === GATE_COOKIE && tokensMatch(pair.slice(separator + 1).trim(), expected)) {\n return true;\n }\n }\n return false;\n}\n","/**\n * Generic OpenID Connect provider emulation plugin.\n *\n * One standards-conformant provider that any OIDC relying party (Auth0, Okta,\n * Cognito, Keycloak, ... configurations on the customer's side) points its\n * issuer at. It owns no domain: the router sends it every request whose Host\n * is not a registered domain, which is the copy's public emulator address.\n *\n * `/authorize` is gated: it answers only a browser that opened the copy's\n * sign-in link (cookie from `/oidc/enter`) or a caller holding the derived gate\n * value as a bearer. Token, userinfo, JWKS and discovery are ungated; a code\n * is redeemable only if `/authorize` issued it.\n *\n * @module\n */\n\nimport type { EmulationPlugin, EmulationRequest, EmulationResponse, PluginContext } from '../plugin.js';\nimport { GATE_COOKIE, gateAllows, gateCookieValue, signInKey } from '../sign-in-gate.js';\nimport { tokensMatch } from '../token-match.js';\nimport {\n authorize,\n handleDiscovery,\n handleJwks,\n handleToken,\n handleUserinfo,\n initializeOidcState,\n oidcFixtureSchema,\n type OidcContext,\n type OidcFixture,\n type OidcFlavor,\n type OidcState,\n} from './oidc-core.js';\n\n/** Declared `emulation: { oidc: {} }`; there are no options. */\nexport type OidcConfig = Record<string, never>;\n\n/**\n * The issuer: exactly the copy's public emulator origin, no trailing slash.\n * buildRouter guarantees `publicOrigins.emulation` is set for this plugin.\n */\nfunction issuerOrigin(ctx: PluginContext): string {\n return new URL(ctx.instance.publicOrigins['emulation']!).origin;\n}\n\nconst genericFlavor: OidcFlavor = {\n label: 'Cofactor sandbox',\n issuer: issuerOrigin,\n endpoints: (ctx) => {\n const issuer = issuerOrigin(ctx);\n return {\n authorization_endpoint: `${issuer}/authorize`,\n token_endpoint: `${issuer}/token`,\n userinfo_endpoint: `${issuer}/userinfo`,\n jwks_uri: `${issuer}/jwks`,\n };\n },\n extraClaims: {},\n};\n\nconst NO_STORE_HEADERS = {\n 'cache-control': 'no-store',\n 'referrer-policy': 'no-referrer',\n};\n\n// title and message are interpolated unescaped: pass literals only.\nfunction page(status: number, title: string, message: string, headers: Record<string, string> = {}): EmulationResponse {\n return {\n status,\n headers: { 'content-type': 'text/html; charset=utf-8', ...NO_STORE_HEADERS, ...headers },\n body: `<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>${title}</title></head><body style=\"font-family:system-ui,sans-serif;max-width:28rem;margin:4rem auto;padding:0 1rem\"><h1>${title}</h1><p>${message}</p></body></html>`,\n };\n}\n\n/** The redirect_uri must be http(s) and on one of the copy's public origins; the callback belongs to this copy. */\nfunction redirectUriIsOnThisCopy(redirectUri: string, ctx: PluginContext): boolean {\n try {\n const parsed = new URL(redirectUri);\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return false;\n return Object.values(ctx.instance.publicOrigins).some((origin) => new URL(origin).origin === parsed.origin);\n } catch {\n return false;\n }\n}\n\nfunction handleAuthorize(req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n if (!gateAllows(req.headers, ctx.instance.controlToken)) {\n return page(403, 'Sign-in is locked', \"Open this sandbox's sign-in link from Cofactor to sign in here.\");\n }\n\n const params = req.url.searchParams;\n const redirectUri = params.get('redirect_uri');\n if (params.get('response_type') !== 'code' || !params.get('client_id') || !redirectUri) {\n return page(400, 'Invalid sign-in request', 'The request needs response_type=code, client_id and redirect_uri.');\n }\n if (!redirectUriIsOnThisCopy(redirectUri, ctx)) {\n return page(400, 'Invalid sign-in request', \"The redirect_uri is not an address of this sandbox, so sign-in was not completed.\");\n }\n\n return authorize(genericFlavor, ctx, req.url);\n}\n\nfunction handleEnter(req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n const key = req.url.searchParams.get('key') ?? '';\n if (!tokensMatch(key, signInKey(ctx.instance.controlToken))) {\n return page(403, 'Sign-in link not valid', \"This sign-in link is not valid for this sandbox. Open the current link from Cofactor.\");\n }\n return {\n status: 303,\n headers: {\n location: '/oidc/ready',\n 'set-cookie': `${GATE_COOKIE}=${gateCookieValue(ctx.instance.controlToken)}; HttpOnly; Secure; SameSite=Lax; Path=/`,\n ...NO_STORE_HEADERS,\n },\n body: '',\n };\n}\n\nfunction handleReady(): EmulationResponse {\n return page(200, 'Sign-in is unlocked', 'Sign-in is unlocked for this browser. Return to the app and sign in.');\n}\n\nexport const oidcPlugin: EmulationPlugin<OidcConfig, OidcFixture, OidcState> = {\n id: 'oidc',\n name: 'OpenID Connect provider',\n version: '1.0.0',\n domains: [],\n servesPublicOrigin: true,\n needsBrowserIntercept: false,\n routes: [\n { method: 'GET', path: '/.well-known/openid-configuration', handler: (req, ctx) => handleDiscovery(genericFlavor, req, ctx) },\n { method: 'GET', path: '/jwks', handler: handleJwks },\n { method: 'GET', path: '/oidc/enter', handler: handleEnter },\n { method: 'GET', path: '/oidc/ready', handler: handleReady },\n { method: 'GET', path: '/authorize', handler: handleAuthorize },\n { method: 'POST', path: '/token', handler: (req, ctx) => handleToken(genericFlavor, req, ctx) },\n { method: 'GET', path: '/userinfo', handler: (req, ctx) => handleUserinfo(genericFlavor, req, ctx) },\n { method: 'POST', path: '/userinfo', handler: (req, ctx) => handleUserinfo(genericFlavor, req, ctx) },\n ],\n initialize: (_config, fixture) => initializeOidcState(fixture, null),\n fixtureSchema: oidcFixtureSchema,\n};\n","/**\n * Slack API Emulation Plugin\n *\n * Emulates the Slack Web API for sandboxed apps so customers can test their\n * Slack integration end-to-end without a real workspace:\n *\n * - Sandbox-side: OAuth token exchange, auth.test, conversations, chat.postMessage\n * (recorded into state for assertions), users/team info.\n * - Browser-side: intercepts the slack.com/oauth/v2/authorize redirect so the\n * connect flow completes headlessly.\n * - Inbound events: builds signed `event_callback` webhooks (app_mention,\n * message, reaction_added) that the control plane fires INTO the app. The\n * HMAC scheme is byte-compatible with Slack's `v0=` signing, so the app's\n * production signature verification passes using the shared signing secret\n * from the env contract.\n *\n * Response shapes mirror the zod schemas in @chatsdet/slack (types.ts) —\n * conformance is asserted in slack.test.ts.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport { z } from 'zod';\nimport type {\n ActionInterfaceDef,\n EmulationPlugin,\n EmulationRequest,\n EmulationResponse,\n InboundEventDef,\n PluginContext,\n} from '../plugin.js';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface SlackEmuConfig {\n /** Override the app_id reported by oauth.v2.access */\n appId?: string;\n}\n\nconst SlackEmuChannelSchema = z.object({\n id: z.string(),\n name: z.string(),\n is_private: z.boolean().optional(),\n is_member: z.boolean().optional(),\n is_archived: z.boolean().optional(),\n});\n\nconst SlackEmuUserSchema = z.object({\n id: z.string(),\n name: z.string(),\n real_name: z.string().optional(),\n email: z.string().optional(),\n is_bot: z.boolean().optional(),\n});\n\nexport const slackFixtureSchema = z.object({\n team: z.object({\n id: z.string(),\n name: z.string(),\n domain: z.string().optional(),\n }),\n botUserId: z.string(),\n channels: z.array(SlackEmuChannelSchema),\n users: z.array(SlackEmuUserSchema),\n});\n\nexport type SlackEmuChannel = z.infer<typeof SlackEmuChannelSchema>;\nexport type SlackEmuUser = z.infer<typeof SlackEmuUserSchema>;\nexport type SlackFixture = z.infer<typeof slackFixtureSchema>;\n\nexport interface PostedMessage {\n channel: string;\n text: string;\n ts: string;\n thread_ts?: string;\n user: string;\n blocks?: unknown;\n attachments?: unknown;\n}\n\nexport interface SlackState {\n team: SlackFixture['team'];\n botUserId: string;\n appId: string;\n channels: Map<string, SlackEmuChannel>;\n users: Map<string, SlackEmuUser>;\n /** Messages the app posted via chat.postMessage — the assertion surface */\n postedMessages: PostedMessage[];\n botToken: string;\n tsCounter: number;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Constants\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst EMULATED_CODE_PREFIX = 'emulated_code_';\nconst DEFAULT_APP_ID = 'A_EMULATED';\n\n/** Mirrors SLACK_BOT_SCOPES in @chatsdet/slack (kept local — runtime dep is dev-only) */\nconst EMULATED_BOT_SCOPES =\n 'chat:write,channels:read,groups:read,team:read,app_mentions:read,channels:history,groups:history,reactions:read,users:read,users:read.email,files:write';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype SlackCtx = PluginContext<SlackFixture, SlackState>;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- parsing untrusted API input\nfunction safeParseJson(body: string | undefined): { ok: true; data: any } | { ok: false; error: EmulationResponse } {\n try {\n return { ok: true, data: JSON.parse(body ?? '{}') };\n } catch {\n return { ok: false, error: slackError('invalid_json') };\n }\n}\n\n/** Slack returns HTTP 200 with `{ok:false, error}` for API-level failures. */\nfunction slackError(error: string): EmulationResponse {\n return { status: 200, body: { ok: false, error } };\n}\n\n/**\n * Enforce bot-token auth the way Slack does: bearer must match the token\n * minted at provision. Returns null when authorized.\n */\nfunction requireBot(req: EmulationRequest, ctx: SlackCtx): EmulationResponse | null {\n const auth = req.headers['authorization'] ?? '';\n const token = auth.startsWith('Bearer ') ? auth.slice('Bearer '.length).trim() : '';\n if (!token) return slackError('not_authed');\n if (token !== ctx.state.botToken) return slackError('invalid_auth');\n return null;\n}\n\n/** Mint a Slack-style message ts: unix seconds + monotonic counter suffix. */\nfunction mintTs(state: SlackState): string {\n const seconds = Math.floor(Date.now() / 1000);\n state.tsCounter += 1;\n return `${seconds}.${String(state.tsCounter).padStart(6, '0')}`;\n}\n\n/** Read a param from query string (GET) or JSON body (POST). */\nfunction readParam(req: EmulationRequest, key: string): string | undefined {\n const fromQuery = req.url.searchParams.get(key);\n if (fromQuery !== null) return fromQuery;\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return undefined;\n const value = parsed.data[key];\n return value === undefined || value === null ? undefined : String(value);\n}\n\nfunction signSlackRequest(signingSecret: string, timestamp: string, body: string): string {\n const basestring = `v0:${timestamp}:${body}`;\n return `v0=${crypto.createHmac('sha256', signingSecret).update(basestring).digest('hex')}`;\n}\n\n/** Build a signed event_callback request aimed at the app's webhook path. */\nfunction buildSignedEvent(opts: {\n env: Record<string, string>;\n targetPath: string;\n teamId: string;\n event: Record<string, unknown>;\n}): ReturnType<InboundEventDef['build']> {\n const body = JSON.stringify({\n type: 'event_callback',\n token: 'emulated-verification-token',\n team_id: opts.teamId,\n event: opts.event,\n event_id: `Ev${crypto.randomUUID().replaceAll('-', '').slice(0, 16).toUpperCase()}`,\n });\n // Timestamp is minted at fire time so the app's 5-minute window holds.\n const timestamp = String(Math.floor(Date.now() / 1000));\n const signingSecret = opts.env.signingSecret ?? '';\n return {\n method: 'POST',\n path: opts.targetPath,\n headers: {\n 'content-type': 'application/json',\n 'x-slack-request-timestamp': timestamp,\n 'x-slack-signature': signSlackRequest(signingSecret, timestamp, body),\n },\n body,\n };\n}\n\nfunction teamIdFrom(fixture: unknown, override?: string): string {\n if (override) return override;\n const parsed = slackFixtureSchema.safeParse(fixture);\n return parsed.success ? parsed.data.team.id : 'T_EMULATED';\n}\n\nfunction nowEventTs(): string {\n return `${Math.floor(Date.now() / 1000)}.000001`;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Inbound events\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst appMentionParamsSchema = z.object({\n channel: z.string(),\n user: z.string(),\n text: z.string(),\n ts: z.string().optional(),\n thread_ts: z.string().optional(),\n team_id: z.string().optional(),\n});\n\nconst messageParamsSchema = z.object({\n channel: z.string(),\n user: z.string(),\n text: z.string(),\n thread_ts: z.string().optional(),\n ts: z.string().optional(),\n channel_type: z.enum(['channel', 'group', 'im', 'mpim']).optional(),\n team_id: z.string().optional(),\n});\n\nconst reactionAddedParamsSchema = z.object({\n user: z.string(),\n reaction: z.string(),\n channel: z.string(),\n message_ts: z.string(),\n item_user: z.string().optional(),\n team_id: z.string().optional(),\n});\n\nconst inboundEvents: InboundEventDef[] = [\n {\n id: 'app-mention',\n description: 'A user @-mentions the app in a channel (signed app_mention event_callback)',\n paramsSchema: appMentionParamsSchema,\n build: ({ params, env, targetPath, fixture }) => {\n const p = appMentionParamsSchema.parse(params);\n return buildSignedEvent({\n env,\n targetPath,\n teamId: teamIdFrom(fixture, p.team_id),\n event: {\n type: 'app_mention',\n user: p.user,\n text: p.text,\n channel: p.channel,\n ts: p.ts ?? nowEventTs(),\n ...(p.thread_ts ? { thread_ts: p.thread_ts } : {}),\n },\n });\n },\n },\n {\n id: 'message',\n description: 'A user posts a (thread) message in a channel (signed message event_callback)',\n paramsSchema: messageParamsSchema,\n build: ({ params, env, targetPath, fixture }) => {\n const p = messageParamsSchema.parse(params);\n return buildSignedEvent({\n env,\n targetPath,\n teamId: teamIdFrom(fixture, p.team_id),\n event: {\n type: 'message',\n user: p.user,\n text: p.text,\n channel: p.channel,\n ts: p.ts ?? nowEventTs(),\n ...(p.thread_ts ? { thread_ts: p.thread_ts } : {}),\n ...(p.channel_type ? { channel_type: p.channel_type } : {}),\n },\n });\n },\n },\n {\n id: 'reaction-added',\n description: 'A user reacts to a message (signed reaction_added event_callback)',\n paramsSchema: reactionAddedParamsSchema,\n build: ({ params, env, targetPath, fixture }) => {\n const p = reactionAddedParamsSchema.parse(params);\n return buildSignedEvent({\n env,\n targetPath,\n teamId: teamIdFrom(fixture, p.team_id),\n event: {\n type: 'reaction_added',\n user: p.user,\n reaction: p.reaction,\n item: { type: 'message', channel: p.channel, ts: p.message_ts },\n ...(p.item_user ? { item_user: p.item_user } : {}),\n event_ts: nowEventTs(),\n },\n });\n },\n },\n];\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Action interfaces\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst actionInterfaces: ActionInterfaceDef[] = [\n {\n slug: 'slack-seed-data',\n label: 'Seed Slack data',\n description:\n 'Replace the emulated Slack workspace fixture (team, channels, users). Idempotent — re-running resets to exactly the given data.',\n inputSchema: {\n type: 'object',\n properties: {\n fixture: {\n type: 'string',\n description: 'JSON fixture: { team, botUserId, channels, users }',\n },\n },\n required: ['fixture'],\n },\n outputSchema: {\n type: 'object',\n properties: { ok: { type: 'boolean' } },\n },\n scaffoldScript: `# Replace the emulated Slack workspace data.\n# $INPUT_FIXTURE is the JSON fixture; the runner exports EMULATION_BASE_URL\n# and EMULATION_CONTROL_TOKEN automatically when emulation is enabled.\ncurl -sf -X POST \"$EMULATION_BASE_URL/plugins/slack/fixture\" \\\\\n -H \"Authorization: Bearer $EMULATION_CONTROL_TOKEN\" \\\\\n -H \"Content-Type: application/json\" \\\\\n -d \"{\\\\\"fixture\\\\\": $INPUT_FIXTURE}\"`,\n },\n {\n slug: 'slack-fire-event',\n label: 'Fire a Slack event into the app',\n description:\n \"Send a signed Slack webhook (app-mention | message | reaction-added) into the app's Slack events endpoint. Set the target path to YOUR app's webhook route.\",\n inputSchema: {\n type: 'object',\n properties: {\n event: {\n type: 'string',\n enum: ['app-mention', 'message', 'reaction-added'],\n description: 'Inbound event id',\n },\n params: { type: 'string', description: 'JSON params for the event (channel, user, text, …)' },\n },\n required: ['event', 'params'],\n },\n outputSchema: {\n type: 'object',\n properties: {\n ok: { type: 'boolean' },\n status: { type: 'number' },\n },\n },\n scaffoldScript: `# Fire a signed Slack event into the app.\n# EDIT the targetPath to your app's Slack webhook route before saving.\ncurl -sf -X POST \"$EMULATION_BASE_URL/fire\" \\\\\n -H \"Authorization: Bearer $EMULATION_CONTROL_TOKEN\" \\\\\n -H \"Content-Type: application/json\" \\\\\n -d \"{\\\\\"pluginId\\\\\": \\\\\"slack\\\\\", \\\\\"eventId\\\\\": \\\\\"$INPUT_EVENT\\\\\", \\\\\"params\\\\\": $INPUT_PARAMS, \\\\\"targetPath\\\\\": \\\\\"/integrations/slack/events\\\\\"}\"`,\n },\n {\n slug: 'slack-recorded-messages',\n label: 'Read messages the app posted to Slack',\n description:\n 'Return the messages the app sent via chat.postMessage since boot (or the last seed/reset) for assertions.',\n inputSchema: { type: 'object', properties: {} },\n outputSchema: {\n type: 'object',\n properties: {\n messages: { type: 'array', description: 'Posted messages: { channel, text, ts, thread_ts?, user }' },\n },\n },\n scaffoldScript: `# Read messages the app posted to the emulated Slack.\ncurl -sf \"$EMULATION_BASE_URL/plugins/slack/posted-messages\" \\\\\n -H \"Authorization: Bearer $EMULATION_CONTROL_TOKEN\"`,\n },\n];\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Plugin\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const slackPlugin: EmulationPlugin<SlackEmuConfig, SlackFixture, SlackState> = {\n id: 'slack',\n name: 'Slack API',\n version: '1.0.0',\n\n domains: ['slack.com'],\n needsBrowserIntercept: true,\n\n fixtureSchema: slackFixtureSchema,\n\n envContract: [\n {\n logicalKey: 'signingSecret',\n strategy: 'random-hex',\n bytes: 32,\n sensitive: true,\n description: \"Signs inbound webhooks — map to your app's Slack signing-secret env var\",\n },\n {\n logicalKey: 'botToken',\n strategy: 'random-hex',\n bytes: 16,\n prefix: 'xoxb-emulated-',\n sensitive: true,\n description: 'Bot token the emulator accepts — issued by oauth.v2.access, or map it directly',\n },\n {\n logicalKey: 'clientId',\n strategy: 'static',\n staticValue: '1234567890.0987654321',\n description: \"OAuth client id — map to your app's Slack client-id env var\",\n },\n {\n logicalKey: 'clientSecret',\n strategy: 'static',\n staticValue: 'emulated-client-secret',\n sensitive: true,\n description: \"OAuth client secret — map to your app's Slack client-secret env var\",\n },\n ],\n\n inboundEvents,\n actionInterfaces,\n\n controlReads: [\n {\n path: 'posted-messages',\n handler: (_req, ctx: SlackCtx) => ({\n status: 200,\n body: { messages: ctx.state.postedMessages },\n }),\n },\n {\n path: 'channels',\n handler: (_req, ctx: SlackCtx) => ({\n status: 200,\n body: { channels: Array.from(ctx.state.channels.values()) },\n }),\n },\n ],\n\n // ── Sandbox-side routes ──────────────────────────────────────────────────\n\n routes: [\n { method: 'POST', path: '/api/oauth.v2.access', handler: handleOAuthAccess },\n { method: 'POST', path: '/api/auth.test', handler: handleAuthTest },\n { method: 'GET', path: '/api/conversations.list', handler: handleConversationsList },\n { method: 'POST', path: '/api/conversations.list', handler: handleConversationsList },\n { method: 'POST', path: '/api/chat.postMessage', handler: handlePostMessage },\n { method: 'POST', path: '/api/conversations.join', handler: handleConversationsJoin },\n { method: 'GET', path: '/api/conversations.history', handler: handleConversationsHistory },\n { method: 'GET', path: '/api/conversations.replies', handler: handleConversationsReplies },\n { method: 'GET', path: '/api/users.info', handler: handleUsersInfo },\n { method: 'POST', path: '/api/users.info', handler: handleUsersInfo },\n { method: 'GET', path: '/api/team.info', handler: handleTeamInfo },\n { method: 'POST', path: '/api/team.info', handler: handleTeamInfo },\n // Best-effort Assistant status — emulate the missing-scope soft failure\n {\n method: 'POST',\n path: '/api/assistant.threads.setStatus',\n handler: (req, ctx: SlackCtx) => requireBot(req, ctx) ?? slackError('missing_scope'),\n },\n // File uploads are not emulated — fail closed so nothing leaks to real Slack\n {\n method: 'GET',\n path: '/api/files.getUploadURLExternal',\n handler: (req, ctx: SlackCtx) => requireBot(req, ctx) ?? slackError('not_emulated'),\n },\n {\n method: 'POST',\n path: '/api/files.completeUploadExternal',\n handler: (req, ctx: SlackCtx) => requireBot(req, ctx) ?? slackError('not_emulated'),\n },\n ],\n\n // ── Browser-side routes ──────────────────────────────────────────────────\n\n getBrowserRoutes(_fixture) {\n return [\n {\n urlPattern: '**/slack.com/oauth/v2/authorize**',\n handler: async (route, _fix) => {\n const url = new URL(route.request().url());\n const redirectUri = url.searchParams.get('redirect_uri');\n const state = url.searchParams.get('state') || '';\n\n if (!redirectUri) {\n await route.continue();\n return;\n }\n\n const callbackUrl = new URL(redirectUri);\n callbackUrl.searchParams.set('code', `${EMULATED_CODE_PREFIX}${crypto.randomUUID()}`);\n if (state) callbackUrl.searchParams.set('state', state);\n\n await route.fulfill({\n status: 302,\n headers: { location: callbackUrl.toString() },\n body: '',\n });\n },\n },\n ];\n },\n\n // ── Initialization ───────────────────────────────────────────────────────\n\n initialize(config, fixture, env) {\n return {\n team: fixture.team,\n botUserId: fixture.botUserId,\n appId: config.appId ?? DEFAULT_APP_ID,\n channels: new Map(fixture.channels.map((c) => [c.id, c])),\n users: new Map(fixture.users.map((u) => [u.id, u])),\n postedMessages: [],\n botToken: env?.botToken ?? 'xoxb-emulated-fallback',\n tsCounter: 0,\n };\n },\n\n defaultFixture: {\n team: { id: 'T_EMULATED', name: 'Emulated Workspace', domain: 'emulated' },\n botUserId: 'U_BOT',\n channels: [{ id: 'C_GENERAL', name: 'general', is_private: false, is_member: false, is_archived: false }],\n users: [\n { id: 'U_BOT', name: 'canary-bot', real_name: 'Canary Bot', is_bot: true },\n { id: 'U_HUMAN', name: 'testuser', real_name: 'Test User', email: 'testuser@example.com', is_bot: false },\n ],\n },\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Route Handlers\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction handleOAuthAccess(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const params = new URLSearchParams(req.body ?? '');\n const code = params.get('code') ?? '';\n const clientId = params.get('client_id') ?? '';\n const clientSecret = params.get('client_secret') ?? '';\n\n if (ctx.env.clientId && clientId !== ctx.env.clientId) return slackError('invalid_client_id');\n if (ctx.env.clientSecret && clientSecret !== ctx.env.clientSecret) return slackError('bad_client_secret');\n if (!code.startsWith(EMULATED_CODE_PREFIX)) {\n ctx.log('warn', `OAuth exchange with non-emulated code: ${code}`);\n return slackError('invalid_code');\n }\n\n const firstHuman = Array.from(ctx.state.users.values()).find((u) => !u.is_bot);\n ctx.log('info', `Issued bot token for team ${ctx.state.team.id}`);\n\n return {\n status: 200,\n body: {\n ok: true,\n access_token: ctx.state.botToken,\n token_type: 'bot',\n scope: EMULATED_BOT_SCOPES,\n bot_user_id: ctx.state.botUserId,\n app_id: ctx.state.appId,\n team: { id: ctx.state.team.id, name: ctx.state.team.name },\n authed_user: { id: firstHuman?.id ?? 'U_HUMAN' },\n },\n };\n}\n\nfunction handleAuthTest(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const denied = requireBot(req, ctx);\n if (denied) return denied;\n\n return {\n status: 200,\n body: {\n ok: true,\n url: `https://${ctx.state.team.domain ?? 'emulated'}.slack.com/`,\n team: ctx.state.team.name,\n user: 'canary-bot',\n team_id: ctx.state.team.id,\n user_id: ctx.state.botUserId,\n bot_id: 'B_EMULATED',\n },\n };\n}\n\nfunction handleConversationsList(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const denied = requireBot(req, ctx);\n if (denied) return denied;\n\n const excludeArchived = req.url.searchParams.get('exclude_archived') === 'true';\n const channels = Array.from(ctx.state.channels.values()).filter(\n (c) => !excludeArchived || !c.is_archived\n );\n\n return {\n status: 200,\n body: {\n ok: true,\n channels: channels.map((c) => ({\n id: c.id,\n name: c.name,\n is_channel: true,\n is_private: c.is_private ?? false,\n is_member: c.is_member ?? false,\n is_archived: c.is_archived ?? false,\n })),\n response_metadata: { next_cursor: '' },\n },\n };\n}\n\nfunction handlePostMessage(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const denied = requireBot(req, ctx);\n if (denied) return denied;\n\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return parsed.error;\n const { channel, text } = parsed.data;\n if (!channel) return slackError('channel_not_found');\n\n const ts = mintTs(ctx.state);\n const message: PostedMessage = {\n channel: String(channel),\n text: String(text ?? ''),\n ts,\n user: ctx.state.botUserId,\n ...(parsed.data.thread_ts ? { thread_ts: String(parsed.data.thread_ts) } : {}),\n ...(parsed.data.blocks ? { blocks: parsed.data.blocks } : {}),\n ...(parsed.data.attachments ? { attachments: parsed.data.attachments } : {}),\n };\n ctx.state.postedMessages.push(message);\n ctx.log('info', `chat.postMessage → ${message.channel}: ${message.text.slice(0, 80)}`);\n\n return {\n status: 200,\n body: {\n ok: true,\n channel: message.channel,\n ts,\n message: { type: 'message', text: message.text, user: ctx.state.botUserId, ts },\n },\n };\n}\n\nfunction handleConversationsJoin(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const denied = requireBot(req, ctx);\n if (denied) return denied;\n\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return parsed.error;\n const channelId = String(parsed.data.channel ?? '');\n const channel = ctx.state.channels.get(channelId);\n if (!channel) return slackError('channel_not_found');\n\n channel.is_member = true;\n return {\n status: 200,\n body: { ok: true, channel: { id: channel.id, name: channel.name, is_member: true } },\n };\n}\n\n/** Serve message lookups from postedMessages (parents only). */\nfunction handleConversationsHistory(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const denied = requireBot(req, ctx);\n if (denied) return denied;\n\n const channel = req.url.searchParams.get('channel') ?? '';\n const latest = req.url.searchParams.get('latest');\n let messages = ctx.state.postedMessages.filter((m) => m.channel === channel && !m.thread_ts);\n if (latest) messages = messages.filter((m) => m.ts === latest);\n\n return {\n status: 200,\n body: {\n ok: true,\n messages: messages.map((m) => ({ type: 'message', user: m.user, text: m.text, ts: m.ts })),\n has_more: false,\n },\n };\n}\n\nfunction handleConversationsReplies(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const denied = requireBot(req, ctx);\n if (denied) return denied;\n\n const channel = req.url.searchParams.get('channel') ?? '';\n const ts = req.url.searchParams.get('ts') ?? '';\n const thread = ctx.state.postedMessages.filter(\n (m) => m.channel === channel && (m.ts === ts || m.thread_ts === ts)\n );\n\n return {\n status: 200,\n body: {\n ok: true,\n messages: thread.map((m) => ({\n type: 'message',\n user: m.user,\n text: m.text,\n ts: m.ts,\n // Everything here was posted by the app, so mirror real Slack and\n // mark it as a bot message — the addressing resolver relies on that\n // to classify alert cards it did not author conversationally.\n bot_id: 'B_EMULATED',\n ...(m.thread_ts ? { thread_ts: m.thread_ts } : {}),\n })),\n has_more: false,\n },\n };\n}\n\nfunction handleUsersInfo(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const denied = requireBot(req, ctx);\n if (denied) return denied;\n\n const userId = readParam(req, 'user') ?? '';\n const user = ctx.state.users.get(userId);\n if (!user) return slackError('user_not_found');\n\n return {\n status: 200,\n body: {\n ok: true,\n user: {\n id: user.id,\n name: user.name,\n real_name: user.real_name ?? user.name,\n is_bot: user.is_bot ?? false,\n deleted: false,\n profile: {\n display_name: user.name,\n real_name: user.real_name ?? user.name,\n ...(user.email ? { email: user.email } : {}),\n },\n },\n },\n };\n}\n\nfunction handleTeamInfo(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const denied = requireBot(req, ctx);\n if (denied) return denied;\n\n return {\n status: 200,\n body: {\n ok: true,\n team: {\n id: ctx.state.team.id,\n name: ctx.state.team.name,\n domain: ctx.state.team.domain ?? 'emulated',\n },\n },\n };\n}\n","/**\n * Emulation Plugin Registry\n *\n * Central registry of all available emulation plugins. Add new plugins here\n * to make them available for sandbox configuration.\n *\n * @module\n */\n\nimport type { EmulationPlugin } from '../plugin.js';\nimport { awsPlugin } from './aws/index.js';\nimport { emailPlugin } from './email.js';\nimport { googleOAuthPlugin } from './google-oauth.js';\nimport { esriPlugin } from './esri/index.js';\nimport { jiraPlugin } from './jira.js';\nimport { maximoStubPlugin } from './maximo-stub.js';\nimport { oidcPlugin } from './oidc.js';\nimport { slackPlugin } from './slack.js';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- type-erased registry for heterogeneous plugins\ntype AnyPlugin = EmulationPlugin<any, any, any>;\n\n/** All registered emulation plugins, keyed by ID. */\nconst pluginRegistry = new Map<string, AnyPlugin>([\n [awsPlugin.id, awsPlugin],\n [emailPlugin.id, emailPlugin],\n [esriPlugin.id, esriPlugin],\n [googleOAuthPlugin.id, googleOAuthPlugin],\n [jiraPlugin.id, jiraPlugin],\n [maximoStubPlugin.id, maximoStubPlugin],\n [oidcPlugin.id, oidcPlugin],\n [slackPlugin.id, slackPlugin],\n]);\n\n/** Look up a plugin by ID. Returns undefined if not found. */\nexport function getPlugin(pluginId: string): AnyPlugin | undefined {\n return pluginRegistry.get(pluginId);\n}\n\n/** Get all registered plugin IDs. */\nexport function getPluginIds(): string[] {\n return Array.from(pluginRegistry.keys());\n}\n\n/** Get all registered plugins. */\nexport function getAllPlugins(): AnyPlugin[] {\n return Array.from(pluginRegistry.values());\n}\n\n/** Register a new plugin at runtime (for custom/third-party plugins). */\nexport function registerPlugin(plugin: AnyPlugin): void {\n pluginRegistry.set(plugin.id, plugin);\n}\n\nexport { emailPlugin, emailFixtureSchema } from './email.js';\nexport type { CapturedEmail, EmailEmuConfig, EmailFixture, EmailState, EmailProvider } from './email.js';\nexport { googleOAuthPlugin } from './google-oauth.js';\nexport { oidcFixture } from './oidc-core.js';\nexport { oidcPlugin } from './oidc.js';\nexport { esriPlugin } from './esri/index.js';\nexport type { EsriConfig, EsriFixture, EsriState } from './esri/index.js';\nexport { jiraPlugin } from './jira.js';\nexport { maximoStubPlugin } from './maximo-stub.js';\nexport { slackPlugin, slackFixtureSchema } from './slack.js';\nexport type { SlackFixture, SlackState, PostedMessage } from './slack.js';\n","/**\n * Operation Catalog\n *\n * Pure helpers over the plugin registry's `operations` declarations, so\n * consumers outside the emulator sidecar (Cofactor actions, tests) can list\n * and validate typed operations without reaching into plugin internals.\n *\n * @module\n */\n\nimport { z } from 'zod';\nimport { getPlugin } from './plugins/index.js';\nimport type { EmulationOperationDef } from './plugin.js';\n\n/** The JSON-Schema subset the validator and UI read from an operation's input. */\nexport interface OperationInputSchema {\n properties?: Record<string, { type?: string; description?: string; default?: unknown; enum?: unknown[] }>;\n required?: string[];\n}\n\nexport interface OperationCatalogEntry {\n id: string;\n description: string;\n inputSchema: OperationInputSchema;\n outputSchema: Record<string, unknown>;\n}\n\n/** List a plugin's operations as a JSON-Schema catalog. Empty array if the plugin is unknown or has none. */\nexport function pluginOperations(pluginId: string): OperationCatalogEntry[] {\n const plugin = getPlugin(pluginId);\n if (!plugin) return [];\n return (plugin.operations ?? []).map((op) => ({\n id: op.id,\n description: op.description,\n inputSchema: z.toJSONSchema(op.input) as OperationInputSchema,\n outputSchema: z.toJSONSchema(op.output) as Record<string, unknown>,\n }));\n}\n\n/** A single operation's schemas, for validating input before invoking it. */\nexport function findOperation(\n pluginId: string,\n opId: string\n): Pick<EmulationOperationDef, 'id' | 'description' | 'input' | 'output'> | undefined {\n const op = getPlugin(pluginId)?.operations?.find((candidate) => candidate.id === opId);\n return op && { id: op.id, description: op.description, input: op.input, output: op.output };\n}\n\n/** Split an operation slug (`<plugin>.<op>`) at its first dot; null when it is not one. */\nexport function parseOperationRef(slug: string): { pluginId: string; operationId: string } | null {\n const dot = slug.indexOf('.');\n if (dot <= 0 || dot === slug.length - 1) return null;\n return { pluginId: slug.slice(0, dot), operationId: slug.slice(dot + 1) };\n}\n","/**\n * Emulation Env Contract\n *\n * Plugins declare logical values (signing secrets, client IDs, bot tokens)\n * that must be shared between the emulation sidecar and the sandboxed app.\n * At provision time the contract is resolved into concrete values: random\n * secrets are minted per-provision (never persisted to the template), static\n * values come from the plugin, and `from-config` values come from the\n * template's plugin config.\n *\n * The resolved map is injected into the sidecar (via EMULATION_CONFIG_B64,\n * exposed to handlers as `PluginContext.env`) and — through the template's\n * `envMapping` — into the sandboxed app's environment, so both sides hold\n * byte-identical values.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type EnvStrategy = 'random-hex' | 'random-uuid' | 'static' | 'from-config';\n\n/** One logical value a plugin produces or consumes. */\nexport interface EnvContractEntry {\n /** Logical name (e.g., 'signingSecret') — mapped to app env vars via the template's envMapping */\n logicalKey: string;\n strategy: EnvStrategy;\n /** Number of random bytes for 'random-hex' (default 32) */\n bytes?: number;\n /** Literal prefix prepended to generated values (e.g., 'xoxb-emulated-') */\n prefix?: string;\n /** Literal value for 'static' */\n staticValue?: string;\n /** Plugin-config key to read for 'from-config' */\n configKey?: string;\n /** Marks secrets that must never be echoed back through read APIs */\n sensitive?: boolean;\n description?: string;\n}\n\n/** Randomness source — injectable so tests are deterministic. */\nexport interface RngAdapter {\n randomHex(bytes: number): string;\n randomUuid(): string;\n}\n\nexport const defaultRng: RngAdapter = {\n randomHex: (bytes) => crypto.randomBytes(bytes).toString('hex'),\n randomUuid: () => crypto.randomUUID(),\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Resolution\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Resolve an env contract into concrete values.\n * Pure given the injected rng. Throws on an unsatisfiable entry\n * (missing staticValue / configKey / config value).\n */\nexport function resolveEnvContract(\n contract: EnvContractEntry[],\n config: Record<string, unknown>,\n rng: RngAdapter = defaultRng\n): Record<string, string> {\n const resolved: Record<string, string> = {};\n\n for (const entry of contract) {\n const prefix = entry.prefix ?? '';\n switch (entry.strategy) {\n case 'random-hex':\n resolved[entry.logicalKey] = prefix + rng.randomHex(entry.bytes ?? 32);\n break;\n case 'random-uuid':\n resolved[entry.logicalKey] = prefix + rng.randomUuid();\n break;\n case 'static':\n if (entry.staticValue === undefined) {\n throw new Error(`Env contract '${entry.logicalKey}': strategy 'static' requires staticValue`);\n }\n resolved[entry.logicalKey] = entry.staticValue;\n break;\n case 'from-config': {\n if (!entry.configKey) {\n throw new Error(`Env contract '${entry.logicalKey}': strategy 'from-config' requires configKey`);\n }\n const value = config[entry.configKey];\n if (value === undefined || value === null || value === '') {\n throw new Error(\n `Env contract '${entry.logicalKey}': plugin config is missing '${entry.configKey}'`\n );\n }\n resolved[entry.logicalKey] = String(value);\n break;\n }\n }\n }\n\n return resolved;\n}\n","/** Google authorization interception, including an app's initial HTTP redirect. */\nimport type { BrowserRouteHandle } from './plugin.js';\n\nconst PROVIDER_URL_PATTERN = '**/accounts.google.com/o/oauth2/**';\n\nexport type GoogleOAuthBrowserConfig = {\n applicationOrigins: string[];\n urlContext: { sourceOrigin: string; targetOrigin: string } | null;\n /** The emulator control plane and the key scoped to its authorize read (never the raw control token). */\n control: { baseUrl: string; authorizeKey: string };\n};\n\ntype RouteResponse = {\n status: number;\n headers: Record<string, string>;\n body: Uint8Array;\n};\n\ninterface GoogleOAuthRouteHandle extends Omit<BrowserRouteHandle, 'fulfill'> {\n fulfill(response: {\n status?: number;\n headers?: Record<string, string>;\n body?: string | Uint8Array;\n }): Promise<void>;\n isMainFrameNavigation(): boolean;\n fallback?(): Promise<void>;\n /** Fetch this request once, preserving browser cookies, without following redirects. */\n fetchResponse(): Promise<RouteResponse>;\n}\n\nconst ENTITY_HEADERS = new Set(['content-length', 'content-encoding', 'transfer-encoding', 'content-type', 'location']);\n\n/** The app's response headers minus those describing its own body or redirect (keeps `set-cookie` etc.). */\nfunction withoutEntityHeaders(headers: Record<string, string>): Record<string, string> {\n return Object.fromEntries(Object.entries(headers).filter(([name]) => !ENTITY_HEADERS.has(name.toLowerCase())));\n}\n\nconst FAILURE_PREFIX = 'Cofactor sandbox emulator: Google authorize failed:';\n\nexport function googleOAuthBrowserRoutes(config: GoogleOAuthBrowserConfig) {\n const origins = new Set(config.applicationOrigins.map((value) => new URL(value).origin));\n\n /** Swap the app's source origin for the copy's; any other URL is returned unchanged. */\n const toCopyOrigin = (value: string): string => {\n const url = new URL(value);\n if (!config.urlContext || url.origin !== config.urlContext.sourceOrigin) return url.href;\n return new URL(config.urlContext.targetOrigin + url.href.slice(url.origin.length)).href;\n };\n\n /** Ask the emulator's authorize read about `authorizeUrl` and fulfill the route with its answer. */\n const authorize = async (\n route: GoogleOAuthRouteHandle,\n authorizeUrl: string,\n headers: Record<string, string>\n ) => {\n const carried = withoutEntityHeaders(headers);\n const failed = (reason: string) =>\n route.fulfill({\n status: 502,\n headers: { 'content-type': 'text/plain; charset=utf-8' },\n body: `${FAILURE_PREFIX} ${reason}`,\n });\n\n let response: Response;\n try {\n response = await fetch(`${config.control.baseUrl}/plugins/google-oauth/authorize${new URL(authorizeUrl).search}`, {\n headers: { authorization: `Bearer ${config.control.authorizeKey}` },\n redirect: 'manual',\n signal: AbortSignal.timeout(15_000),\n });\n } catch (error) {\n await failed(`${config.control.baseUrl} unreachable (${error instanceof Error ? error.message : String(error)})`);\n return;\n }\n\n if (response.status === 302) {\n const location = response.headers.get('location');\n if (!location) {\n await failed('the emulator redirect has no Location');\n return;\n }\n const callback = new URL(toCopyOrigin(location));\n if (!origins.has(callback.origin)) {\n await route.fulfill({\n status: 400,\n body: 'OAuth callback must belong to this sandbox copy',\n });\n return;\n }\n await route.fulfill({ status: 302, headers: { ...carried, location: callback.href }, body: '' });\n return;\n }\n\n if (response.status !== 200 && response.status !== 400) {\n await failed(`HTTP ${response.status} from the emulator control plane (is the copy on a platform version with the Google authorize endpoint?)`);\n return;\n }\n // The fetch's AbortSignal timeout also covers the body read; a stall there would otherwise leave the route unfulfilled.\n let body: string;\n try {\n body = await response.text();\n } catch (error) {\n await failed(`reading the emulator answer from ${config.control.baseUrl} (${error instanceof Error ? error.message : String(error)})`);\n return;\n }\n await route.fulfill({\n status: response.status,\n headers: { ...carried, 'content-type': response.headers.get('content-type') ?? 'text/plain' },\n body,\n });\n };\n\n return [\n {\n urlPattern: PROVIDER_URL_PATTERN,\n handler: (route: GoogleOAuthRouteHandle) => authorize(route, route.request().url(), {}),\n },\n ...[...origins].map((origin) => ({\n urlPattern: `${origin}/**`,\n handler: async (route: GoogleOAuthRouteHandle) => {\n if (!route.isMainFrameNavigation() || route.request().method() !== 'GET') {\n if (!route.fallback)\n throw new Error('Browser client cannot preserve context route owners');\n await route.fallback();\n return;\n }\n // Playwright only routes the first URL of a redirect chain. Inspect the\n // app response before the browser follows its Google authorization URL.\n const response = await route.fetchResponse();\n const location = response.headers.location;\n if (response.status >= 300 && response.status < 400 && location) {\n const redirect = new URL(location, route.request().url());\n if (\n redirect.hostname === 'accounts.google.com' &&\n redirect.pathname.startsWith('/o/oauth2/')\n ) {\n await authorize(route, redirect.href, response.headers);\n return;\n }\n }\n await route.fulfill(response);\n },\n })),\n ];\n}\n","/** Browser-side sign-in gate for a native v2 sandbox copy's OIDC emulator: carries the gate value on `/authorize`. */\n\nexport type OidcGateBrowserConfig = {\n /** The emulator's origin (the copy's `emulation` port URL). */\n origin: string;\n /** `gateCookieValue(controlToken)`, sent as a bearer. */\n gateValue: string;\n};\n\n/** Distinct from Google's `emulation` group so both can be armed on one context. */\nexport const OIDC_GATE_ROUTE_KEY = 'emulation-oidc-gate';\n\ninterface OidcGateRouteHandle {\n continue(): Promise<void>;\n request(): { url(): string; headers(): Record<string, string> };\n fallback?(): Promise<void>;\n /** Fetch once without following redirects; `headers` replace the request headers. */\n fetchResponse(opts?: {\n headers?: Record<string, string>;\n }): Promise<{ status: number; headers: Record<string, string>; body: Uint8Array }>;\n fulfill(response: { status?: number; headers?: Record<string, string>; body?: Uint8Array }): Promise<void>;\n}\n\n/**\n * One route on `${origin}/authorize**`: `/authorize` is fetched once with\n * `authorization: Bearer <gateValue>` added and the response fulfilled as-is.\n * Not `continue({ headers })`: Playwright carries overridden headers across\n * redirects, which would leak the bearer to the app's callback. A fulfilled 302\n * is followed by the browser itself, without the header. Anything else goes to\n * the next route owner.\n */\nexport function oidcGateBrowserRoutes(config: OidcGateBrowserConfig) {\n const origin = new URL(config.origin).origin;\n return [\n {\n urlPattern: `${origin}/authorize**`,\n handler: async (route: OidcGateRouteHandle) => {\n const url = new URL(route.request().url());\n if (url.origin === origin && url.pathname === '/authorize') {\n const response = await route.fetchResponse({\n headers: { ...route.request().headers(), authorization: `Bearer ${config.gateValue}` },\n });\n await route.fulfill(response);\n return;\n }\n if (route.fallback) await route.fallback();\n else await route.continue();\n },\n },\n ];\n}\n"],"mappings":"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","names":["z","message","maxResults","text","message","withDecryption","invalid","operation","crypto","existsSync","readFileSync","crypto","existsSync","readFileSync","crypto","validation","message","OPERATIONS","operation","notFound","message","OPERATIONS","operation","z","z","crypto","crypto","headers","text","captured","crypto","server","text","page","value","z","z","crypto","z","crypto","z","z","crypto","crypto","message","crypto","z","text","text","l","r","negate","z","crypto","crypto","z","z","z","z","crypto","page","crypto","crypto","z","safeParseJson","text","notFound","z","configSchema","z","message","flag","attr","want","compareValues","sweep","page","key","headers","message","headers","crypto","z","safeParseJson","text","message","z","z","crypto","headers","authorize"]}
|
|
1
|
+
{"version":3,"sources":["../../emulation/src/plugins/aws/index.ts","../../emulation/src/plugins/aws/config.ts","../../emulation/src/plugins/aws/protocol.ts","../../emulation/src/plugins/aws/ssm.ts","../../emulation/src/plugins/aws/kms.ts","../../emulation/src/service/tls.ts","../../emulation/src/plugins/aws/secrets-manager.ts","../../emulation/src/plugins/email.ts","../../emulation/src/plugins/email/actions.ts","../../emulation/src/plugins/email/handlers.ts","../../emulation/src/plugins/email/capture.ts","../../emulation/src/plugins/email/parsing.ts","../../emulation/src/plugins/email/mailosaur.ts","../../emulation/src/plugins/email/types.ts","../../emulation/src/plugins/oidc-core.ts","../../emulation/src/plugins/jwt.ts","../../emulation/src/persona-identity.ts","../../emulation/src/plugins/google-oauth.ts","../../emulation/src/plugins/esri/index.ts","../../emulation/src/token-match.ts","../../emulation/src/plugins/esri/errors.ts","../../emulation/src/plugins/esri/layers.ts","../../emulation/src/credential-keys.ts","../../emulation/src/redact-json.ts","../../emulation/src/plugins/esri/where.ts","../../emulation/src/plugins/esri/params.ts","../../emulation/src/plugins/esri/operations.ts","../../emulation/src/plugin.ts","../../emulation/src/plugins/esri/tenants.ts","../../emulation/src/plugins/esri/query.ts","../../emulation/src/plugins/jira.ts","../../emulation/src/plugins/maximo-stub.ts","../../emulation/src/plugins/maximo-stub-data.ts","../../emulation/src/authorize-key.ts","../../emulation/src/sign-in-gate.ts","../../emulation/src/plugins/oidc.ts","../../emulation/src/plugins/slack.ts","../../emulation/src/plugins/index.ts","../../emulation/src/operations.ts","../../emulation/src/env-contract.ts","../../emulation/src/google-oauth-browser.ts","../../emulation/src/oidc-gate-browser.ts"],"sourcesContent":["/**\n * AWS Emulation Plugin\n *\n * Emulates AWS service APIs an app calls with its unmodified AWS SDK: the\n * sandbox resolves `<service>.<region>.amazonaws.com` to the emulator, which\n * serves it over TLS from the emulation CA, so no `AWS_ENDPOINT_URL_*` or code\n * change is needed. Only the services the config declares a section for are\n * intercepted, in each configured region (default `us-east-1`); the `email`\n * plugin keeps owning SES.\n *\n * Services: Secrets Manager (read-only, seeded by the definition) and KMS\n * (seeded Decrypt mappings plus Encrypt/Decrypt/GenerateDataKey under an\n * emulated key) and SSM Parameter Store (read-only, seeded by the definition).\n *\n * Seeded values may hold `${params.x}` and `${secrets.NAME}` references; the\n * sandbox resolves them before the emulator starts (see the sandbox helper's\n * `emulationConfigFor` in emulation-refs.ts), so this plugin only ever sees final values. No\n * value is logged, recorded or returned by an operation: the `secrets`\n * operation lists names, ARNs and version ids.\n *\n * @module\n */\n\nimport { z } from 'zod';\nimport type { EmulationPlugin } from '../../plugin.js';\nimport { awsConfigSchema, declaredServices, type AwsConfigInput } from './config.js';\nimport { serviceHost } from './protocol.js';\nimport { handleKms, initKms } from './kms.js';\nimport { handleSecretsManager, initSecretsManager, secretArn } from './secrets-manager.js';\nimport { handleSsm, initSsm, PARAMETER_TYPES, PARAMETER_VERSION, parameterArn } from './ssm.js';\nimport type { AwsCtx, AwsFixture, AwsState } from './types.js';\n\n/**\n * Each service's handler answers only its own host. It returns null for\n * another host, and also for its own host's calls it does not emulate; those\n * stay a 501, since every later handler also checks its own host first.\n */\nconst SERVICE_HANDLERS = [handleSecretsManager, handleKms, handleSsm];\n\nconst parameterSummary = z.object({\n name: z.string(),\n type: z.enum(PARAMETER_TYPES),\n version: z.number(),\n /** The parameter's ARN in each intercepted region. */\n arns: z.array(z.string()),\n /** How many times the app has read the parameter since boot. */\n reads: z.number(),\n});\n\nconst secretSummary = z.object({\n name: z.string(),\n versionId: z.string(),\n /** The secret's ARN in each intercepted region. */\n arns: z.array(z.string()),\n /** How many times the app has read the secret's value since boot. */\n reads: z.number(),\n});\n\nexport const awsPlugin: EmulationPlugin<AwsConfigInput, AwsFixture, AwsState> = {\n id: 'aws',\n name: 'AWS (Secrets Manager, KMS, SSM Parameter Store)',\n version: '1.0.0',\n\n configSchema: awsConfigSchema,\n configReferences: true,\n\n // Definition validation already checked the config; parsing again applies its defaults.\n domains: (input) => {\n const config = awsConfigSchema.parse(input);\n return declaredServices(config).flatMap((service) => config.regions.map((region) => serviceHost(service, region)));\n },\n\n needsBrowserIntercept: false,\n\n operations: [\n {\n id: 'secrets',\n description: 'The seeded Secrets Manager secrets: names, ARNs, version ids and read counts, never values.',\n input: z.object({}).strict(),\n output: z.object({ secrets: z.array(secretSummary) }),\n handler: (ctx: AwsCtx) => ({\n secrets: [...(ctx.state.secretsManager?.secrets.values() ?? [])].map((secret) => ({\n name: secret.name,\n versionId: secret.versionId,\n arns: ctx.state.regions.map((region) => secretArn(secret, region)),\n reads: secret.reads,\n })),\n }),\n },\n {\n id: 'parameters',\n description: 'The seeded SSM parameters: names, types, versions, ARNs and read counts, never values.',\n input: z.object({}).strict(),\n output: z.object({ parameters: z.array(parameterSummary) }),\n handler: (ctx: AwsCtx) => ({\n parameters: [...(ctx.state.ssm?.parameters.values() ?? [])].map((parameter) => ({\n name: parameter.name,\n type: parameter.type,\n version: PARAMETER_VERSION,\n arns: ctx.state.regions.map((region) => parameterArn(parameter, region)),\n reads: parameter.reads,\n })),\n }),\n },\n ],\n\n routes: [\n // Every AWS JSON 1.1 call is `POST /`; the host names the service and `X-Amz-Target` the operation.\n {\n method: 'POST',\n path: '/',\n handler: (req, ctx: AwsCtx) => {\n for (const handle of SERVICE_HANDLERS) {\n const response = handle(req, ctx);\n if (response) return response;\n }\n return null;\n },\n },\n ],\n\n initialize(input): AwsState {\n const config = awsConfigSchema.parse(input);\n return {\n regions: config.regions,\n createdDate: Math.floor(Date.now() / 1000),\n secretsManager: config.secrets_manager ? initSecretsManager(config.secrets_manager) : null,\n kms: config.kms ? initKms(config.kms) : null,\n ssm: config.ssm ? initSsm(config.ssm) : null,\n };\n },\n};\n","/**\n * The `aws` plugin's config: a definition's `emulation.aws` block. Each\n * declared service section is intercepted in every listed region; a service\n * without a section is not intercepted at all.\n *\n * @module\n */\n\nimport { z } from 'zod';\nimport { isBase64, REGION, type AwsService } from './protocol.js';\nimport { PARAMETER_TYPES } from './ssm.js';\n\n/** Secrets Manager's own secret-name alphabet (1–512 characters). */\nconst SECRET_NAME = /^[A-Za-z0-9/_+=.@-]{1,512}$/;\n\nconst secretsManagerSchema = z.strictObject({\n /** Secret name -> its value: a string is the SecretString as is; an object is served as its JSON. */\n secrets: z\n .record(z.string(), z.union([z.string(), z.record(z.string(), z.unknown())]))\n .superRefine((secrets, ctx) => {\n for (const name of Object.keys(secrets)) {\n if (!SECRET_NAME.test(name)) {\n ctx.addIssue({ code: 'custom', path: [name], message: 'a secret name is 1-512 letters, digits and /_+=.@-' });\n }\n }\n }),\n});\n\n/**\n * Standard padded base64, or a value holding a reference: the sandbox checks\n * the config again once references are resolved, so that one must be base64 too.\n */\nconst base64OrReference = z.string().refine((value) => isBase64(value) || value.includes('${'), { message: 'must be base64' });\n\nconst kmsSchema = z.strictObject({\n /** Ciphertext made by real KMS -> its plaintext, both base64: the only way such ciphertext decrypts in a sandbox. */\n decrypt: z\n .array(\n z.strictObject({\n ciphertext: base64OrReference,\n plaintext: base64OrReference,\n /** The key real KMS encrypted it under (id, ARN or alias); Decrypt answers with it. */\n key_id: z\n .string()\n .regex(/^(?:alias\\/[\\w/.-]+|[\\w-]+|arn:[a-z-]+:kms:[a-z0-9-]+:\\d{12}:(?:key\\/[\\w-]+|alias\\/[\\w/.-]+))$/, {\n message: 'must be a key id, key ARN, alias name or alias ARN',\n })\n .optional(),\n })\n )\n .default([]),\n});\n\n/** Parameter Store's name alphabet: a plain name or a `/`-separated path. */\nconst PARAMETER_NAME = /^[A-Za-z0-9_.\\-/]{1,2048}$/;\n\nconst ssmSchema = z.strictObject({\n /** Parameter name -> its value and type (String unless given). */\n parameters: z\n .record(\n z.string(),\n z.strictObject({\n value: z.string(),\n type: z.enum(PARAMETER_TYPES).default('String'),\n })\n )\n .superRefine((parameters, ctx) => {\n for (const name of Object.keys(parameters)) {\n if (!PARAMETER_NAME.test(name)) {\n ctx.addIssue({ code: 'custom', path: [name], message: 'a parameter name is 1-2048 letters, digits and _.-/' });\n }\n }\n }),\n});\n\nexport const awsConfigSchema = z\n .strictObject({\n /** Regions whose service endpoints are intercepted. */\n regions: z\n .array(z.string().regex(REGION, 'must be an AWS region such as us-east-1 (China regions are not emulated)'))\n .min(1)\n .default(['us-east-1']),\n secrets_manager: secretsManagerSchema.optional(),\n kms: kmsSchema.optional(),\n ssm: ssmSchema.optional(),\n })\n .refine((config) => declaredServices(config).length > 0, {\n message: 'declare at least one service: secrets_manager, kms, ssm',\n });\n\n/** The config as a definition writes it. */\nexport type AwsConfigInput = z.input<typeof awsConfigSchema>;\n/** The config with defaults applied. */\nexport type AwsConfig = z.output<typeof awsConfigSchema>;\n\n/** The services a config declares, in endpoint-prefix form. */\nexport function declaredServices(config: { secrets_manager?: unknown; kms?: unknown; ssm?: unknown }): AwsService[] {\n const sections: Array<[unknown, AwsService]> = [\n [config.secrets_manager, 'secretsmanager'],\n [config.kms, 'kms'],\n [config.ssm, 'ssm'],\n ];\n return sections.filter(([section]) => section !== undefined).map(([, service]) => service);\n}\n","/**\n * The AWS JSON 1.1 wire protocol shared by every service the `aws` plugin\n * emulates: which service and region a request is for (from its host), the\n * operation it calls (from `X-Amz-Target`), and AWS-shaped success and error\n * responses. Requests are never signature-checked: any credentials work.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport type { EmulationRequest, EmulationResponse } from '../../plugin.js';\n\n/** The account id in every emulated ARN (no real account has it). */\nexport const ACCOUNT_ID = '000000000000';\n\n/** The services the plugin can emulate, by their endpoint prefix (`<service>.<region>.amazonaws.com`). */\nexport type AwsService = 'secretsmanager' | 'kms' | 'ssm';\n\n/** A region name in the standard (`.amazonaws.com`) or GovCloud partitions; China's `.amazonaws.com.cn` hosts are not emulated. */\nexport const REGION = /^(?!cn-)[a-z]{2}(-[a-z]+)+-\\d+$/;\n\nconst HOST = /^([a-z0-9-]+)\\.([a-z0-9-]+)\\.amazonaws\\.com$/;\n\n/** The service endpoint host of `service` in `region`. */\nexport function serviceHost(service: AwsService, region: string): string {\n return `${service}.${region}.amazonaws.com`;\n}\n\nconst BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;\n\n/** Whether `value` is standard, padded base64 (the JSON protocols' blob encoding). */\nexport function isBase64(value: string): boolean {\n return BASE64.test(value);\n}\n\n/** The ARN partition of a region. */\nexport function partition(region: string): string {\n return region.startsWith('us-gov-') ? 'aws-us-gov' : 'aws';\n}\n\n/** The region of a request to `<service>.<region>.amazonaws.com`, or null for another host. */\nexport function requestRegion(req: EmulationRequest, service: AwsService): string | null {\n const match = HOST.exec(req.url.hostname.toLowerCase());\n return match && match[1] === service ? match[2]! : null;\n}\n\n/** The operation an `X-Amz-Target: <prefix>.<Operation>` header names, or null when it names another prefix. */\nexport function targetOperation(req: EmulationRequest, prefix: string): string | null {\n const target = req.headers['x-amz-target'] ?? '';\n return target.startsWith(`${prefix}.`) ? target.slice(prefix.length + 1) : null;\n}\n\nfunction headers(): Record<string, string> {\n return { 'content-type': 'application/x-amz-json-1.1', 'x-amzn-requestid': crypto.randomUUID() };\n}\n\n/**\n * A 200 JSON 1.1 response. Its content type keeps it out of the recorder's\n * response previews (JSON only), and `SecretString` is a credential key there\n * anyway, so a served value is never recorded.\n */\nexport function awsOk(body: object): EmulationResponse {\n return { status: 200, headers: headers(), body: JSON.stringify(body) };\n}\n\n/** A 400 AWS JSON 1.1 error: `__type` names the exception, as the SDKs expect; `messageKey` is the service's own casing. */\nexport function awsError(type: string, message: string, messageKey: 'Message' | 'message'): EmulationResponse {\n return {\n status: 400,\n headers: { ...headers(), 'x-amzn-errortype': type },\n body: JSON.stringify({ __type: type, [messageKey]: message }),\n };\n}\n\n/** The request's JSON object body, or null when it is not one. */\nexport function jsonBody(req: EmulationRequest): Record<string, unknown> | null {\n try {\n const parsed: unknown = JSON.parse(req.body ?? '{}');\n return typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed) ? (parsed as Record<string, unknown>) : null;\n } catch {\n return null;\n }\n}\n\n/** A stable hex digest of `parts`, for ids that must not change across copies of a sandbox. */\nexport function stableHex(...parts: string[]): string {\n return crypto.createHash('sha256').update(parts.join('\\0')).digest('hex');\n}\n\n/** A stable UUID-shaped id derived from `parts`. */\nexport function stableUuid(...parts: string[]): string {\n const hex = stableHex(...parts);\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;\n}\n\n/** A request's `MaxResults` within [1, max], defaulting to max; null when out of range. */\nexport function maxResults(raw: unknown, max: number): number | null {\n if (raw === undefined) return max;\n return typeof raw === 'number' && Number.isInteger(raw) && raw >= 1 && raw <= max ? raw : null;\n}\n\n/** One page of `items` from an opaque `NextToken`; null when the token is not one this emulator issued. */\nexport function paginate<T>(\n items: T[],\n maxResults: number,\n nextToken: unknown\n): { page: T[]; nextToken?: string } | null {\n let start = 0;\n if (nextToken !== undefined) {\n const text = typeof nextToken === 'string' ? Buffer.from(nextToken, 'base64url').toString('utf8') : '';\n const decoded = /^\\d+$/.test(text) ? Number(text) : NaN;\n if (!(decoded > 0 && decoded <= items.length)) return null;\n start = decoded;\n }\n const end = start + maxResults;\n return {\n page: items.slice(start, end),\n ...(end < items.length ? { nextToken: Buffer.from(String(end), 'utf8').toString('base64url') } : {}),\n };\n}\n","/**\n * AWS Systems Manager Parameter Store, read-only: the parameters a definition\n * seeds, served by `GetParameter`, `GetParameters`, `GetParametersByPath` and\n * `DescribeParameters` with the field names and types of the real API. Each\n * parameter has version 1. A SecureString's value is returned only with\n * `WithDecryption: true`; without it the value is an opaque base64 stand-in\n * for KMS ciphertext that never encodes the value. Writes (`PutParameter`,\n * ...), parameter filters on reads, the deprecated `Filters` of\n * DescribeParameters, and version or label selectors (`name:1`) are not\n * emulated: 501 in Sandboxes v2, rather than an approximate answer. A 501 is\n * recorded with its headers (`X-Amz-Target` names the operation) and no body.\n *\n * @module\n */\n\nimport type { EmulationRequest, EmulationResponse } from '../../plugin.js';\nimport type { AwsConfig } from './config.js';\nimport { ACCOUNT_ID, awsError, awsOk, jsonBody, maxResults, paginate, partition, requestRegion, stableHex, targetOperation } from './protocol.js';\nimport type { AwsCtx } from './types.js';\n\n/** The parameter types, shared with the config schema and the `parameters` operation. */\nexport const PARAMETER_TYPES = ['String', 'StringList', 'SecureString'] as const;\ntype ParameterType = (typeof PARAMETER_TYPES)[number];\n\n/** Every seeded parameter has one version. */\nexport const PARAMETER_VERSION = 1;\n\ninterface SeededParameter {\n name: string;\n type: ParameterType;\n value: string;\n /** How many times the app has read this parameter's value. */\n reads: number;\n}\n\nexport interface SsmState {\n /** By name, in the order the definition declares them. */\n parameters: Map<string, SeededParameter>;\n}\n\n/** The key SSM names for a SecureString encrypted with the account's default key. */\nconst DEFAULT_SECURE_KEY = 'alias/aws/ssm';\n\nexport function initSsm(section: NonNullable<AwsConfig['ssm']>): SsmState {\n const parameters = new Map<string, SeededParameter>();\n for (const [name, { value, type }] of Object.entries(section.parameters)) {\n parameters.set(name, { name, type, value, reads: 0 });\n }\n return { parameters };\n}\n\nexport function parameterArn(parameter: SeededParameter, region: string): string {\n const path = parameter.name.startsWith('/') ? parameter.name.slice(1) : parameter.name;\n return `arn:${partition(region)}:ssm:${region}:${ACCOUNT_ID}:parameter/${path}`;\n}\n\n/** A parameter by name or ARN, in `region`. */\nfunction findParameter(state: SsmState, region: string, id: string): SeededParameter | undefined {\n if (!id.startsWith('arn:')) return state.parameters.get(id);\n for (const parameter of state.parameters.values()) {\n if (parameterArn(parameter, region) === id) return parameter;\n }\n return undefined;\n}\n\nconst notFound = (name: string) => awsError('ParameterNotFound', `Parameter ${name} not found.`, 'message');\nconst validation = (message: string) => awsError('ValidationException', message, 'message');\n\n/** The `Parameter` shape GetParameter(s) and GetParametersByPath return. */\nfunction parameterValue(parameter: SeededParameter, region: string, withDecryption: boolean, createdDate: number) {\n parameter.reads += 1;\n const hidden = parameter.type === 'SecureString' && !withDecryption;\n return {\n Name: parameter.name,\n Type: parameter.type,\n Value: hidden ? Buffer.from(stableHex('ssm-securestring', parameter.name), 'hex').toString('base64') : parameter.value,\n Version: PARAMETER_VERSION,\n LastModifiedDate: createdDate,\n ARN: parameterArn(parameter, region),\n DataType: 'text',\n };\n}\n\nfunction withDecryption(body: Record<string, unknown>): boolean {\n return body.WithDecryption === true;\n}\n\nconst invalidToken = () => awsError('InvalidNextToken', 'The specified token is not valid.', 'message');\n\nfunction getParameter(state: SsmState, region: string, body: Record<string, unknown>, createdDate: number) {\n if (typeof body.Name !== 'string' || body.Name === '') return validation('Name is required.');\n const parameter = findParameter(state, region, body.Name);\n if (!parameter) return notFound(body.Name);\n return awsOk({ Parameter: parameterValue(parameter, region, withDecryption(body), createdDate) });\n}\n\nfunction getParameters(state: SsmState, region: string, body: Record<string, unknown>, createdDate: number) {\n const names = body.Names;\n if (!Array.isArray(names) || names.length === 0 || names.length > 10 || !names.every((name) => typeof name === 'string')) {\n return validation('Names must be a list of 1 to 10 parameter names.');\n }\n const parameters = [];\n const invalid = [];\n for (const name of names as string[]) {\n const parameter = findParameter(state, region, name);\n if (parameter) parameters.push(parameterValue(parameter, region, withDecryption(body), createdDate));\n else invalid.push(name);\n }\n return awsOk({ Parameters: parameters, InvalidParameters: invalid });\n}\n\n/** Whether `name` is under `path`: one level below it, or any depth when `recursive`. */\nfunction underPath(name: string, path: string, recursive: boolean): boolean {\n const prefix = path.endsWith('/') ? path : `${path}/`;\n if (!name.startsWith(prefix)) return false;\n return recursive || !name.slice(prefix.length).includes('/');\n}\n\nfunction getParametersByPath(state: SsmState, region: string, body: Record<string, unknown>, createdDate: number) {\n if (typeof body.Path !== 'string' || !body.Path.startsWith('/')) return validation('Path must begin with \"/\".');\n const max = maxResults(body.MaxResults, 10);\n if (max === null) return validation('MaxResults must be between 1 and 10.');\n const path = body.Path;\n const matching = [...state.parameters.values()].filter((parameter) => underPath(parameter.name, path, body.Recursive === true));\n const paged = paginate(matching, max, body.NextToken);\n if (!paged) return invalidToken();\n return awsOk({\n Parameters: paged.page.map((parameter) => parameterValue(parameter, region, withDecryption(body), createdDate)),\n ...(paged.nextToken ? { NextToken: paged.nextToken } : {}),\n });\n}\n\ntype StringFilter = { Key: string; Option?: string; Values?: string[] };\n\n/**\n * Whether a parameter passes `DescribeParameters`' `ParameterFilters`: `Name`\n * (Equals or BeginsWith), `Type` (Equals) and `Path` (OneLevel or Recursive).\n * Null when a filter uses anything else, so the call is reported unemulated\n * rather than answered wrongly.\n */\nfunction describeMatcher(body: Record<string, unknown>): ((parameter: SeededParameter) => boolean) | null {\n if (body.Filters !== undefined) return null;\n const checks: Array<(parameter: SeededParameter) => boolean> = [];\n const add = (filter: StringFilter): boolean => {\n const values = filter.Values ?? [];\n const option = filter.Option ?? (filter.Key === 'Path' ? 'OneLevel' : 'Equals');\n if (filter.Key === 'Name' && (option === 'Equals' || option === 'BeginsWith')) {\n checks.push((p) => values.some((value) => (option === 'Equals' ? p.name === value : p.name.startsWith(value))));\n } else if (filter.Key === 'Type' && option === 'Equals') {\n checks.push((p) => values.includes(p.type));\n } else if (filter.Key === 'Path' && (option === 'OneLevel' || option === 'Recursive')) {\n checks.push((p) => values.some((value) => underPath(p.name, value, option === 'Recursive')));\n } else return false;\n return true;\n };\n const raw = body.ParameterFilters ?? [];\n if (!Array.isArray(raw)) return null;\n for (const entry of raw) {\n if (typeof entry !== 'object' || entry === null) return null;\n const { Key, Option, Values } = entry as Record<string, unknown>;\n if (typeof Key !== 'string' || (Values !== undefined && !(Array.isArray(Values) && Values.every((v) => typeof v === 'string')))) return null;\n const filter: StringFilter = {\n Key,\n ...(typeof Option === 'string' ? { Option } : {}),\n ...(Values !== undefined ? { Values: Values as string[] } : {}),\n };\n if (!add(filter)) return null;\n }\n return (parameter) => checks.every((check) => check(parameter));\n}\n\nfunction describeParameters(state: SsmState, region: string, body: Record<string, unknown>, createdDate: number) {\n const matches = describeMatcher(body);\n if (!matches) return null;\n const max = maxResults(body.MaxResults, 50);\n if (max === null) return validation('MaxResults must be between 1 and 50.');\n const paged = paginate([...state.parameters.values()].filter(matches), max, body.NextToken);\n if (!paged) return invalidToken();\n return awsOk({\n Parameters: paged.page.map((parameter) => ({\n Name: parameter.name,\n ARN: parameterArn(parameter, region),\n Type: parameter.type,\n ...(parameter.type === 'SecureString' ? { KeyId: DEFAULT_SECURE_KEY } : {}),\n LastModifiedDate: createdDate,\n Version: PARAMETER_VERSION,\n Tier: 'Standard',\n Policies: [],\n DataType: 'text',\n })),\n ...(paged.nextToken ? { NextToken: paged.nextToken } : {}),\n });\n}\n\nconst OPERATIONS = {\n GetParameter: getParameter,\n GetParameters: getParameters,\n GetParametersByPath: getParametersByPath,\n DescribeParameters: describeParameters,\n} as const;\n\n/** `POST /` on an SSM endpoint. Null (not emulated) for another host, any other operation, or an unsupported filter. */\nexport function handleSsm(req: EmulationRequest, ctx: AwsCtx): EmulationResponse | null {\n const state = ctx.state.ssm;\n const region = requestRegion(req, 'ssm');\n const operation = targetOperation(req, 'AmazonSSM');\n if (!state || !region || !operation || !Object.hasOwn(OPERATIONS, operation)) return null;\n const body = jsonBody(req);\n if (!body) return awsError('SerializationException', 'The request body is not a JSON object.', 'message');\n // Filters on reads and `name:version` / `name:label` selectors are not emulated: 501, not a wrong answer.\n if (body.ParameterFilters !== undefined && operation !== 'DescribeParameters') return null;\n const names = [body.Name, ...(Array.isArray(body.Names) ? body.Names : [])];\n if (names.some((name) => typeof name === 'string' && !name.startsWith('arn:') && name.includes(':'))) return null;\n return OPERATIONS[operation as keyof typeof OPERATIONS](state, region, body, ctx.state.createdDate);\n}\n","/**\n * AWS KMS, minimal. `Decrypt` answers the ciphertext a definition seeds (made\n * by real KMS, which only a seeded mapping can answer), and `Encrypt`,\n * `Decrypt` and `GenerateDataKey` work under one emulated symmetric key, so an\n * app that encrypts at run time round-trips. Any other operation is not\n * emulated: 501 in Sandboxes v2.\n *\n * The emulated key is internal, never configured: derived (HKDF-SHA256) from\n * the emulation CA's private key, which the emulator creates at its first\n * start, before the ready snapshot is captured, and keeps root-only across\n * restarts. Every copy of a snapshot therefore has the same key and decrypts\n * what the snapshot's seeds or another copy encrypted. Any KeyId (key id, key\n * ARN, alias name or ARN) is accepted and answered as a key ARN.\n *\n * Emulated ciphertext is `cfkms1 | key ARN length (2 bytes) | key ARN | IV\n * (12) | tag (16) | AES-256-GCM ciphertext`, with the key ARN (length-prefixed)\n * and the encryption context as additional authenticated data, so decrypting\n * with a different context fails as on AWS (InvalidCiphertextException).\n * Seeded ciphertext was made by real KMS under a context the emulator cannot\n * check, so its Decrypt ignores EncryptionContext.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport { existsSync, readFileSync } from 'node:fs';\nimport type { EmulationRequest, EmulationResponse } from '../../plugin.js';\nimport { CA_KEY_FILE } from '../../service/tls.js';\nimport type { AwsConfig } from './config.js';\nimport { ACCOUNT_ID, awsError, awsOk, isBase64, jsonBody, partition, requestRegion, stableUuid, targetOperation } from './protocol.js';\nimport type { AwsCtx } from './types.js';\n\nconst MAGIC = Buffer.from('cfkms1', 'utf8');\nconst ALGORITHM = 'SYMMETRIC_DEFAULT';\nconst IV_BYTES = 12;\nconst TAG_BYTES = 16;\nconst MAX_PLAINTEXT_BYTES = 4096;\nconst MAX_DATA_KEY_BYTES = 1024;\n\ninterface SeededCiphertext {\n plaintext: Buffer;\n /** The key the seed names, as given; null when it names none. */\n keyId: string | null;\n}\n\nexport interface KmsState {\n /** Seeded ciphertext, as canonical base64 -> what it decrypts to. */\n seeded: Map<string, SeededCiphertext>;\n /** The emulated key, derived on first use (`masterKey`). */\n masterKey: Buffer | null;\n}\n\n/**\n * The state for a config's `kms` section. The config was parsed by the\n * plugin's schema with every reference resolved, so both blobs are base64.\n */\nexport function initKms(section: NonNullable<AwsConfig['kms']>): KmsState {\n const seeded = new Map<string, SeededCiphertext>();\n for (const entry of section.decrypt) {\n seeded.set(Buffer.from(entry.ciphertext, 'base64').toString('base64'), { plaintext: Buffer.from(entry.plaintext, 'base64'), keyId: entry.key_id ?? null });\n }\n return { seeded, masterKey: null };\n}\n\n/** The emulated key: HKDF of the CA's private key, so it lives exactly as long as the CA (see the module doc). */\nfunction deriveKey(): Buffer {\n // The emulator creates the CA before it serves anything; without one (a host that runs no CA) KMS cannot work.\n if (!existsSync(CA_KEY_FILE)) throw new Error(`KMS emulation needs the emulation CA key at ${CA_KEY_FILE}`);\n const caKey = readFileSync(CA_KEY_FILE);\n return Buffer.from(crypto.hkdfSync('sha256', caKey, 'cofactor-emulation', 'aws-kms-key', 32));\n}\n\n/** A KeyId (key id, key ARN, alias name or alias ARN) as the key ARN AWS answers with; null for a malformed ARN. */\nfunction keyArn(keyId: string, region: string): string | null {\n if (keyId.startsWith('arn:')) {\n if (/^arn:[a-z-]+:kms:[a-z0-9-]+:\\d{12}:key\\/[^/]+$/.test(keyId)) return keyId;\n const alias = /^arn:[a-z-]+:kms:[a-z0-9-]+:\\d{12}:(alias\\/.+)$/.exec(keyId)?.[1];\n return alias === undefined ? null : keyArn(alias, region);\n }\n // An alias has no key id of its own here: it names a stable emulated one.\n const id = keyId.startsWith('alias/') ? stableUuid('kms-alias', keyId) : keyId;\n return `arn:${partition(region)}:kms:${region}:${ACCOUNT_ID}:key/${id}`;\n}\n\n/** The encryption context as additional authenticated data: its entries sorted by key. */\nfunction contextAad(context: unknown): Buffer {\n const entries = typeof context === 'object' && context !== null ? Object.entries(context).sort(([a], [b]) => (a < b ? -1 : 1)) : [];\n return Buffer.from(JSON.stringify(entries), 'utf8');\n}\n\nfunction seal(key: Buffer, arn: string, plaintext: Buffer, context: unknown): Buffer {\n const iv = crypto.randomBytes(IV_BYTES);\n const arnBytes = Buffer.from(arn, 'utf8');\n const length = Buffer.alloc(2);\n length.writeUInt16BE(arnBytes.length);\n const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);\n cipher.setAAD(Buffer.concat([length, arnBytes, contextAad(context)]));\n const sealed = Buffer.concat([cipher.update(plaintext), cipher.final()]);\n return Buffer.concat([MAGIC, length, arnBytes, iv, cipher.getAuthTag(), sealed]);\n}\n\n/** The key ARN and plaintext of emulated ciphertext, or null when it is not ours or does not authenticate. */\nfunction open(key: Buffer, blob: Buffer, context: unknown): { arn: string; plaintext: Buffer } | null {\n if (blob.length < MAGIC.length + 2 || !blob.subarray(0, MAGIC.length).equals(MAGIC)) return null;\n const arnLength = blob.readUInt16BE(MAGIC.length);\n const arnStart = MAGIC.length + 2;\n const ivStart = arnStart + arnLength;\n const sealedStart = ivStart + IV_BYTES + TAG_BYTES;\n if (blob.length < sealedStart) return null;\n const arnBytes = blob.subarray(arnStart, ivStart);\n try {\n const decipher = crypto.createDecipheriv('aes-256-gcm', key, blob.subarray(ivStart, ivStart + IV_BYTES));\n decipher.setAAD(Buffer.concat([blob.subarray(MAGIC.length, arnStart), arnBytes, contextAad(context)]));\n decipher.setAuthTag(blob.subarray(ivStart + IV_BYTES, sealedStart));\n const plaintext = Buffer.concat([decipher.update(blob.subarray(sealedStart)), decipher.final()]);\n return { arn: arnBytes.toString('utf8'), plaintext };\n } catch {\n // A failed GCM authentication is exactly AWS's InvalidCiphertextException (wrong context, tampered blob).\n return null;\n }\n}\n\nconst invalidCiphertext = () => awsError('InvalidCiphertextException', 'The ciphertext is invalid or was not encrypted under this emulated key.', 'message');\nconst incorrectKey = () =>\n awsError('IncorrectKeyException', 'The key ID in the request does not identify a CMK that can perform this operation.', 'message');\nconst validation = (message: string) => awsError('ValidationException', message, 'message');\n\nfunction masterKey(state: KmsState): Buffer {\n state.masterKey ??= deriveKey();\n return state.masterKey;\n}\n\nconst malformedKey = (keyId: string) => validation(`Invalid keyId ${keyId}`);\n\n/** A base64 blob field of the request, or null when it is missing or not base64. */\nfunction blobField(value: unknown): Buffer | null {\n return typeof value === 'string' && value !== '' && isBase64(value) ? Buffer.from(value, 'base64') : null;\n}\n\nfunction decrypt(state: KmsState, region: string, body: Record<string, unknown>): EmulationResponse {\n const blob = blobField(body.CiphertextBlob);\n if (!blob) return validation('CiphertextBlob must be base64-encoded ciphertext.');\n const requested = typeof body.KeyId === 'string' ? keyArn(body.KeyId, region) : null;\n if (typeof body.KeyId === 'string' && requested === null) return malformedKey(body.KeyId);\n const seeded = state.seeded.get(blob.toString('base64'));\n if (seeded) {\n // A seed without a KeyId answers with a stable emulated key's ARN and matches any requested key.\n // The schema accepts only a well-formed key_id, so keyArn cannot return null for it.\n const arn = keyArn(seeded.keyId ?? stableUuid('kms-key', 'default'), region)!;\n if (requested !== null && seeded.keyId !== null && requested !== arn) return incorrectKey();\n return awsOk({ KeyId: arn, Plaintext: seeded.plaintext.toString('base64'), EncryptionAlgorithm: ALGORITHM });\n }\n const opened = open(masterKey(state), blob, body.EncryptionContext);\n if (!opened) return invalidCiphertext();\n if (requested !== null && requested !== opened.arn) return incorrectKey();\n return awsOk({ KeyId: opened.arn, Plaintext: opened.plaintext.toString('base64'), EncryptionAlgorithm: ALGORITHM });\n}\n\nfunction encrypt(state: KmsState, region: string, body: Record<string, unknown>): EmulationResponse {\n if (typeof body.KeyId !== 'string' || body.KeyId === '') return validation('KeyId is required.');\n const plaintext = blobField(body.Plaintext);\n if (!plaintext || plaintext.length > MAX_PLAINTEXT_BYTES) return validation('Plaintext must be 1 to 4096 base64-encoded bytes.');\n const arn = keyArn(body.KeyId, region);\n if (arn === null) return malformedKey(body.KeyId);\n return awsOk({\n CiphertextBlob: seal(masterKey(state), arn, plaintext, body.EncryptionContext).toString('base64'),\n KeyId: arn,\n EncryptionAlgorithm: ALGORITHM,\n });\n}\n\nfunction generateDataKey(state: KmsState, region: string, body: Record<string, unknown>): EmulationResponse {\n if (typeof body.KeyId !== 'string' || body.KeyId === '') return validation('KeyId is required.');\n const bytes =\n body.KeySpec === 'AES_256' ? 32 : body.KeySpec === 'AES_128' ? 16 : typeof body.NumberOfBytes === 'number' ? body.NumberOfBytes : null;\n if (bytes === null || !Number.isInteger(bytes) || bytes < 1 || bytes > MAX_DATA_KEY_BYTES) {\n return validation('Please specify either number of bytes (1 to 1024) or key spec (AES_256 or AES_128).');\n }\n const arn = keyArn(body.KeyId, region);\n if (arn === null) return malformedKey(body.KeyId);\n const plaintext = crypto.randomBytes(bytes);\n return awsOk({\n CiphertextBlob: seal(masterKey(state), arn, plaintext, body.EncryptionContext).toString('base64'),\n Plaintext: plaintext.toString('base64'),\n KeyId: arn,\n });\n}\n\nconst OPERATIONS = {\n Decrypt: decrypt,\n Encrypt: encrypt,\n GenerateDataKey: generateDataKey,\n} as const;\n\n/** `POST /` on a KMS endpoint. Null (not emulated) for another host or any other operation. */\nexport function handleKms(req: EmulationRequest, ctx: AwsCtx): EmulationResponse | null {\n const state = ctx.state.kms;\n const region = requestRegion(req, 'kms');\n const operation = targetOperation(req, 'TrentService');\n if (!state || !region || !operation || !Object.hasOwn(OPERATIONS, operation)) return null;\n const body = jsonBody(req);\n if (!body) return awsError('SerializationException', 'The request body is not a JSON object.', 'message');\n return OPERATIONS[operation as keyof typeof OPERATIONS](state, region, body);\n}\n","/**\n * TLS Certificate Generation\n *\n * Generates a self-signed CA and per-domain certificates at startup.\n * The CA cert is written to a shared volume so app containers can trust it\n * via NODE_EXTRA_CA_CERTS.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport { execFileSync } from 'node:child_process';\nimport { writeFileSync, readFileSync, mkdirSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport interface TlsConfig {\n /** PEM-encoded certificate (including CA chain) */\n cert: string;\n /** PEM-encoded private key */\n key: string;\n}\n\nconst CA_DIR = '/etc/emulation';\n/**\n * The CA's private key, which the aws plugin's emulated KMS key is derived\n * from: regenerating the CA (never done; see ensureCa) would also orphan\n * every ciphertext encrypted under that key.\n */\nexport const CA_KEY_FILE = join(CA_DIR, 'ca.key');\n\nconst DOMAIN_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9]$/;\n\n/** Validate domain names to prevent injection into openssl arguments. */\nfunction validateDomains(domains: string[]): void {\n for (const domain of domains) {\n if (!DOMAIN_PATTERN.test(domain) || domain.length > 253) {\n throw new Error(`Invalid domain for TLS cert generation: ${domain}`);\n }\n }\n}\n\nconst EXEC_OPTS = { stdio: 'pipe' as const, timeout: 30_000 };\n\n/**\n * Create the self-signed CA in `caDir`, or reuse the one already on disk.\n * Runs at emulator start whether or not any domain needs a certificate: the\n * supervisor treats `ca.crt` as part of \"healthy\", and an `oidc`-only copy\n * has no domains.\n *\n * The CA must survive an emulator restart: app containers read\n * `NODE_EXTRA_CA_CERTS` once at their own startup, so a rotated CA would\n * silently break TLS trust for any app container that started before the\n * restart. Only the leaf (server) cert, which is re-issued on every start,\n * is allowed to change.\n *\n * `caDir` defaults to the production shared-volume path; overridable so\n * tests can point at a scratch directory instead of `/etc/emulation`\n * (which requires root).\n */\nexport function ensureCa(caDir: string = CA_DIR): { caCertPath: string; caKeyPath: string } {\n mkdirSync(caDir, { recursive: true });\n const caCertPath = join(caDir, 'ca.crt');\n const caKeyPath = join(caDir, 'ca.key');\n\n if (!(existsSync(caCertPath) && existsSync(caKeyPath))) {\n const caKey = crypto.generateKeyPairSync('rsa', { modulusLength: 2048 });\n const caKeyPem = caKey.privateKey.export({ type: 'pkcs8', format: 'pem' }) as string;\n writeFileSync(caKeyPath, caKeyPem, { mode: 0o600 });\n\n execFileSync('openssl', [\n 'req', '-new', '-x509',\n '-key', caKeyPath,\n '-out', caCertPath,\n '-days', '365',\n '-subj', '/CN=Emulation Proxy CA/O=Canary',\n '-addext', 'basicConstraints=critical,CA:TRUE',\n ], EXEC_OPTS);\n }\n\n return { caCertPath, caKeyPath };\n}\n\n/**\n * Generate domain certificates signed by the CA (created or reused through\n * {@link ensureCa}) for the given domains. Only the leaf cert is new on each call.\n */\nexport function generateTlsCerts(domains: string[], caDir: string = CA_DIR): TlsConfig {\n validateDomains(domains);\n const { caCertPath, caKeyPath } = ensureCa(caDir);\n\n // Generate server key + cert signed by CA for all domains\n const serverKey = crypto.generateKeyPairSync('rsa', { modulusLength: 2048 });\n const serverKeyPem = serverKey.privateKey.export({ type: 'pkcs8', format: 'pem' }) as string;\n\n const serverKeyPath = join(caDir, 'server.key');\n const serverCsrPath = join(caDir, 'server.csr');\n const serverCertPath = join(caDir, 'server.crt');\n const extPath = join(caDir, 'server.ext');\n\n writeFileSync(serverKeyPath, serverKeyPem, { mode: 0o600 });\n\n // Build SAN extension file\n const sanEntries = domains.map((d, i) => `DNS.${i + 1} = ${d}`).join('\\n');\n const extContent = [\n 'authorityKeyIdentifier=keyid,issuer',\n 'basicConstraints=CA:FALSE',\n 'keyUsage=digitalSignature,keyEncipherment',\n 'extendedKeyUsage=serverAuth',\n 'subjectAltName=@alt_names',\n '',\n '[alt_names]',\n sanEntries,\n ].join('\\n');\n writeFileSync(extPath, extContent);\n\n // Generate CSR\n execFileSync('openssl', [\n 'req', '-new',\n '-key', serverKeyPath,\n '-out', serverCsrPath,\n '-subj', `/CN=${domains[0]}`,\n ], EXEC_OPTS);\n\n // Sign with CA\n execFileSync('openssl', [\n 'x509', '-req',\n '-in', serverCsrPath,\n '-CA', caCertPath,\n '-CAkey', caKeyPath,\n '-CAcreateserial',\n '-out', serverCertPath,\n '-days', '365',\n '-extfile', extPath,\n ], EXEC_OPTS);\n\n const caCert = readFileSync(caCertPath, 'utf-8');\n const serverCert = readFileSync(serverCertPath, 'utf-8');\n\n return {\n cert: serverCert + '\\n' + caCert,\n key: serverKeyPem,\n };\n}\n","/**\n * AWS Secrets Manager, read-only: the secrets a definition seeds, served by\n * `GetSecretValue`, `BatchGetSecretValue`, `DescribeSecret` and `ListSecrets`\n * with the field names and types of the real API. Each secret has one version,\n * staged `AWSCURRENT`. Writes (`CreateSecret`, `PutSecretValue`, ...) are not\n * emulated: like any unimplemented call they answer 501 in Sandboxes v2, which\n * never passes through to the real service.\n *\n * A secret's ARN, version id and ARN suffix derive from its name only, so they\n * are the same in every copy of a sandbox and across restarts.\n *\n * @module\n */\n\nimport type { EmulationRequest, EmulationResponse } from '../../plugin.js';\nimport type { AwsConfig } from './config.js';\nimport {\n ACCOUNT_ID,\n awsError,\n awsOk,\n jsonBody,\n maxResults,\n paginate,\n partition,\n requestRegion,\n stableHex,\n stableUuid,\n targetOperation,\n} from './protocol.js';\nimport type { AwsCtx } from './types.js';\n\nconst NOT_FOUND = \"Secrets Manager can't find the specified secret.\";\nconst CURRENT = 'AWSCURRENT';\nconst ARN = /^arn:([a-z-]+):secretsmanager:([a-z0-9-]+):(\\d{12}):secret:(.+)$/;\nconst FILTER_KEYS = new Set(['description', 'name', 'tag-key', 'tag-value', 'primary-region', 'owning-service', 'all']);\n\nexport interface SeededSecret {\n name: string;\n /** The six characters Secrets Manager appends to a secret's name in its ARN. */\n suffix: string;\n versionId: string;\n secretString: string;\n /** How many times the app has read this secret's value. */\n reads: number;\n}\n\nexport interface SecretsManagerState {\n /** By name, in the order the definition declares them. */\n secrets: Map<string, SeededSecret>;\n}\n\n/** The state for a config's `secrets_manager` section: each value as its SecretString. */\nexport function initSecretsManager(section: NonNullable<AwsConfig['secrets_manager']>): SecretsManagerState {\n const secrets = new Map<string, SeededSecret>();\n for (const [name, value] of Object.entries(section.secrets)) {\n secrets.set(name, {\n name,\n suffix: stableHex('secret-suffix', name).slice(0, 6),\n versionId: stableUuid('secret-version', name),\n secretString: typeof value === 'string' ? value : JSON.stringify(value),\n reads: 0,\n });\n }\n return { secrets };\n}\n\nexport function secretArn(secret: SeededSecret, region: string): string {\n return `arn:${partition(region)}:secretsmanager:${region}:${ACCOUNT_ID}:secret:${secret.name}-${secret.suffix}`;\n}\n\n/** A secret by name, full ARN, or partial ARN (without the suffix), in `region`. */\nfunction findSecret(state: SecretsManagerState, region: string, secretId: string): SeededSecret | undefined {\n const arn = ARN.exec(secretId);\n if (!arn) return state.secrets.get(secretId);\n const [, arnPartition, arnRegion, account, rest] = arn;\n if (arnPartition !== partition(region) || arnRegion !== region || account !== ACCOUNT_ID) return undefined;\n for (const secret of state.secrets.values()) {\n if (`${secret.name}-${secret.suffix}` === rest) return secret;\n }\n return state.secrets.get(rest!);\n}\n\nconst notFound = (message = NOT_FOUND) => awsError('ResourceNotFoundException', message, 'Message');\nconst invalidParameter = (message: string) => awsError('InvalidParameterException', message, 'Message');\n\nfunction secretValue(secret: SeededSecret, region: string, createdDate: number) {\n secret.reads += 1;\n return {\n ARN: secretArn(secret, region),\n Name: secret.name,\n VersionId: secret.versionId,\n SecretString: secret.secretString,\n VersionStages: [CURRENT],\n CreatedDate: createdDate,\n };\n}\n\ntype Filter = { Key: string; Values: string[] };\n\n/** The request's `Filters`, or an error response when they are malformed. */\nfunction parseFilters(raw: unknown): Filter[] | EmulationResponse {\n if (raw === undefined) return [];\n if (!Array.isArray(raw)) return invalidParameter('Filters must be a list.');\n const filters: Filter[] = [];\n for (const entry of raw) {\n const key = typeof entry === 'object' && entry !== null ? (entry as Record<string, unknown>).Key : undefined;\n const values = typeof entry === 'object' && entry !== null ? (entry as Record<string, unknown>).Values : undefined;\n if (typeof key !== 'string' || !FILTER_KEYS.has(key)) return invalidParameter(`Invalid filter key: ${String(key)}`);\n if (!Array.isArray(values) || !values.every((value) => typeof value === 'string')) {\n return invalidParameter('Filter values must be a list of strings.');\n }\n filters.push({ Key: key, Values: values });\n }\n return filters;\n}\n\n/**\n * Whether a secret passes every filter (filters AND, a filter's values OR). A\n * value starting with `!` negates it. `name` is a case-sensitive prefix match;\n * `all` matches when every word of the value appears in the name, ignoring\n * case. A seeded secret has no description, tags, primary region or owning\n * service, so those keys match nothing (and their `!` negations match every\n * secret, as \"not tagged X\" does on AWS).\n */\nfunction matchesFilters(secret: SeededSecret, filters: Filter[]): boolean {\n return filters.every((filter) =>\n filter.Values.some((raw) => {\n const negated = raw.startsWith('!');\n const value = negated ? raw.slice(1) : raw;\n let matches = false;\n if (filter.Key === 'name') matches = secret.name.startsWith(value);\n else if (filter.Key === 'all') {\n const name = secret.name.toLowerCase();\n matches = value.toLowerCase().split(/\\s+/).filter(Boolean).every((word) => name.includes(word));\n }\n return negated ? !matches : matches;\n })\n );\n}\n\nfunction getSecretValue(state: SecretsManagerState, region: string, body: Record<string, unknown>, createdDate: number) {\n if (typeof body.SecretId !== 'string' || body.SecretId === '') return invalidParameter('You must provide a SecretId.');\n const secret = findSecret(state, region, body.SecretId);\n if (!secret) return notFound();\n if (body.VersionId !== undefined && body.VersionId !== secret.versionId) {\n return notFound(`Secrets Manager can't find the specified secret value for VersionId: ${String(body.VersionId)}`);\n }\n if (body.VersionStage !== undefined && body.VersionStage !== CURRENT) {\n return notFound(`Secrets Manager can't find the specified secret value for staging label: ${String(body.VersionStage)}`);\n }\n return awsOk(secretValue(secret, region, createdDate));\n}\n\nfunction batchGetSecretValue(state: SecretsManagerState, region: string, body: Record<string, unknown>, createdDate: number) {\n const hasList = body.SecretIdList !== undefined;\n if (hasList === (body.Filters !== undefined)) {\n return invalidParameter('Either SecretIdList or Filters must be specified, but not both.');\n }\n if (hasList) {\n const ids = body.SecretIdList;\n if (!Array.isArray(ids) || ids.length === 0 || ids.length > 20 || !ids.every((id) => typeof id === 'string')) {\n return invalidParameter('SecretIdList must be a list of 1 to 20 secret ids.');\n }\n const values = [];\n const errors = [];\n for (const id of ids as string[]) {\n const secret = findSecret(state, region, id);\n if (secret) values.push(secretValue(secret, region, createdDate));\n else errors.push({ SecretId: id, ErrorCode: 'ResourceNotFoundException', Message: NOT_FOUND });\n }\n return awsOk({ SecretValues: values, Errors: errors });\n }\n const filters = parseFilters(body.Filters);\n if (!Array.isArray(filters)) return filters;\n const max = maxResults(body.MaxResults, 20);\n if (max === null) return invalidParameter('MaxResults must be between 1 and 20.');\n const matching = [...state.secrets.values()].filter((secret) => matchesFilters(secret, filters));\n const paged = paginate(matching, max, body.NextToken);\n if (!paged) return awsError('InvalidNextTokenException', 'The NextToken value is invalid.', 'Message');\n return awsOk({\n SecretValues: paged.page.map((secret) => secretValue(secret, region, createdDate)),\n Errors: [],\n ...(paged.nextToken ? { NextToken: paged.nextToken } : {}),\n });\n}\n\nfunction describeSecret(state: SecretsManagerState, region: string, body: Record<string, unknown>, createdDate: number) {\n if (typeof body.SecretId !== 'string' || body.SecretId === '') return invalidParameter('You must provide a SecretId.');\n const secret = findSecret(state, region, body.SecretId);\n if (!secret) return notFound();\n return awsOk({\n ARN: secretArn(secret, region),\n Name: secret.name,\n CreatedDate: createdDate,\n LastChangedDate: createdDate,\n VersionIdsToStages: { [secret.versionId]: [CURRENT] },\n });\n}\n\nfunction listSecrets(state: SecretsManagerState, region: string, body: Record<string, unknown>, createdDate: number) {\n const filters = parseFilters(body.Filters);\n if (!Array.isArray(filters)) return filters;\n const max = maxResults(body.MaxResults, 100);\n if (max === null) return invalidParameter('MaxResults must be between 1 and 100.');\n const matching = [...state.secrets.values()].filter((secret) => matchesFilters(secret, filters));\n const paged = paginate(matching, max, body.NextToken);\n if (!paged) return awsError('InvalidNextTokenException', 'The NextToken value is invalid.', 'Message');\n return awsOk({\n SecretList: paged.page.map((secret) => ({\n ARN: secretArn(secret, region),\n Name: secret.name,\n CreatedDate: createdDate,\n LastChangedDate: createdDate,\n SecretVersionsToStages: { [secret.versionId]: [CURRENT] },\n })),\n ...(paged.nextToken ? { NextToken: paged.nextToken } : {}),\n });\n}\n\nconst OPERATIONS = {\n GetSecretValue: getSecretValue,\n BatchGetSecretValue: batchGetSecretValue,\n DescribeSecret: describeSecret,\n ListSecrets: listSecrets,\n} as const;\n\n/** `POST /` on a Secrets Manager endpoint. Null (not emulated) for any other operation. */\nexport function handleSecretsManager(req: EmulationRequest, ctx: AwsCtx): EmulationResponse | null {\n const state = ctx.state.secretsManager;\n const region = requestRegion(req, 'secretsmanager');\n const operation = targetOperation(req, 'secretsmanager');\n if (!state || !region || !operation || !Object.hasOwn(OPERATIONS, operation)) return null;\n const body = jsonBody(req);\n if (!body) return awsError('SerializationException', 'The request body is not a JSON object.', 'Message');\n return OPERATIONS[operation as keyof typeof OPERATIONS](state, region, body, ctx.state.createdDate);\n}\n","/**\n * Email Provider Emulation Plugin\n *\n * Emulates the HTTP send APIs of several email providers so a sandboxed app's\n * outbound mail is captured in-process instead of leaving the sandbox. One\n * plugin spans many providers; each send request normalizes into a shared\n * `CapturedEmail` shape for assertions and API-side inbox ingestion.\n *\n * Supported providers (HTTP APIs only):\n * - Amazon SES: `POST /` and SES v2 `POST /v2/email/outbound-emails`.\n * - SendGrid: `POST /v3/mail/send`.\n * - Resend: `POST /emails`.\n * - Postmark: `POST /email` and `POST /email/batch`.\n * - Mailgun: `POST /v3/:domain/messages`.\n *\n * With `mailosaur: {}` it also serves Mailosaur's read API on mailosaur.com\n * over the same captures (see `email/mailosaur.ts`), so a suite reading mail\n * through a Mailosaur SDK finds what the app sent.\n *\n * Unknown paths on these hosts pass through to the real provider.\n *\n * @module\n */\n\nimport { z } from 'zod';\nimport type { EmulationPlugin } from '../plugin.js';\nimport { emailActionInterfaces } from './email/actions.js';\nimport {\n handleMailgun,\n handlePostmarkBatch,\n handlePostmarkSingle,\n handleResend,\n handleSendgrid,\n handleSesV1,\n handleSesV2,\n} from './email/handlers.js';\nimport {\n handleDeleteAllMessages,\n handleDeleteMessage,\n handleGetMessage,\n handleGetServer,\n handleListMessages,\n handleListServers,\n handleSearchMessages,\n MAILOSAUR_API_HOST,\n} from './email/mailosaur.js';\nimport { capturedEmailSchema, emailConfigSchema, emailFixtureSchema } from './email/types.js';\nimport type { EmailCtx, EmailEmuConfig, EmailFixture, EmailState } from './email/types.js';\n\nexport { emailFixtureSchema } from './email/types.js';\nexport type {\n CapturedEmail,\n EmailEmuConfig,\n EmailFixture,\n EmailProvider,\n EmailState,\n} from './email/types.js';\n\nconst DEFAULT_SES_REGIONS = ['us-east-1'];\n\n/** Shared by the `sent-emails` controlRead (v1) and operation (v2). */\nfunction getSentEmails(ctx: EmailCtx): { emails: EmailState['sentEmails'] } {\n return { emails: ctx.state.sentEmails };\n}\n\nexport const emailPlugin: EmulationPlugin<EmailEmuConfig, EmailFixture, EmailState> = {\n id: 'email',\n name: 'Email (multi-provider)',\n version: '1.0.0',\n\n domains: (config) => {\n const sesRegions = config.sesRegions?.length ? config.sesRegions : DEFAULT_SES_REGIONS;\n return [\n 'api.sendgrid.com',\n 'api.resend.com',\n 'api.postmarkapp.com',\n 'api.mailgun.net',\n 'api.eu.mailgun.net',\n ...sesRegions.map((region) => `email.${region}.amazonaws.com`),\n ...(config.extraDomains ?? []),\n ...(config.mailosaur ? [MAILOSAUR_API_HOST] : []),\n ];\n },\n\n configSchema: emailConfigSchema,\n\n needsBrowserIntercept: false,\n\n fixtureSchema: emailFixtureSchema,\n defaultFixture: {},\n\n actionInterfaces: emailActionInterfaces,\n\n controlReads: [\n {\n path: 'sent-emails',\n handler: (_req, ctx: EmailCtx) => ({\n status: 200,\n body: getSentEmails(ctx),\n }),\n },\n ],\n\n operations: [\n {\n id: 'sent-emails',\n description: 'All emails captured since boot or last reset.',\n input: z.object({}).strict(),\n output: z.object({ emails: z.array(capturedEmailSchema) }),\n handler: (ctx: EmailCtx) => getSentEmails(ctx),\n },\n ],\n\n routes: [\n { method: 'POST', path: '/v3/mail/send', handler: handleSendgrid },\n { method: 'POST', path: '/emails', handler: handleResend },\n { method: 'POST', path: '/email', handler: handlePostmarkSingle },\n { method: 'POST', path: '/email/batch', handler: handlePostmarkBatch },\n { method: 'POST', path: '/v3/:domain/messages', handler: handleMailgun },\n { method: 'POST', path: '/v2/email/outbound-emails', handler: handleSesV2 },\n { method: 'POST', path: '/api/messages/search', handler: handleSearchMessages },\n { method: 'GET', path: '/api/messages', handler: handleListMessages },\n { method: 'DELETE', path: '/api/messages', handler: handleDeleteAllMessages },\n { method: 'GET', path: '/api/messages/:id', handler: handleGetMessage },\n { method: 'DELETE', path: '/api/messages/:id', handler: handleDeleteMessage },\n { method: 'GET', path: '/api/servers', handler: handleListServers },\n { method: 'GET', path: '/api/servers/:id', handler: handleGetServer },\n { method: 'POST', path: '/', handler: handleSesV1 },\n ],\n\n initialize(_config, _fixture, _env): EmailState {\n return { sentEmails: [], mailosaurHidden: new Set() };\n },\n};\n","/**\n * Email plugin action-interface declarations.\n *\n * @module\n */\n\nimport type { ActionInterfaceDef } from '../../plugin.js';\n\nexport const emailActionInterfaces: ActionInterfaceDef[] = [\n {\n slug: 'email-sent-messages',\n label: 'Read emails the app sent',\n description:\n 'Return the emails the app sent via any emulated provider since boot (or the last reset), for assertions.',\n inputSchema: { type: 'object', properties: {} },\n outputSchema: {\n type: 'object',\n properties: {\n emails: {\n type: 'array',\n description: 'Captured emails: { id, provider, from, to[], subject, text, html, ... }',\n },\n },\n },\n scaffoldScript: `# Read emails the app sent to the emulated providers.\ncurl -sf \"$EMULATION_BASE_URL/plugins/email/sent-emails\" \\\\\n -H \"Authorization: Bearer $EMULATION_CONTROL_TOKEN\"`,\n },\n {\n slug: 'email-reset',\n label: 'Clear captured emails',\n description: 'Reset the email emulator, discarding all captured emails.',\n inputSchema: { type: 'object', properties: {} },\n outputSchema: { type: 'object', properties: { ok: { type: 'boolean' } } },\n scaffoldScript: `# Discard all captured emails.\ncurl -sf -X POST \"$EMULATION_BASE_URL/plugins/email/reset\" \\\\\n -H \"Authorization: Bearer $EMULATION_CONTROL_TOKEN\"`,\n },\n];\n","/**\n * Provider-specific HTTP handlers for the email emulation plugin.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport type { EmulationRequest, EmulationResponse } from '../../plugin.js';\nimport { record } from './capture.js';\nimport {\n decodeBase64,\n extractGenericAttachments,\n isRecord,\n parseAddress,\n parseAddressList,\n parseRawMime,\n safeParseJson,\n} from './parsing.js';\nimport type { EmailCtx } from './types.js';\n\n/** SendGrid v3 - POST /v3/mail/send (returns 202 with X-Message-Id). */\nexport function handleSendgrid(req: EmulationRequest, ctx: EmailCtx): EmulationResponse {\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return { status: 400, body: { errors: [{ message: 'Invalid JSON body' }] } };\n if (!isRecord(parsed.data))\n return { status: 400, body: { errors: [{ message: 'Invalid JSON body' }] } };\n const data = parsed.data;\n\n const personalizations: unknown[] = Array.isArray(data.personalizations)\n ? data.personalizations\n : [];\n const to: string[] = [];\n const cc: string[] = [];\n const bcc: string[] = [];\n let subject: string | null = typeof data.subject === 'string' ? data.subject : null;\n for (const p of personalizations) {\n const pers = isRecord(p) ? p : {};\n to.push(...parseAddressList(pers.to).emails);\n cc.push(...parseAddressList(pers.cc).emails);\n bcc.push(...parseAddressList(pers.bcc).emails);\n if (!subject && typeof pers.subject === 'string') subject = pers.subject;\n }\n\n const fromAddr = parseAddress(data.from);\n const content = Array.isArray(data.content) ? data.content.filter(isRecord) : [];\n const textValue = content.find((c) => c.type === 'text/plain')?.value;\n const htmlValue = content.find((c) => c.type === 'text/html')?.value;\n const text = typeof textValue === 'string' ? textValue : null;\n const html = typeof htmlValue === 'string' ? htmlValue : null;\n\n const captured = record(ctx, {\n provider: 'sendgrid',\n from: fromAddr?.email ?? '',\n ...(fromAddr?.name ? { fromName: fromAddr.name } : {}),\n to,\n cc,\n bcc,\n subject,\n text,\n html,\n headers: { 'x-provider': 'sendgrid' },\n attachments: extractGenericAttachments(data.attachments, 'filename', 'type'),\n });\n\n return { status: 202, headers: { 'x-message-id': captured.id }, body: '' };\n}\n\n/** Resend - POST /emails (returns 200 {id}). */\nexport function handleResend(req: EmulationRequest, ctx: EmailCtx): EmulationResponse {\n const parsed = safeParseJson(req.body);\n if (!parsed.ok)\n return { status: 400, body: { message: 'Invalid JSON body', name: 'validation_error' } };\n if (!isRecord(parsed.data))\n return { status: 400, body: { message: 'Invalid JSON body', name: 'validation_error' } };\n const data = parsed.data;\n\n const fromAddr = parseAddress(data.from);\n const captured = record(ctx, {\n provider: 'resend',\n from: fromAddr?.email ?? '',\n ...(fromAddr?.name ? { fromName: fromAddr.name } : {}),\n to: parseAddressList(data.to).emails,\n cc: parseAddressList(data.cc).emails,\n bcc: parseAddressList(data.bcc).emails,\n subject: typeof data.subject === 'string' ? data.subject : null,\n text: typeof data.text === 'string' ? data.text : null,\n html: typeof data.html === 'string' ? data.html : null,\n headers: { 'x-provider': 'resend' },\n attachments: extractGenericAttachments(data.attachments, 'filename', 'content_type'),\n });\n\n return { status: 200, body: { id: captured.id } };\n}\n\n/** Postmark - POST /email (returns 200 {MessageID, ErrorCode:0}). */\nexport function handlePostmarkSingle(req: EmulationRequest, ctx: EmailCtx): EmulationResponse {\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return { status: 422, body: { ErrorCode: 300, Message: 'Invalid JSON body' } };\n if (!isRecord(parsed.data))\n return { status: 422, body: { ErrorCode: 300, Message: 'Invalid JSON body' } };\n return { status: 200, body: postmarkRecord(ctx, parsed.data) };\n}\n\n/** Postmark - POST /email/batch (returns 200 [{MessageID}, ...]). */\nexport function handlePostmarkBatch(req: EmulationRequest, ctx: EmailCtx): EmulationResponse {\n const parsed = safeParseJson(req.body);\n if (!parsed.ok || !Array.isArray(parsed.data)) {\n return { status: 422, body: { ErrorCode: 300, Message: 'Invalid batch body' } };\n }\n return {\n status: 200,\n body: parsed.data.map((entry) => postmarkRecord(ctx, isRecord(entry) ? entry : {})),\n };\n}\n\nfunction postmarkRecord(ctx: EmailCtx, data: Record<string, unknown>) {\n const fromAddr = parseAddress(typeof data.From === 'string' ? data.From : null);\n const captured = record(ctx, {\n provider: 'postmark',\n from: fromAddr?.email ?? '',\n ...(fromAddr?.name ? { fromName: fromAddr.name } : {}),\n to: parseAddressList(data.To).emails,\n cc: parseAddressList(data.Cc).emails,\n bcc: parseAddressList(data.Bcc).emails,\n subject: typeof data.Subject === 'string' ? data.Subject : null,\n text: typeof data.TextBody === 'string' ? data.TextBody : null,\n html: typeof data.HtmlBody === 'string' ? data.HtmlBody : null,\n headers: { 'x-provider': 'postmark' },\n attachments: extractGenericAttachments(data.Attachments, 'Name', 'ContentType'),\n });\n return {\n To: parseAddressList(data.To).emails.join(', '),\n SubmittedAt: captured.receivedAt,\n MessageID: captured.id,\n ErrorCode: 0,\n Message: 'OK',\n };\n}\n\n/** Mailgun - POST /v3/:domain/messages (form-encoded, returns 200 {id, message}). */\nexport function handleMailgun(req: EmulationRequest, ctx: EmailCtx): EmulationResponse {\n const form = new URLSearchParams(req.body ?? '');\n const fromAddr = parseAddress(form.get('from'));\n const collect = (key: string) =>\n form.getAll(key).flatMap((value) => parseAddressList(value).emails);\n\n const captured = record(ctx, {\n provider: 'mailgun',\n from: fromAddr?.email ?? '',\n ...(fromAddr?.name ? { fromName: fromAddr.name } : {}),\n to: collect('to'),\n cc: collect('cc'),\n bcc: collect('bcc'),\n subject: form.get('subject'),\n text: form.get('text'),\n html: form.get('html'),\n headers: { 'x-provider': 'mailgun' },\n attachments: [],\n });\n\n return {\n status: 200,\n body: { id: `<${captured.id}@mailgun.emulated>`, message: 'Queued. Thank you.' },\n };\n}\n\n/** Amazon SES - POST / (SendEmail / SendRawEmail, query/form-encoded). */\nexport function handleSesV1(req: EmulationRequest, ctx: EmailCtx): EmulationResponse {\n const form = new URLSearchParams(req.body ?? '');\n const action = form.get('Action') ?? '';\n\n if (action === 'SendRawEmail') {\n const rawData = form.get('RawMessage.Data');\n const mime = rawData ? parseRawMime(decodeBase64(rawData)) : null;\n const captured = record(ctx, {\n provider: 'ses',\n from: mime?.from?.email ?? (form.get('Source') ?? '').toLowerCase(),\n ...(mime?.from?.name ? { fromName: mime.from.name } : {}),\n to: mime?.to ?? sesMemberList(form, 'Destinations.member'),\n cc: mime?.cc ?? [],\n bcc: mime?.bcc ?? [],\n subject: mime?.subject ?? null,\n text: mime?.text ?? null,\n html: mime?.html ?? null,\n headers: { 'x-provider': 'ses', 'x-ses-action': 'SendRawEmail' },\n attachments: [],\n });\n return sesXmlResponse('SendRawEmail', captured.id);\n }\n\n const captured = record(ctx, {\n provider: 'ses',\n from: (form.get('Source') ?? '').toLowerCase(),\n to: sesMemberList(form, 'Destination.ToAddresses.member'),\n cc: sesMemberList(form, 'Destination.CcAddresses.member'),\n bcc: sesMemberList(form, 'Destination.BccAddresses.member'),\n subject: form.get('Message.Subject.Data'),\n text: form.get('Message.Body.Text.Data'),\n html: form.get('Message.Body.Html.Data'),\n headers: { 'x-provider': 'ses', 'x-ses-action': action || 'SendEmail' },\n attachments: [],\n });\n return sesXmlResponse('SendEmail', captured.id);\n}\n\n/** Amazon SES v2 - POST /v2/email/outbound-emails (JSON). */\nexport function handleSesV2(req: EmulationRequest, ctx: EmailCtx): EmulationResponse {\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return { status: 400, body: { message: 'Invalid JSON body' } };\n if (!isRecord(parsed.data)) return { status: 400, body: { message: 'Invalid JSON body' } };\n const data = parsed.data;\n\n const dest = isRecord(data.Destination) ? data.Destination : {};\n const content = isRecord(data.Content) ? data.Content : {};\n const simple = isRecord(content.Simple) ? content.Simple : undefined;\n const raw = isRecord(content.Raw) ? content.Raw : undefined;\n\n let subject: string | null = null;\n let text: string | null = null;\n let html: string | null = null;\n let from = String(data.FromEmailAddress ?? '').toLowerCase();\n let to = parseAddressList(dest.ToAddresses).emails;\n let cc = parseAddressList(dest.CcAddresses).emails;\n let bcc = parseAddressList(dest.BccAddresses).emails;\n\n if (raw?.Data) {\n const mime = parseRawMime(decodeBase64(String(raw.Data)));\n if (mime.from) from = mime.from.email;\n if (mime.to.length) to = mime.to;\n if (mime.cc.length) cc = mime.cc;\n if (mime.bcc.length) bcc = mime.bcc;\n subject = mime.subject;\n text = mime.text;\n html = mime.html;\n } else if (simple) {\n const subjObj = isRecord(simple.Subject) ? simple.Subject : undefined;\n const bodyObj = isRecord(simple.Body) ? simple.Body : undefined;\n const textObj = bodyObj && isRecord(bodyObj.Text) ? bodyObj.Text : undefined;\n const htmlObj = bodyObj && isRecord(bodyObj.Html) ? bodyObj.Html : undefined;\n subject = subjObj?.Data ? String(subjObj.Data) : null;\n text = textObj?.Data ? String(textObj.Data) : null;\n html = htmlObj?.Data ? String(htmlObj.Data) : null;\n }\n\n const fromAddr = parseAddress(from);\n const captured = record(ctx, {\n provider: 'ses',\n from: fromAddr?.email ?? from,\n ...(fromAddr?.name ? { fromName: fromAddr.name } : {}),\n to,\n cc,\n bcc,\n subject,\n text,\n html,\n headers: { 'x-provider': 'ses', 'x-ses-action': 'SendEmailV2' },\n attachments: [],\n });\n\n return { status: 200, body: { MessageId: captured.id } };\n}\n\nfunction sesMemberList(form: URLSearchParams, prefix: string): string[] {\n const out: string[] = [];\n for (let i = 1; ; i++) {\n const value = form.get(`${prefix}.${i}`);\n if (value === null) break;\n const parsed = parseAddress(value);\n if (parsed) out.push(parsed.email);\n }\n return out;\n}\n\nfunction sesXmlResponse(\n action: 'SendEmail' | 'SendRawEmail',\n messageId: string\n): EmulationResponse {\n const requestId = crypto.randomUUID();\n const body = `<${action}Response xmlns=\"http://ses.amazonaws.com/doc/2010-12-01/\">\n <${action}Result>\n <MessageId>${messageId}</MessageId>\n </${action}Result>\n <ResponseMetadata>\n <RequestId>${requestId}</RequestId>\n </ResponseMetadata>\n</${action}Response>`;\n return { status: 200, headers: { 'content-type': 'application/xml' }, body };\n}\n","/**\n * Email capture state mutation helpers.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport type { CapturedEmail, EmailCtx } from './types.js';\n\n/** Cap retained captures so a runaway send loop cannot grow state unbounded. */\nconst MAX_RETAINED_EMAILS = 500;\n\nexport function record(\n ctx: EmailCtx,\n email: Omit<CapturedEmail, 'id' | 'receivedAt'>\n): CapturedEmail {\n const captured: CapturedEmail = {\n id: crypto.randomUUID(),\n receivedAt: new Date().toISOString(),\n ...email,\n };\n ctx.state.sentEmails.push(captured);\n if (ctx.state.sentEmails.length > MAX_RETAINED_EMAILS) {\n ctx.state.sentEmails.splice(0, ctx.state.sentEmails.length - MAX_RETAINED_EMAILS);\n }\n\n const recipientCount = email.to.length + email.cc.length + email.bcc.length;\n ctx.log(\n 'info',\n `[${email.provider}] captured email ${captured.id} for ${recipientCount} recipient(s)`\n );\n return captured;\n}\n","/**\n * Email address, MIME, and provider payload parsing helpers.\n *\n * @module\n */\n\nimport type { CapturedEmail } from './types.js';\n\nexport interface ParsedAddress {\n email: string;\n name?: string;\n}\n\nexport interface ParsedRawMime {\n from: ParsedAddress | null;\n to: string[];\n cc: string[];\n bcc: string[];\n subject: string | null;\n text: string | null;\n html: string | null;\n}\n\ntype JsonObject = Record<string, unknown>;\n\n/**\n * Parse a single address from a string (\"Name <a@b.com>\" / \"a@b.com\") or an\n * object ({ email, name }, as SendGrid uses).\n */\nexport function parseAddress(input: unknown): ParsedAddress | null {\n if (input && typeof input === 'object' && 'email' in input) {\n const email = String((input as { email: unknown }).email ?? '')\n .trim()\n .toLowerCase();\n if (!email) return null;\n const name = (input as { name?: unknown }).name;\n return { email, ...(name ? { name: String(name) } : {}) };\n }\n if (typeof input !== 'string') return null;\n const trimmed = input.trim();\n if (!trimmed) return null;\n const angle = /^\\s*(?:\"?([^\"<]*?)\"?\\s*)?<([^>]+)>\\s*$/.exec(trimmed);\n if (angle) {\n const name = angle[1]?.trim();\n return { email: angle[2].trim().toLowerCase(), ...(name ? { name } : {}) };\n }\n return { email: trimmed.toLowerCase() };\n}\n\n/**\n * Parse an address list that may be a string, an array of strings, or an array\n * of `{email,name}` objects.\n */\nexport function parseAddressList(input: unknown): { emails: string[]; first?: ParsedAddress } {\n const out: ParsedAddress[] = [];\n\n const pushString = (value: string) => {\n // This intentionally supports the provider payloads we emulate, not full RFC parsing.\n for (const part of value.split(',')) {\n const parsed = parseAddress(part);\n if (parsed) out.push(parsed);\n }\n };\n\n if (typeof input === 'string') {\n pushString(input);\n } else if (Array.isArray(input)) {\n for (const entry of input) {\n if (typeof entry === 'string') {\n pushString(entry);\n } else if (entry && typeof entry === 'object' && 'email' in entry) {\n const email = String((entry as { email: unknown }).email ?? '')\n .trim()\n .toLowerCase();\n if (email) {\n const name = (entry as { name?: unknown }).name;\n out.push({ email, ...(name ? { name: String(name) } : {}) });\n }\n }\n }\n }\n\n return { emails: out.map((a) => a.email), ...(out[0] ? { first: out[0] } : {}) };\n}\n\n/** Decode a base64 payload to a UTF-8 string. */\nexport function decodeBase64(data: string): string {\n return Buffer.from(data, 'base64').toString('utf-8');\n}\n\n/** Decode quoted-printable: soft line breaks plus `=XX` hex escapes. */\nfunction decodeQuotedPrintable(input: string): string {\n return input\n .replace(/=\\r?\\n/g, '')\n .replace(/=([0-9A-Fa-f]{2})/g, (_m, hex) => String.fromCharCode(parseInt(hex, 16)));\n}\n\nfunction decodeMimeBody(body: string, contentTransferEncoding: string): string {\n const cte = contentTransferEncoding.trim().toLowerCase();\n if (cte === 'base64') {\n return Buffer.from(body.replace(/\\s+/g, ''), 'base64').toString('utf-8');\n }\n if (cte === 'quoted-printable') return decodeQuotedPrintable(body);\n return body;\n}\n\n/**\n * Best-effort raw-MIME parse: header block plus first body part. Enough to\n * surface OTP and magic-link mail without pulling in a full MIME parser.\n */\nexport function parseRawMime(raw: string): ParsedRawMime {\n const norm = raw.replace(/\\r\\n/g, '\\n');\n const splitAt = norm.indexOf('\\n\\n');\n const headerBlock = splitAt >= 0 ? norm.slice(0, splitAt) : norm;\n const body = splitAt >= 0 ? norm.slice(splitAt + 2) : '';\n\n const unfolded = headerBlock.replace(/\\n[ \\t]+/g, ' ');\n const headers = new Map<string, string>();\n for (const line of unfolded.split('\\n')) {\n const m = /^([^:]+):\\s*(.*)$/.exec(line);\n if (m) headers.set(m[1].trim().toLowerCase(), m[2].trim());\n }\n\n const contentType = headers.get('content-type') ?? '';\n const isHtml = /text\\/html/i.test(contentType);\n const isMultipart = /multipart\\//i.test(contentType);\n const decodedBody = isMultipart\n ? body\n : decodeMimeBody(body, headers.get('content-transfer-encoding') ?? '');\n\n return {\n from: parseAddress(headers.get('from')),\n to: parseAddressList(headers.get('to')).emails,\n cc: parseAddressList(headers.get('cc')).emails,\n bcc: parseAddressList(headers.get('bcc')).emails,\n subject: headers.get('subject') ?? null,\n text: isHtml ? null : decodedBody || null,\n html: isHtml ? decodedBody || null : null,\n };\n}\n\nexport function isRecord(value: unknown): value is JsonObject {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nexport function safeParseJson(\n body: string | undefined\n): { ok: true; data: unknown } | { ok: false } {\n try {\n return { ok: true, data: JSON.parse(body ?? '{}') };\n } catch {\n return { ok: false };\n }\n}\n\nexport function extractGenericAttachments(\n input: unknown,\n nameKey: string,\n typeKey: string\n): CapturedEmail['attachments'] {\n if (!Array.isArray(input)) return [];\n return input.map((entry) => {\n const att = (entry ?? {}) as Record<string, unknown>;\n const filename = att[nameKey];\n const contentType = att[typeKey];\n return {\n ...(typeof filename === 'string' ? { filename } : {}),\n ...(typeof contentType === 'string' ? { contentType } : {}),\n };\n });\n}\n","/**\n * Mailosaur-compatible inbox over the email plugin's captured mail.\n *\n * With `email: { mailosaur: {} }` the plugin also owns `mailosaur.com`, the\n * host every official Mailosaur SDK calls, and answers the read side of its\n * REST API (`/api/messages*`, `/api/servers*`) from `state.sentEmails`. A\n * captured email belongs to server `<id>` when one of its recipients is\n * `<anything>@<id>.mailosaur.net`, Mailosaur's addressing scheme. Deleting\n * hides a message from the inbox only; `email.sent-emails` still returns it.\n *\n * Shapes follow the official `mailosaur` npm SDK (11.x): Basic auth with the\n * API key as the user name (any key is accepted), list results as\n * `{ items }`, 204 for deletes, and the SDK's 400 `{ errors: [{ field,\n * detail: [{ description }] }] }`. The SDK's wait-for (`messages.get`,\n * `search` with `timeout`) polls `POST /api/messages/search` client-side,\n * pausing for the `x-ms-delay` header between polls.\n *\n * Everything else on mailosaur.com (creating servers or messages, files,\n * previews, analysis, devices, usage) is not declared, so it answers 501.\n *\n * @module\n */\n\nimport type { EmulationRequest, EmulationResponse } from '../../plugin.js';\nimport { isRecord, safeParseJson } from './parsing.js';\nimport type { CapturedEmail, EmailCtx } from './types.js';\n\nexport const MAILOSAUR_API_HOST = 'mailosaur.com';\n\nconst SERVER_ID = /^[a-z0-9]+$/;\nconst SERVER_ADDRESS = new RegExp(`^[^@\\\\s]+@(${SERVER_ID.source.slice(1, -1)})\\\\.mailosaur\\\\.net$`);\nconst DEFAULT_ITEMS_PER_PAGE = 50;\nconst MAX_ITEMS_PER_PAGE = 1000;\n/** Polling pause the SDK reads between empty searches; mail is captured synchronously, so keep it short. */\nconst POLL_DELAY_MS = 250;\n\ninterface Address {\n name: string;\n email: string;\n}\n\ninterface Inboxed {\n server: string;\n email: CapturedEmail;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Inbox\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** The Mailosaur servers an email was delivered to, by its recipients' addresses. */\nfunction serversOf(email: CapturedEmail): string[] {\n const servers = new Set<string>();\n for (const address of [...email.to, ...email.cc, ...email.bcc]) {\n const match = SERVER_ADDRESS.exec(address.toLowerCase());\n if (match) servers.add(match[1]!);\n }\n return [...servers];\n}\n\nfunction hiddenKey(server: string, id: string): string {\n return `${server}/${id}`;\n}\n\n/** Every visible (server, email) pair, newest first. */\nfunction inbox(ctx: EmailCtx): Inboxed[] {\n const out: Inboxed[] = [];\n for (const email of ctx.state.sentEmails) {\n for (const server of serversOf(email)) {\n if (!ctx.state.mailosaurHidden.has(hiddenKey(server, email.id))) out.push({ server, email });\n }\n }\n return out.reverse();\n}\n\nfunction findMessage(ctx: EmailCtx, id: string): Inboxed | undefined {\n return inbox(ctx).find((entry) => entry.email.id === id);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Content extraction\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction decodeEntities(value: string): string {\n return value\n .replace(/&#x([0-9a-f]+);/gi, (_m, hex: string) => String.fromCodePoint(parseInt(hex, 16)))\n .replace(/&#(\\d+);/g, (_m, dec: string) => String.fromCodePoint(parseInt(dec, 10)))\n .replace(/ /g, ' ')\n .replace(/"/g, '\"')\n .replace(/'|'/g, \"'\")\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&');\n}\n\n/** The text a reader sees in an HTML body: no head, style or script, no tags, entities decoded. */\nfunction visibleText(html: string): string {\n return decodeEntities(\n html\n .replace(/<(head|style|script)\\b[\\s\\S]*?<\\/\\1\\s*>/gi, ' ')\n .replace(/<br\\s*\\/?>|<\\/(p|div|tr|li|h[1-6])\\s*>/gi, '\\n')\n .replace(/<[^>]+>/g, ' ')\n );\n}\n\nfunction attribute(tag: string, name: string): string | null {\n const match = new RegExp(`\\\\s${name}\\\\s*=\\\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\\\s>]+))`, 'i').exec(tag);\n if (!match) return null;\n return decodeEntities(match[1] ?? match[2] ?? match[3] ?? '');\n}\n\nfunction htmlLinks(html: string): Array<{ href: string; text: string }> {\n const links: Array<{ href: string; text: string }> = [];\n for (const match of html.matchAll(/(<a\\b[^>]*>)([\\s\\S]*?)<\\/a\\s*>/gi)) {\n const href = attribute(match[1]!, 'href');\n if (href) links.push({ href, text: collapse(visibleText(match[2]!)) });\n }\n return links;\n}\n\nfunction htmlImages(html: string): Array<{ src: string; alt: string }> {\n const images: Array<{ src: string; alt: string }> = [];\n for (const match of html.matchAll(/<img\\b[^>]*>/gi)) {\n const src = attribute(match[0], 'src');\n if (src) images.push({ src, alt: attribute(match[0], 'alt') ?? '' });\n }\n return images;\n}\n\nconst URL_IN_TEXT = /https?:\\/\\/[^\\s<>\"']+/g;\n\nfunction textLinks(text: string): Array<{ href: string; text: string }> {\n return [...text.matchAll(URL_IN_TEXT)].map((match) => {\n const href = match[0].replace(/[).,;:!?\\]]+$/, '');\n return { href, text: href };\n });\n}\n\n/**\n * Verification codes in the order they appear: a standalone run of 4–8\n * digits, or 4–8 upper-case letters and digits holding at least one of each.\n * URLs are skipped, so ids inside links are not codes.\n */\nfunction extractCodes(text: string): Array<{ value: string }> {\n const seen = new Set<string>();\n const codes: Array<{ value: string }> = [];\n const withoutUrls = text.replace(URL_IN_TEXT, ' ');\n for (const match of withoutUrls.matchAll(/(?<![\\w-])([0-9]{4,8}|[A-Z0-9]{4,8})(?![\\w-])/g)) {\n const value = match[1]!;\n const isDigits = /^[0-9]+$/.test(value);\n if (!isDigits && !(/[0-9]/.test(value) && /[A-Z]/.test(value))) continue;\n if (seen.has(value)) continue;\n seen.add(value);\n codes.push({ value });\n }\n return codes;\n}\n\nfunction collapse(value: string): string {\n return value.replace(/\\s+/g, ' ').trim();\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Serialization\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction addresses(emails: string[]): Address[] {\n return emails.map((email) => ({ name: '', email }));\n}\n\nfunction fromAddresses(email: CapturedEmail): Address[] {\n return email.from ? [{ name: email.fromName ?? '', email: email.from }] : [];\n}\n\nfunction summaryText(email: CapturedEmail): string {\n const body = email.text ?? (email.html ? visibleText(email.html) : '');\n return collapse(body).slice(0, 200);\n}\n\nfunction messageSummary({ server, email }: Inboxed) {\n return {\n id: email.id,\n type: 'Email',\n server,\n from: fromAddresses(email),\n to: addresses(email.to),\n cc: addresses(email.cc),\n bcc: addresses(email.bcc),\n received: email.receivedAt,\n subject: email.subject ?? '',\n summary: summaryText(email),\n attachments: email.attachments.length,\n };\n}\n\nfunction message({ server, email }: Inboxed) {\n const html = email.html;\n const text = email.text;\n return {\n id: email.id,\n type: 'Email',\n server,\n from: fromAddresses(email),\n to: addresses(email.to),\n cc: addresses(email.cc),\n bcc: addresses(email.bcc),\n received: email.receivedAt,\n subject: email.subject ?? '',\n html: {\n body: html,\n links: html ? htmlLinks(html) : [],\n codes: html ? extractCodes(visibleText(html)) : [],\n images: html ? htmlImages(html) : [],\n },\n text: {\n body: text,\n links: text ? textLinks(text) : [],\n codes: text ? extractCodes(text) : [],\n },\n attachments: email.attachments.map((attachment, index) => ({\n id: `${email.id}-${index}`,\n contentType: attachment.contentType ?? 'application/octet-stream',\n fileName: attachment.filename ?? '',\n contentId: null,\n length: attachment.size ?? 0,\n url: '',\n })),\n metadata: {\n headers: [\n { field: 'From', value: email.fromName ? `${email.fromName} <${email.from}>` : email.from },\n { field: 'To', value: email.to.join(', ') },\n ...(email.cc.length ? [{ field: 'Cc', value: email.cc.join(', ') }] : []),\n { field: 'Subject', value: email.subject ?? '' },\n { field: 'Date', value: new Date(email.receivedAt).toUTCString() },\n ],\n ehlo: null,\n mailFrom: email.from,\n rcptTo: addresses([...email.to, ...email.cc, ...email.bcc]),\n },\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Request plumbing\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction invalid(field: string, description: string): EmulationResponse {\n return { status: 400, body: { errors: [{ field, detail: [{ description }] }] } };\n}\n\n/** Basic auth with the API key as the user name; any non-empty key is accepted. */\nfunction authorized(req: EmulationRequest): boolean {\n const match = /^Basic\\s+(\\S+)$/i.exec(req.headers.authorization ?? '');\n if (!match) return false;\n const decoded = Buffer.from(match[1]!, 'base64').toString('utf-8');\n return decoded.split(':')[0]!.length > 0;\n}\n\n/**\n * Wrap a handler: answer only HTTPS for mailosaur.com, and require Basic auth\n * like the real API. The plugin's routes are shared by every provider host, so\n * elsewhere these paths stay not-emulated. HTTPS only, because the emulator's\n * TLS listener is reached solely through the sandbox's /etc/hosts entry; its\n * plain-HTTP listener is the copy's public `emulation` port, where a forged\n * `Host: mailosaur.com` must not read the app's mail.\n */\nfunction onMailosaur(\n handler: (req: EmulationRequest, ctx: EmailCtx) => EmulationResponse\n): (req: EmulationRequest, ctx: EmailCtx) => EmulationResponse | null {\n return (req, ctx) => {\n if (req.url.protocol !== 'https:' || req.url.hostname.toLowerCase() !== MAILOSAUR_API_HOST) return null;\n if (!authorized(req)) return { status: 401, body: '' };\n return handler(req, ctx);\n };\n}\n\ntype ListQuery = { server: string; page: number; itemsPerPage: number; receivedAfter: number | null; received: boolean };\n\ntype Parsed<T> = { ok: true; value: T } | { ok: false; response: EmulationResponse };\n\nfunction rejected(field: string, description: string): { ok: false; response: EmulationResponse } {\n return { ok: false, response: invalid(field, description) };\n}\n\n/** The list/search query string; `page`, `itemsPerPage` and `dir` are what the SDK forwards from its options. */\nfunction listQuery(req: EmulationRequest): Parsed<ListQuery> {\n const params = req.url.searchParams;\n const server = params.get('server');\n if (!server) return rejected('server', 'The server field is required.');\n const page = Number(params.get('page') ?? 0);\n const itemsPerPage = Number(params.get('itemsPerPage') ?? DEFAULT_ITEMS_PER_PAGE);\n if (!Number.isInteger(page) || page < 0) return rejected('page', 'Page must be a non-negative integer.');\n if (!Number.isInteger(itemsPerPage) || itemsPerPage < 1 || itemsPerPage > MAX_ITEMS_PER_PAGE) {\n return rejected('itemsPerPage', `Items per page must be between 1 and ${MAX_ITEMS_PER_PAGE}.`);\n }\n // The SDK appends the ISO date unencoded, so a `+hh:mm` offset arrives as a space.\n const receivedAfterRaw = params.get('receivedAfter');\n let receivedAfter: number | null = null;\n if (receivedAfterRaw) {\n receivedAfter = Date.parse(receivedAfterRaw.replace(/ /g, '+'));\n if (Number.isNaN(receivedAfter)) return rejected('receivedAfter', 'Received after must be a date.');\n }\n const dir = params.get('dir') ?? 'Received';\n if (dir !== 'Received' && dir !== 'Sent') return rejected('dir', 'Direction must be Sent or Received.');\n return { ok: true, value: { server: server.toLowerCase(), page, itemsPerPage, receivedAfter, received: dir === 'Received' } };\n}\n\nfunction listed(ctx: EmailCtx, query: ListQuery, predicate: (email: CapturedEmail) => boolean) {\n // Captured mail is mail the app sent INTO Mailosaur: every message is a received one.\n const matches = query.received\n ? inbox(ctx).filter(\n (entry) =>\n entry.server === query.server &&\n (query.receivedAfter === null || Date.parse(entry.email.receivedAt) >= query.receivedAfter) &&\n predicate(entry.email)\n )\n : [];\n const start = query.page * query.itemsPerPage;\n return {\n status: 200,\n headers: { 'x-ms-delay': String(POLL_DELAY_MS) },\n body: { items: matches.slice(start, start + query.itemsPerPage).map(messageSummary) },\n };\n}\n\nconst CRITERIA_FIELDS = ['sentFrom', 'sentTo', 'subject', 'body'] as const;\n\nfunction criteriaPredicate(criteria: Record<string, unknown>): Parsed<(email: CapturedEmail) => boolean> {\n const checks: Array<(email: CapturedEmail) => boolean> = [];\n for (const field of CRITERIA_FIELDS) {\n const raw = criteria[field];\n if (raw === undefined || raw === null || raw === '') continue;\n if (typeof raw !== 'string') return rejected(field, `${field} must be a string.`);\n const value = raw.toLowerCase();\n if (field === 'sentFrom') checks.push((email) => email.from === value);\n if (field === 'sentTo') checks.push((email) => [...email.to, ...email.cc, ...email.bcc].includes(value));\n if (field === 'subject') checks.push((email) => (email.subject ?? '').toLowerCase().includes(value));\n if (field === 'body') {\n checks.push(\n (email) =>\n (email.text ?? '').toLowerCase().includes(value) || (email.html ?? '').toLowerCase().includes(value)\n );\n }\n }\n if (checks.length === 0) return rejected('criteria', 'Please provide at least one search criteria.');\n const match = criteria.match ?? 'ALL';\n if (match !== 'ALL' && match !== 'ANY') return rejected('match', 'Match must be ALL or ANY.');\n const value =\n match === 'ALL'\n ? (email: CapturedEmail) => checks.every((check) => check(email))\n : (email: CapturedEmail) => checks.some((check) => check(email));\n return { ok: true, value };\n}\n\nfunction server(ctx: EmailCtx, id: string) {\n const messages = inbox(ctx).filter((entry) => entry.server === id).length;\n return { id, name: id, users: [], messages };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Handlers\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** GET /api/messages?server= */\nexport const handleListMessages = onMailosaur((req, ctx) => {\n const query = listQuery(req);\n if (!query.ok) return query.response;\n return listed(ctx, query.value, () => true);\n});\n\n/** POST /api/messages/search?server= with `{ sentFrom, sentTo, subject, body, match }`. */\nexport const handleSearchMessages = onMailosaur((req, ctx) => {\n const query = listQuery(req);\n if (!query.ok) return query.response;\n const parsed = safeParseJson(req.body);\n if (!parsed.ok || !isRecord(parsed.data)) return invalid('criteria', 'The request body must be a JSON object.');\n const predicate = criteriaPredicate(parsed.data);\n if (!predicate.ok) return predicate.response;\n return listed(ctx, query.value, predicate.value);\n});\n\n/** GET /api/messages/:id */\nexport const handleGetMessage = onMailosaur((req, ctx) => {\n const found = findMessage(ctx, req.params.id!);\n return found ? { status: 200, body: message(found) } : { status: 404, body: '' };\n});\n\n/** DELETE /api/messages/:id: hides it from every server inbox it was in. */\nexport const handleDeleteMessage = onMailosaur((req, ctx) => {\n const id = req.params.id!;\n const entries = inbox(ctx).filter((entry) => entry.email.id === id);\n if (entries.length === 0) return { status: 404, body: '' };\n for (const entry of entries) ctx.state.mailosaurHidden.add(hiddenKey(entry.server, id));\n return { status: 204 };\n});\n\n/** DELETE /api/messages?server=: empties one server's inbox. */\nexport const handleDeleteAllMessages = onMailosaur((req, ctx) => {\n const id = req.url.searchParams.get('server')?.toLowerCase();\n if (!id) return invalid('server', 'The server field is required.');\n for (const entry of inbox(ctx)) {\n if (entry.server === id) ctx.state.mailosaurHidden.add(hiddenKey(id, entry.email.id));\n }\n return { status: 204 };\n});\n\n/** GET /api/servers: every server some captured email was addressed to, by name. */\nexport const handleListServers = onMailosaur((_req, ctx) => {\n const ids = new Set(ctx.state.sentEmails.flatMap(serversOf));\n return { status: 200, body: { items: [...ids].sort().map((id) => server(ctx, id)) } };\n});\n\n/** GET /api/servers/:id: any well-formed id is a server, empty until mail arrives. */\nexport const handleGetServer = onMailosaur((req, ctx) => {\n const id = req.params.id!.toLowerCase();\n return SERVER_ID.test(id) ? { status: 200, body: server(ctx, id) } : { status: 404, body: '' };\n});\n","/**\n * Shared email emulation types.\n *\n * @module\n */\n\nimport { z } from 'zod';\nimport type { PluginContext } from '../../plugin.js';\n\nexport type EmailProvider = 'ses' | 'sendgrid' | 'resend' | 'postmark' | 'mailgun';\n\n/** Zod schema of a definition's `emulation.email` block. */\nexport const emailConfigSchema = z.object({\n /** AWS SES regions whose API hosts to intercept (default ['us-east-1']). */\n sesRegions: z.array(z.string()).optional(),\n /** Extra custom hosts to intercept (e.g. a self-hosted provider API). */\n extraDomains: z.array(z.string()).optional(),\n /** Present: also serve Mailosaur's read API on mailosaur.com from the captured mail. */\n mailosaur: z.strictObject({}).optional(),\n});\nexport type EmailEmuConfig = z.infer<typeof emailConfigSchema>;\n\n/** Normalized capture of one outbound email, provider-agnostic. */\nexport interface CapturedEmail {\n /** Stable per-send id, used as the inbox dedup key (messageId). */\n id: string;\n provider: EmailProvider;\n from: string;\n fromName?: string;\n to: string[];\n cc: string[];\n bcc: string[];\n subject: string | null;\n text: string | null;\n html: string | null;\n /** Selected provider headers, with sensitive values redacted. */\n headers: Record<string, string>;\n attachments: Array<{ filename?: string; contentType?: string; size?: number }>;\n /** ISO-8601 capture time. */\n receivedAt: string;\n}\n\n/** Zod schema mirroring `CapturedEmail`, for validating operation outputs. */\nexport const capturedEmailSchema = z.object({\n id: z.string(),\n provider: z.enum(['ses', 'sendgrid', 'resend', 'postmark', 'mailgun']),\n from: z.string(),\n fromName: z.string().optional(),\n to: z.array(z.string()),\n cc: z.array(z.string()),\n bcc: z.array(z.string()),\n subject: z.string().nullable(),\n text: z.string().nullable(),\n html: z.string().nullable(),\n headers: z.record(z.string(), z.string()),\n attachments: z.array(\n z.object({\n filename: z.string().optional(),\n contentType: z.string().optional(),\n size: z.number().optional(),\n })\n ),\n receivedAt: z.string(),\n});\n\n/** Fixture is intentionally empty; there is no seed data, only captured state. */\nexport const emailFixtureSchema = z.object({}).passthrough();\nexport type EmailFixture = z.infer<typeof emailFixtureSchema>;\n\nexport interface EmailState {\n /** Every email sent since boot or last reset, used as the assertion surface. */\n sentEmails: CapturedEmail[];\n /** `<server>/<message id>` pairs deleted through the Mailosaur API: hidden from that inbox only. */\n mailosaurHidden: Set<string>;\n}\n\nexport type EmailCtx = PluginContext<EmailFixture, EmailState>;\n","/**\n * Shared OIDC provider core.\n *\n * The authorize / token / userinfo / discovery / JWKS logic behind the\n * persona-backed OIDC emulators. A provider is an {@link OidcFlavor}: plain\n * data (label, issuer, endpoints) plus the claims it adds beyond the standard\n * set. Every declared persona is an account; codes, access tokens and refresh\n * tokens are each bound to one persona.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport { z } from 'zod';\nimport type { EmulationRequest, EmulationResponse, PluginContext } from '../plugin.js';\nimport { generateKeyPair, signIdToken, buildJwks, type EphemeralKeyPair } from './jwt.js';\nimport {\n GrantStore,\n identityForHint,\n personaIdentities,\n personaIdentitySchema,\n renderAccountChooser,\n type PersonaDeclaration,\n type PersonaIdentity,\n} from '../persona-identity.js';\n\nexport interface OidcFixture {\n identities: PersonaIdentity[];\n}\n\nexport const oidcFixtureSchema = z.object({ identities: z.array(personaIdentitySchema).min(1) });\n\n/** Each declared persona is an account. Throws when there are none. */\nexport function oidcFixture(personas: Record<string, PersonaDeclaration>): OidcFixture {\n return { identities: personaIdentities(personas) };\n}\n\nexport interface OidcState {\n keyPair: EphemeralKeyPair;\n identities: PersonaIdentity[];\n /** Authorization codes (`emulated_code_`), single use. */\n grants: GrantStore;\n /** `emulated_at_<uuid>` -> sub */\n accessTokens: Map<string, string>;\n /** `emulated_rt_<uuid>` -> sub */\n refreshTokens: Map<string, string>;\n detectedClientId: string | null;\n /** Pre-computed JWKS response (key pair is stable for the container lifetime) */\n jwksResponse: object;\n}\n\nexport type OidcContext = PluginContext<OidcFixture, OidcState>;\n\ninterface OidcEndpoints {\n authorization_endpoint: string;\n token_endpoint: string;\n userinfo_endpoint: string;\n jwks_uri: string;\n}\n\n/** What differs between providers; everything else is shared. */\nexport interface OidcFlavor {\n /** Provider name shown on the account chooser. */\n label: string;\n issuer(ctx: OidcContext): string;\n /** Absolute URLs: the chooser is also served while the browser's page URL is the app's. */\n endpoints(ctx: OidcContext): OidcEndpoints;\n /** Claims added to the id_token and userinfo beyond the standard set: claim name -> value for an identity. */\n extraClaims: Record<string, (identity: PersonaIdentity) => unknown>;\n}\n\nexport function initializeOidcState(fixture: OidcFixture, clientId: string | null): OidcState {\n const keyPair = generateKeyPair();\n return {\n keyPair,\n identities: fixture.identities,\n grants: new GrantStore(),\n accessTokens: new Map(),\n refreshTokens: new Map(),\n detectedClientId: clientId,\n jwksResponse: buildJwks(keyPair),\n };\n}\n\nconst EMULATED_ACCESS_TOKEN_PREFIX = 'emulated_at_';\nconst EMULATED_REFRESH_TOKEN_PREFIX = 'emulated_rt_';\n\nfunction isHttpUrl(value: string): boolean {\n try {\n const { protocol } = new URL(value);\n return protocol === 'http:' || protocol === 'https:';\n } catch {\n return false;\n }\n}\n\n/** 302 back to the app with a code, 200 account chooser, or 400 without redirect_uri. */\nexport function authorize(flavor: OidcFlavor, ctx: OidcContext, url: URL): EmulationResponse {\n const redirectUri = url.searchParams.get('redirect_uri');\n if (!redirectUri || !isHttpUrl(redirectUri)) {\n ctx.log('warn', `Authorize rejected: redirect_uri is missing or not an http(s) URL`);\n return {\n status: 400,\n headers: { 'content-type': 'text/plain' },\n body: 'Invalid OAuth request: redirect_uri must be an http(s) URL',\n };\n }\n\n const loginHint = url.searchParams.get('login_hint');\n const identity = identityForHint(ctx.state.identities, loginHint);\n if (!identity) {\n if (loginHint) ctx.log('info', `login_hint ${loginHint} matched no persona; showing the chooser`);\n const authorizeUrl = flavor.endpoints(ctx).authorization_endpoint;\n return {\n status: 200,\n headers: { 'content-type': 'text/html; charset=utf-8' },\n body: renderAccountChooser({\n provider: flavor.label,\n accounts: ctx.state.identities.map((account) => {\n const query = new URLSearchParams(url.searchParams);\n query.set('login_hint', account.email);\n return {\n label: account.name,\n email: account.email,\n href: `${authorizeUrl}?${query.toString()}`,\n };\n }),\n }),\n };\n }\n\n const code = ctx.state.grants.issue({\n identity,\n clientId: url.searchParams.get('client_id'),\n redirectUri,\n nonce: url.searchParams.get('nonce'),\n });\n const callback = new URL(redirectUri);\n callback.searchParams.set('code', code);\n const state = url.searchParams.get('state');\n if (state) callback.searchParams.set('state', state);\n return { status: 302, headers: { location: callback.toString() }, body: '' };\n}\n\nfunction invalidGrant(description: string): EmulationResponse {\n return { status: 400, body: { error: 'invalid_grant', error_description: description } };\n}\n\nfunction identityBySub(ctx: OidcContext, sub: string | undefined): PersonaIdentity | null {\n return ctx.state.identities.find((identity) => identity.sub === sub) ?? null;\n}\n\nfunction bearerToken(req: EmulationRequest): string | undefined {\n const header = req.headers['authorization'] ?? '';\n return /^bearer\\s+(.+)$/i.exec(header)?.[1]?.trim();\n}\n\n/** The client_id from `Authorization: Basic base64(id:secret)` (RFC 6749 §2.3.1); malformed means absent. */\nfunction basicClientId(req: EmulationRequest): string | null {\n const header = req.headers['authorization'] ?? '';\n const credentials = /^basic\\s+(.+)$/i.exec(header)?.[1];\n if (!credentials) return null;\n const decoded = Buffer.from(credentials.trim(), 'base64').toString('utf8');\n const separator = decoded.indexOf(':');\n if (separator <= 0) return null;\n try {\n return decodeURIComponent(decoded.slice(0, separator).replace(/\\+/g, ' '));\n } catch {\n return null;\n }\n}\n\nfunction standardClaims(identity: PersonaIdentity) {\n return {\n sub: identity.sub,\n email: identity.email,\n email_verified: identity.emailVerified,\n name: identity.name,\n };\n}\n\n/** Evaluates the flavour's extra claims for one identity. */\nfunction evaluateExtraClaims(flavor: OidcFlavor, identity: PersonaIdentity): Record<string, unknown> {\n return Object.fromEntries(Object.entries(flavor.extraClaims).map(([name, claim]) => [name, claim(identity)]));\n}\n\nexport function handleToken(flavor: OidcFlavor, req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n const params = new URLSearchParams(req.body ?? '');\n const grantType = params.get('grant_type');\n // Plan Decision 14: the client secret is never checked.\n // The body client_id wins over HTTP Basic.\n const requestClientId = params.get('client_id') ?? basicClientId(req);\n const clientId = requestClientId ?? ctx.state.detectedClientId ?? 'unknown';\n\n // Track client_id for future requests\n if (!ctx.state.detectedClientId && clientId !== 'unknown') {\n ctx.state.detectedClientId = clientId;\n }\n\n if (grantType === 'authorization_code') {\n const grant = ctx.state.grants.take(params.get('code') ?? '');\n if (!grant) {\n ctx.log('warn', 'Token exchange with an unknown or already redeemed code');\n return invalidGrant('Invalid authorization code');\n }\n const redirectUri = params.get('redirect_uri');\n if (\n redirectUri !== grant.redirectUri ||\n (requestClientId && grant.clientId && requestClientId !== grant.clientId)\n ) {\n ctx.log('warn', 'Token exchange rejected: redirect_uri or client_id differs from the authorize request');\n return invalidGrant('Authorization code was issued for a different client or redirect_uri');\n }\n const { identity } = grant;\n const audience = requestClientId ?? grant.clientId ?? ctx.state.detectedClientId ?? 'unknown';\n\n const accessToken = `${EMULATED_ACCESS_TOKEN_PREFIX}${crypto.randomUUID()}`;\n const refreshToken = `${EMULATED_REFRESH_TOKEN_PREFIX}${crypto.randomUUID()}`;\n ctx.state.accessTokens.set(accessToken, identity.sub);\n ctx.state.refreshTokens.set(refreshToken, identity.sub);\n\n const idToken = signIdToken(\n {\n ...evaluateExtraClaims(flavor, identity),\n ...standardClaims(identity),\n iss: flavor.issuer(ctx),\n aud: audience,\n azp: audience,\n nonce: grant.nonce ?? undefined,\n },\n ctx.state.keyPair\n );\n\n ctx.log('info', `Issued tokens for ${identity.email}`);\n\n return {\n status: 200,\n body: {\n access_token: accessToken,\n token_type: 'Bearer',\n expires_in: 3600,\n refresh_token: refreshToken,\n scope: 'openid email profile',\n id_token: idToken,\n },\n };\n }\n\n if (grantType === 'refresh_token') {\n const sub = ctx.state.refreshTokens.get(params.get('refresh_token') ?? '');\n const identity = identityBySub(ctx, sub);\n if (!identity) {\n ctx.log('warn', 'Token refresh with an unknown refresh token');\n return invalidGrant('Invalid refresh token');\n }\n\n const accessToken = `${EMULATED_ACCESS_TOKEN_PREFIX}${crypto.randomUUID()}`;\n ctx.state.accessTokens.set(accessToken, identity.sub);\n ctx.log('info', `Refreshed token for ${identity.email}`);\n\n return {\n status: 200,\n body: {\n access_token: accessToken,\n token_type: 'Bearer',\n expires_in: 3600,\n scope: 'openid email profile',\n },\n };\n }\n\n return { status: 400, body: { error: 'unsupported_grant_type' } };\n}\n\nexport function handleUserinfo(flavor: OidcFlavor, req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n const token = bearerToken(req);\n const identity = identityBySub(ctx, token ? ctx.state.accessTokens.get(token) : undefined);\n if (!identity) return { status: 401, body: { error: 'invalid_token' } };\n return { status: 200, body: { ...evaluateExtraClaims(flavor, identity), ...standardClaims(identity) } };\n}\n\nexport function handleDiscovery(flavor: OidcFlavor, _req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n return {\n status: 200,\n body: {\n issuer: flavor.issuer(ctx),\n ...flavor.endpoints(ctx),\n response_types_supported: ['code'],\n grant_types_supported: ['authorization_code', 'refresh_token'],\n subject_types_supported: ['public'],\n id_token_signing_alg_values_supported: ['RS256'],\n scopes_supported: ['openid', 'email', 'profile'],\n token_endpoint_auth_methods_supported: ['client_secret_post', 'client_secret_basic', 'none'],\n // Advertised so PKCE-sending libraries proceed; the challenge is never verified (plan Decision 13).\n code_challenge_methods_supported: ['S256', 'plain'],\n claims_supported: [\n 'sub', 'iss', 'aud', 'iat', 'exp', 'nonce', 'email', 'email_verified', 'name',\n ...Object.keys(flavor.extraClaims),\n ],\n },\n };\n}\n\nexport function handleJwks(_req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n return {\n status: 200,\n headers: { 'cache-control': 'public, max-age=3600' },\n body: ctx.state.jwksResponse,\n };\n}\n","/**\n * JWT Utilities for OAuth Emulation\n *\n * Generates ephemeral RSA key pairs and signs JWTs for OpenID Connect id_tokens.\n * The corresponding public key is served via JWKS endpoints so apps that verify\n * JWT signatures via OIDC discovery will succeed.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Key Management\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface EphemeralKeyPair {\n privateKey: crypto.KeyObject;\n publicKey: crypto.KeyObject;\n kid: string;\n}\n\n/** Generate an RSA-2048 key pair for JWT signing. Called once on startup. */\nexport function generateKeyPair(): EphemeralKeyPair {\n const { privateKey, publicKey } = crypto.generateKeyPairSync('rsa', {\n modulusLength: 2048,\n });\n const kid = crypto.randomUUID();\n return { privateKey, publicKey, kid };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// JWT Signing\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface IdTokenClaims {\n iss: string;\n aud: string;\n sub: string;\n email: string;\n email_verified?: boolean;\n name: string;\n given_name?: string;\n family_name?: string;\n picture?: string;\n nonce?: string;\n [key: string]: unknown;\n}\n\n/** Sign a JWT id_token with the ephemeral key pair. */\nexport function signIdToken(\n claims: IdTokenClaims,\n keyPair: EphemeralKeyPair\n): string {\n const now = Math.floor(Date.now() / 1000);\n\n const header = {\n alg: 'RS256',\n typ: 'JWT',\n kid: keyPair.kid,\n };\n\n const payload = {\n ...claims,\n iat: now,\n exp: now + 3600,\n };\n\n const headerB64 = base64url(JSON.stringify(header));\n const payloadB64 = base64url(JSON.stringify(payload));\n const signingInput = `${headerB64}.${payloadB64}`;\n\n const signature = crypto.sign('sha256', Buffer.from(signingInput), keyPair.privateKey);\n const signatureB64 = base64url(signature);\n\n return `${signingInput}.${signatureB64}`;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// JWKS\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Build a JWKS response containing the public key. */\nexport function buildJwks(keyPair: EphemeralKeyPair): object {\n const jwk = keyPair.publicKey.export({ format: 'jwk' });\n return {\n keys: [\n {\n ...jwk,\n kid: keyPair.kid,\n alg: 'RS256',\n use: 'sig',\n },\n ],\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction base64url(input: string | Buffer): string {\n const buf = typeof input === 'string' ? Buffer.from(input) : input;\n return buf.toString('base64url');\n}\n","/**\n * Provider-neutral persona identities: persona -> OIDC-style identity, the\n * one-time authorization-code store and the server-rendered account chooser.\n * Providers (Google today) import this; nothing here is provider specific.\n *\n * @module\n */\n\nimport { createHash, randomUUID } from 'node:crypto';\nimport { z } from 'zod';\n\nexport type PersonaDeclaration = { email: string };\n\n/** One declared persona as an OIDC-style identity. Serialisable: it is the plugin fixture. */\nexport const personaIdentitySchema = z.object({\n persona: z.string(),\n /** Stable, derived from `persona` only. */\n sub: z.string(),\n email: z.string(),\n emailVerified: z.literal(true),\n /** = persona */\n name: z.string(),\n});\n\nexport type PersonaIdentity = z.infer<typeof personaIdentitySchema>;\n\n/** `sub` is 21 decimal digits (Google's shape) from sha256(\"cofactor-persona:\" + name). */\nexport function personaSub(persona: string): string {\n const hex = createHash('sha256').update(`cofactor-persona:${persona}`).digest('hex').slice(0, 32);\n return BigInt(`0x${hex}`).toString().slice(0, 21).padStart(21, '0');\n}\n\n/** Throws on an empty set: a provider with no accounts cannot sign anyone in. */\nexport function personaIdentities(\n personas: Record<string, PersonaDeclaration>\n): PersonaIdentity[] {\n const entries = Object.entries(personas);\n if (entries.length === 0) {\n throw new Error('at least one persona is required: each persona is a provider account');\n }\n return entries.map(([persona, { email }]) => ({\n persona,\n sub: personaSub(persona),\n email,\n emailVerified: true,\n name: persona,\n }));\n}\n\n/** Case-insensitive email match; null for no/unknown hint (the caller shows the chooser). */\nexport function identityForHint(\n identities: PersonaIdentity[],\n hint: string | null\n): PersonaIdentity | null {\n if (!hint) return null;\n const wanted = hint.toLowerCase();\n return identities.find((identity) => identity.email.toLowerCase() === wanted) ?? null;\n}\n\nexport type AuthorizationGrant = {\n identity: PersonaIdentity;\n clientId: string | null;\n redirectUri: string;\n nonce: string | null;\n};\n\nconst CODE_PREFIX = 'emulated_code_';\n\n/** Issued-code store: `take` removes the grant (single use). */\nexport class GrantStore {\n private readonly grants = new Map<string, AuthorizationGrant>();\n\n issue(grant: AuthorizationGrant): string {\n const code = `${CODE_PREFIX}${randomUUID()}`;\n this.grants.set(code, grant);\n return code;\n }\n\n take(code: string): AuthorizationGrant | null {\n const grant = this.grants.get(code) ?? null;\n this.grants.delete(code);\n return grant;\n }\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\n/** Server-rendered chooser. `accounts[i].href` is the authorize URL with login_hint set. All values HTML-escaped. */\nexport function renderAccountChooser(input: {\n provider: string;\n accounts: { label: string; email: string; href: string }[];\n}): string {\n const provider = escapeHtml(input.provider);\n const items = input.accounts\n .map(\n (account) =>\n `<li><a href=\"${escapeHtml(account.href)}\"><strong>${escapeHtml(account.label)}</strong><br><span>${escapeHtml(account.email)}</span></a></li>`\n )\n .join('');\n return `<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Sign in with ${provider}</title><style>body{font-family:system-ui,sans-serif;max-width:24rem;margin:4rem auto;padding:0 1rem}ul{list-style:none;padding:0}li{border:1px solid #ccc;border-radius:.5rem;margin:.5rem 0}a{display:block;padding:.75rem 1rem;color:inherit;text-decoration:none}span{color:#555;font-size:.9rem}</style></head><body><h1>Choose an account</h1><p>to continue with ${provider} (sandbox emulator)</p><ul>${items}</ul></body></html>`;\n}\n","/**\n * Google OAuth 2.0 / OpenID Connect Emulation Plugin\n *\n * Emulates Google's OAuth authorization server for sandboxed apps.\n *\n * Every declared persona is a Google account. The authorize endpoint serves an\n * account chooser (or completes straight away for a matching `login_hint`);\n * codes, access tokens and refresh tokens are each bound to one persona.\n *\n * Sandbox-side: authorize, token exchange (POST /token), userinfo endpoint,\n * OIDC discovery, and JWKS endpoint. The Cofactor browser reaches authorize\n * through the control plane (`controlReads`).\n *\n * @module\n */\n\nimport type { EmulationPlugin, EmulationRequest, EmulationResponse } from '../plugin.js';\nimport {\n authorize,\n handleDiscovery,\n handleJwks,\n handleToken,\n handleUserinfo,\n initializeOidcState,\n oidcFixtureSchema,\n type OidcContext,\n type OidcFixture,\n type OidcFlavor,\n type OidcState,\n} from './oidc-core.js';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface GoogleOAuthConfig {\n /** The app's OAuth client ID (used in aud/azp claims). Optional — extracted from requests if not set. */\n clientId?: string;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Constants\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const GOOGLE_OAUTH_DOMAINS = [\n 'accounts.google.com',\n 'oauth2.googleapis.com',\n 'www.googleapis.com',\n 'openidconnect.googleapis.com',\n];\n\nconst GOOGLE_ISSUER = 'https://accounts.google.com';\n\nconst googleFlavor: OidcFlavor = {\n label: 'Google',\n issuer: () => GOOGLE_ISSUER,\n endpoints: () => ({\n authorization_endpoint: `${GOOGLE_ISSUER}/o/oauth2/v2/auth`,\n token_endpoint: 'https://oauth2.googleapis.com/token',\n userinfo_endpoint: 'https://www.googleapis.com/oauth2/v3/userinfo',\n jwks_uri: `${GOOGLE_ISSUER}/oauth2/v3/certs`,\n }),\n extraClaims: { given_name: (identity) => identity.name },\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Plugin\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const googleOAuthPlugin: EmulationPlugin<GoogleOAuthConfig, OidcFixture, OidcState> = {\n id: 'google-oauth',\n name: 'Google OAuth 2.0',\n version: '1.0.0',\n domains: GOOGLE_OAUTH_DOMAINS,\n needsBrowserIntercept: false,\n\n // ── Sandbox-side routes ──────────────────────────────────────────────────\n\n routes: [\n // Authorize (Host: accounts.google.com; in-VM clients reach it over :443)\n { method: 'GET', path: '/o/oauth2/v2/auth', handler: handleAuthorizeRoute },\n { method: 'GET', path: '/o/oauth2/auth', handler: handleAuthorizeRoute },\n\n // Token exchange\n {\n method: 'POST',\n path: '/token',\n handler: handleTokenExchange,\n },\n {\n method: 'POST',\n path: '/oauth2/v4/token',\n handler: handleTokenExchange,\n },\n\n // Userinfo\n {\n method: 'GET',\n path: '/oauth2/v3/userinfo',\n handler: handleUserinfoRoute,\n },\n {\n method: 'GET',\n path: '/oauth2/v2/userinfo',\n handler: handleUserinfoRoute,\n },\n {\n method: 'GET',\n path: '/userinfo/v2/me',\n handler: handleUserinfoRoute,\n },\n {\n method: 'GET',\n path: '/v1/userinfo',\n handler: handleUserinfoRoute,\n },\n\n // OIDC Discovery\n {\n method: 'GET',\n path: '/.well-known/openid-configuration',\n handler: handleOidcDiscovery,\n },\n\n // JWKS\n {\n method: 'GET',\n path: '/oauth2/v3/certs',\n handler: handleJwks,\n },\n ],\n\n // ── Control-plane reads ──────────────────────────────────────────────────\n\n // Guarded by the derived authorize key (control-plane.ts), for the Cofactor browser.\n controlReads: [{ path: 'authorize', handler: handleAuthorizeRoute }],\n\n fixtureSchema: oidcFixtureSchema,\n\n // ── Initialization ───────────────────────────────────────────────────────\n\n initialize(config, fixture) {\n return initializeOidcState(fixture, config.clientId ?? null);\n },\n};\n\nfunction handleAuthorizeRoute(req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n return authorize(googleFlavor, ctx, req.url);\n}\n\nfunction handleTokenExchange(req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n return handleToken(googleFlavor, req, ctx);\n}\nfunction handleUserinfoRoute(req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n return handleUserinfo(googleFlavor, req, ctx);\n}\nfunction handleOidcDiscovery(req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n return handleDiscovery(googleFlavor, req, ctx);\n}\n","/**\n * Esri ArcGIS REST Emulation Plugin\n *\n * Emulates the slice of the ArcGIS REST API a third-party connector uses to\n * query and edit hosted feature layers: the token endpoint, the portal health\n * check, the signed-in user, FeatureServer/layer metadata, `query`, and `applyEdits`.\n *\n * Host-routed: one configured host serves every tenant. A tenant is the first\n * path segment (`https://<host>/<tenant>/arcgis/rest/services`), where ArcGIS\n * Online puts its org id. State is per tenant, in memory, seeded through the\n * `seed-layer` operation, and dropped when idle past `tenantTtlMinutes` or older\n * than `tenantMaxAgeMinutes` (swept lazily on each request and seed, no timers).\n *\n * Like real ArcGIS, errors are HTTP 200 with an `{ error: { code, ... } }` body.\n * Paths are as forgiving as real ArcGIS: resources take a trailing slash, and an\n * operation (`generateToken`, `query`, ...) ignores any path after it. Every\n * request that matches nothing gets ArcGIS Online's `Invalid URL` answer from a\n * catch-all route and is recorded by the proxy, so the traffic of a real\n * connector shows what to implement next.\n *\n * Tokens and the credential are global, not per tenant: isolation between\n * tenants rests on the unguessable tenant name.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport type { EmulationPlugin, EmulationRoute } from '../../plugin.js';\nimport { tokensMatch } from '../../token-match.js';\nimport { EsriError, badParameter, errorResponse } from './errors.js';\nimport {\n applyLayerEdits,\n parseFeatures,\n parseIds,\n withoutCredentials,\n} from './layers.js';\nimport { flag, ok, readParams } from './params.js';\nimport { esriOperations } from './operations.js';\nimport { CURRENT_VERSION, layerMetadata, queryLayer, serviceMetadata } from './query.js';\nimport {\n configSchema,\n findLayer,\n guarded,\n logEdit,\n storeToken,\n presentedToken,\n sweep,\n type EsriConfig,\n type EsriFixture,\n type EsriState,\n type Handler,\n} from './tenants.js';\n\nexport type { EsriConfig, EsriFixture, EsriState };\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Routes\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst SERVICES = '/:tenant/arcgis/rest/services';\n/** The emulated portal's org id (`portals/self` id, the user's `orgId`). */\nconst ORG_ID = 'emulatedportal';\nconst FEATURE_SERVER = `${SERVICES}/:service/FeatureServer`;\nconst LAYER = `${FEATURE_SERVER}/:layer`;\n/** The longest token lifetime ArcGIS grants (14 days). */\nconst MAX_TOKEN_MINUTES = 20_160;\n\ntype EsriRoute = EmulationRoute<EsriFixture, EsriState>;\n\n/** A resource: either verb, with or without a trailing slash. */\nfunction resource(path: string, handler: Handler): EsriRoute[] {\n return [path, `${path}/`].flatMap((p): EsriRoute[] => [\n { method: 'GET', path: p, handler },\n { method: 'POST', path: p, handler },\n ]);\n}\n\n/** An operation: either verb, and like real ArcGIS any path after it is ignored (`query/`, `generateToken/x`). */\nfunction operation(path: string, handler: Handler): EsriRoute[] {\n return [\n { method: 'GET', path: `${path}/*`, handler },\n { method: 'POST', path: `${path}/*`, handler },\n ];\n}\n\nconst generateToken: Handler = (req, ctx) => {\n sweep(ctx.state);\n const p = readParams(req);\n const { config } = ctx.state;\n // Both comparisons always run so timing does not reveal which one failed.\n const userOk = tokensMatch(p.get('username') ?? '', config.username);\n const passOk = tokensMatch(p.get('password') ?? '', config.password);\n if (!userOk || !passOk) {\n return errorResponse(new EsriError(400, 'Unable to generate token.', ['Invalid username or password.']));\n }\n let ttlSeconds = config.tokenTtlSeconds;\n const expiration = p.get('expiration');\n if (expiration !== undefined && expiration !== '') {\n const minutes = Number(expiration);\n if (!Number.isFinite(minutes) || minutes <= 0) return errorResponse(badParameter('expiration'));\n ttlSeconds = Math.min(minutes, MAX_TOKEN_MINUTES) * 60;\n }\n const token = crypto.randomBytes(162).toString('base64url');\n const expires = Date.now() + ttlSeconds * 1000;\n storeToken(ctx.state, token, expires);\n return ok(p, { token, expires, ssl: true });\n};\n\nconst tokenViaGet: Handler = () =>\n errorResponse(new EsriError(405, 'Method not supported.', [], 'GWM_0005'));\n\nconst portalSelf: Handler = (req, ctx) =>\n ok(readParams(req), {\n id: ORG_ID,\n name: 'Emulated ArcGIS Portal',\n isPortal: false,\n urlKey: 'emulator',\n customBaseUrl: 'arcgis.com',\n portalHostname: ctx.state.config.host,\n supportsHostedServices: true,\n });\n\n/**\n * The signed-in user; a connection test can probe it to check its token. The errors match ArcGIS Online\n * (probed); the user is a minimal subset of its documented shape, extended when a client needs more.\n */\nconst communitySelf: Handler = (req, ctx) => {\n sweep(ctx.state);\n const p = readParams(req);\n const token = presentedToken(req, p);\n if (!token) return errorResponse(new EsriError(400, 'Not logged in.', [], 'COM_0019'));\n if (!ctx.state.tokens.has(token)) return errorResponse(new EsriError(498, 'Invalid token.'));\n const { username } = ctx.state.config;\n return ok(p, {\n username,\n id: 'emulateduser',\n fullName: 'Emulated User',\n email: `${username}@example.com`,\n orgId: ORG_ID,\n role: 'org_admin',\n disabled: false,\n });\n};\n\nconst restInfo: Handler = (req, ctx) =>\n ok(readParams(req), {\n currentVersion: CURRENT_VERSION,\n fullVersion: '11.2.0',\n owningSystemUrl: `https://${ctx.state.config.host}`,\n authInfo: {\n isTokenBasedSecurity: true,\n tokenServicesUrl: `https://${ctx.state.config.host}/sharing/rest/generateToken`,\n },\n });\n\nconst listServices = guarded((call) =>\n ok(call.p, {\n currentVersion: CURRENT_VERSION,\n folders: [],\n services: [...call.tenant.services.keys()].map((name) => ({ name, type: 'FeatureServer' })),\n })\n);\n\nconst getService = guarded((call) => {\n const layers = call.tenant.services.get(call.req.params['service']!);\n if (!layers) throw new EsriError(404, 'Service not found');\n return ok(call.p, serviceMetadata(layers));\n});\n\nconst getLayer = guarded((call) => ok(call.p, layerMetadata(findLayer(call))));\nconst queryHandler = guarded((call) => queryLayer(findLayer(call), call.p));\n\nconst applyEdits = guarded((call) => {\n const layer = findLayer(call);\n const { p } = call;\n const outcome = applyLayerEdits(\n layer,\n {\n adds: parseFeatures('adds', p.get('adds')),\n updates: parseFeatures('updates', p.get('updates')),\n deletes: parseIds('deletes', p.get('deletes')),\n },\n { useGlobalIds: flag(p, 'useGlobalIds'), rollbackOnFailure: flag(p, 'rollbackOnFailure', true) }\n );\n logEdit(call.tenant, {\n ts: new Date().toISOString(),\n source: 'connector',\n endpoint: 'applyEdits',\n service: call.req.params['service']!,\n layerId: layer.def.id,\n received: withoutCredentials(p.raw),\n results: outcome.results,\n rolledBack: !outcome.committed,\n });\n if (!outcome.committed) {\n return errorResponse(new EsriError(400, 'Unable to complete operation.', ['Operation rolled back.']));\n }\n return ok(p, outcome.results);\n});\n\n/** ArcGIS Online's answer to an unknown path. The request itself is in the proxy's log line and recorder. */\nconst catchAll: Handler = () => errorResponse(new EsriError(400, 'Invalid URL', [], 'GWM_0002'));\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Plugin\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const esriPlugin: EmulationPlugin<EsriConfig, EsriFixture, EsriState> = {\n id: 'esri',\n name: 'Esri ArcGIS REST API',\n version: '1.0.0',\n\n domains: (config) => [config.host.toLowerCase()],\n needsBrowserIntercept: false,\n\n routes: [\n // ── Token, portal health check, server info ─────────────────────────\n ...['', '/portal'].flatMap((prefix): EsriRoute[] => [\n // Not operation(): the token is POST only, a GET gets ArcGIS Online's refusal.\n { method: 'POST', path: `${prefix}/sharing/rest/generateToken/*`, handler: generateToken },\n { method: 'GET', path: `${prefix}/sharing/rest/generateToken/*`, handler: tokenViaGet },\n ...operation(`${prefix}/sharing/rest/portals/self`, portalSelf),\n ...operation(`${prefix}/sharing/rest/community/self`, communitySelf),\n ...operation(`${prefix}/sharing/rest/info`, restInfo),\n ]),\n ...resource('/arcgis/rest/info', restInfo),\n ...resource('/:tenant/arcgis/rest/info', restInfo),\n\n // ── Services, FeatureServer and layer metadata (token required) ─────\n ...resource(SERVICES, listServices),\n ...resource(FEATURE_SERVER, getService),\n ...resource(LAYER, getLayer),\n\n // ── Query and edits ─────────────────────────────────────────────────\n ...operation(`${LAYER}/query`, queryHandler),\n ...operation(`${LAYER}/applyEdits`, applyEdits),\n\n // ── Anything else: answered and recorded, so real traffic drives iteration\n { method: '*', path: '*', handler: catchAll },\n ],\n\n initialize(config) {\n return { config: configSchema.parse(config), tenants: new Map(), tokens: new Map() };\n },\n\n countActive(ctx, sinceMs) {\n sweep(ctx.state);\n return [...ctx.state.tenants.values()].filter((t) => t.touchedAt >= sinceMs).length;\n },\n\n controlReads: [\n {\n path: 'features',\n handler: (req, ctx) => {\n const q = req.url.searchParams;\n const layer = ctx.state.tenants\n .get(q.get('tenant') ?? '')\n ?.services.get(q.get('service') ?? '')\n ?.get(Number(q.get('layer')));\n if (!layer) return { status: 404, body: { error: 'Layer not found' } };\n return { status: 200, body: { features: layer.features } };\n },\n },\n {\n path: 'edits',\n handler: (req, ctx) => {\n const tenant = ctx.state.tenants.get(req.url.searchParams.get('tenant') ?? '');\n if (!tenant) return { status: 404, body: { error: 'Tenant not found' } };\n return { status: 200, body: { edits: tenant.edits } };\n },\n },\n ],\n\n operations: esriOperations,\n};\n","import { timingSafeEqual } from 'node:crypto';\n\n/** Constant-time bearer-token comparison. */\nexport function tokensMatch(provided: string, expected: string): boolean {\n const a = Buffer.from(provided);\n const b = Buffer.from(expected);\n if (a.length !== b.length) return false;\n return timingSafeEqual(a, b);\n}\n","/**\n * ArcGIS error envelope. Real ArcGIS answers errors as HTTP 200 with an `error` body.\n *\n * @module\n */\n\nimport type { EmulationResponse } from '../../plugin.js';\n\n/** Headers real ArcGIS Online sends on every JSON answer. */\nexport const JSON_HEADERS = {\n 'content-type': 'application/json;charset=utf-8',\n 'cache-control': 'no-cache',\n vary: 'Origin',\n 'x-content-type-options': 'nosniff',\n};\n\nexport class EsriError extends Error {\n constructor(\n readonly code: number,\n message: string,\n readonly details: string[] = [],\n /** ArcGIS Online's gateway code (`GWM_…`), sent only on the errors that carry one. */\n readonly messageCode?: string\n ) {\n super(message);\n }\n}\n\nexport function errorResponse(err: EsriError): EmulationResponse {\n // An absent messageCode is dropped when the body is serialized, as on real ArcGIS.\n return {\n status: 200,\n headers: JSON_HEADERS,\n body: { error: { code: err.code, messageCode: err.messageCode, message: err.message, details: err.details } },\n };\n}\n\nexport const badQuery = () =>\n new EsriError(400, 'Unable to complete operation.', ['Unable to perform query. Please check your parameters.']);\n\nexport const badParameter = (name: string) =>\n new EsriError(400, 'Unable to complete operation.', [`Invalid parameter: ${name}`]);\n","/**\n * Layer schema, features, and the edit semantics of applyEdits.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport { z } from 'zod';\nimport { isCredentialKey } from '../../credential-keys.js';\nimport { redactForLog } from '../../redact-json.js';\nimport { badParameter } from './errors.js';\nimport { parseDateLiteral, type Attributes } from './where.js';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Schema / State\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst fieldSchema = z.object({\n name: z.string().min(1),\n /** esriFieldType*, e.g. esriFieldTypeString */\n type: z.string().min(1),\n alias: z.string().optional(),\n nullable: z.boolean().default(true),\n editable: z.boolean().default(true),\n length: z.number().int().positive().optional(),\n});\ntype FieldDef = z.infer<typeof fieldSchema>;\n\nconst GEOMETRY_TYPES = [\n 'esriGeometryPoint',\n 'esriGeometryMultipoint',\n 'esriGeometryPolyline',\n 'esriGeometryPolygon',\n] as const;\n\nexport const layerDefSchema = z.object({\n id: z.number().int().nonnegative(),\n name: z.string().min(1),\n /** null makes the layer a table (no geometry). */\n geometryType: z.enum(GEOMETRY_TYPES).nullable(),\n fields: z.array(fieldSchema),\n objectIdField: z.string().min(1),\n globalIdField: z.string().min(1).optional(),\n maxRecordCount: z.number().int().positive().default(1000),\n});\nexport type LayerDef = z.infer<typeof layerDefSchema>;\n\nexport interface Feature {\n attributes: Attributes;\n geometry?: Record<string, unknown>;\n}\n\nexport interface LayerState {\n def: LayerDef;\n features: Feature[];\n nextObjectId: number;\n fieldsByLower: Map<string, FieldDef>;\n}\n\n/** One edit call as received, with what the emulator answered. */\nexport interface EditLogEntry {\n ts: string;\n /** `connector` for HTTP edits, `external` for the edit-feature operation. */\n source: 'connector' | 'external';\n endpoint: 'applyEdits' | 'edit-feature';\n service: string;\n layerId: number;\n /** Request params as received (credential keys removed). */\n received: Record<string, string>;\n results: unknown;\n rolledBack: boolean;\n}\n\nexport function createLayerState(def: LayerDef): LayerState {\n return {\n def,\n features: [],\n nextObjectId: 1,\n fieldsByLower: new Map(def.fields.map((f) => [f.name.toLowerCase(), f])),\n };\n}\n\nexport function fieldResolver(layer: LayerState): (name: string) => string | undefined {\n return (name) => layer.fieldsByLower.get(name.toLowerCase())?.name;\n}\n\nconst FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\nconst MAX_RECEIVED_VALUE = 4096;\nexport const MAX_FEATURES_PER_LAYER = 10_000;\n\n/** Request params safe to keep in the edit log: no credentials whatever their casing, long values truncated. */\nexport function withoutCredentials(raw: Record<string, string>): Record<string, string> {\n return Object.fromEntries(\n Object.entries(raw)\n .filter(([key]) => !isCredentialKey(key))\n .map(([key, value]) => {\n const safe = redactForLog(value);\n return [key, safe.length > MAX_RECEIVED_VALUE ? `${safe.slice(0, MAX_RECEIVED_VALUE)}…[truncated]` : safe];\n })\n );\n}\n\n/** Attribute keys in the layer's field-name casing, date strings as epoch ms, prototype keys dropped. */\nfunction canonicalAttributes(layer: LayerState, attributes: Attributes): Attributes {\n const out: Attributes = {};\n for (const [key, value] of Object.entries(attributes)) {\n if (FORBIDDEN_KEYS.has(key)) continue;\n const field = layer.fieldsByLower.get(key.toLowerCase());\n const isDate = field?.type === 'esriFieldTypeDate' && typeof value === 'string';\n out[field?.name ?? key] = isDate ? (parseDateLiteral(value) ?? value) : value;\n }\n return out;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Edits\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst FEATURE_NOT_FOUND = { code: 1019, description: 'Feature not found.' };\nconst DUPLICATE_GLOBAL_ID = { code: 1019, description: 'Duplicate GlobalID.' };\nconst LAYER_FULL = { code: 1019, description: `Layer is full (${MAX_FEATURES_PER_LAYER} features).` };\nconst INVALID_EDIT = { code: 1020, description: 'Invalid edit: missing identifier or attributes.' };\n\nconst MAX_IDS = 1000;\n\nfunction newGlobalId(): string {\n return `{${crypto.randomUUID().toUpperCase()}}`;\n}\n\nfunction normalizeGuid(value: unknown): string {\n return String(value).replace(/[{}]/g, '').toLowerCase();\n}\n\n/**\n * Append a feature; the ObjectID is the next free one unless a seed pins it.\n * A client-supplied GlobalID is kept only when `keepGlobalId`. Fails when it duplicates one or the layer is full.\n */\nexport function addFeature(\n layer: LayerState,\n input: Feature,\n opts: { objectId?: number; keepGlobalId: boolean }\n): { feature: Feature } | { error: { code: number; description: string } } {\n const { objectIdField, globalIdField } = layer.def;\n if (layer.features.length >= MAX_FEATURES_PER_LAYER) return { error: LAYER_FULL };\n const attributes = canonicalAttributes(layer, input.attributes);\n const objectId = opts.objectId ?? layer.nextObjectId;\n attributes[objectIdField] = objectId;\n if (globalIdField) {\n const supplied = attributes[globalIdField];\n attributes[globalIdField] = opts.keepGlobalId && typeof supplied === 'string' ? supplied : newGlobalId();\n const taken = layer.features.some(\n (f) => normalizeGuid(f.attributes[globalIdField]) === normalizeGuid(attributes[globalIdField])\n );\n if (taken) return { error: DUPLICATE_GLOBAL_ID };\n }\n layer.nextObjectId = Math.max(layer.nextObjectId, objectId + 1);\n const feature: Feature = { attributes, ...(input.geometry ? { geometry: input.geometry } : {}) };\n layer.features.push(feature);\n return { feature };\n}\n\nfunction idsOf(layer: LayerState, feature: Feature): { objectId: number; globalId: string | null } {\n const { objectIdField, globalIdField } = layer.def;\n return {\n objectId: feature.attributes[objectIdField] as number,\n globalId: globalIdField ? ((feature.attributes[globalIdField] as string | undefined) ?? null) : null,\n };\n}\n\nfunction findFeature(layer: LayerState, id: unknown, useGlobalIds: boolean): Feature | undefined {\n const { objectIdField, globalIdField } = layer.def;\n if (useGlobalIds && globalIdField) {\n return layer.features.find((f) => normalizeGuid(f.attributes[globalIdField]) === normalizeGuid(id));\n }\n return layer.features.find((f) => f.attributes[objectIdField] === Number(id));\n}\n\ninterface EditSet {\n adds?: Feature[];\n updates?: Feature[];\n deletes?: Array<string | number>;\n}\n\ninterface EditResult {\n objectId: number | null;\n globalId: string | null;\n success: boolean;\n error?: { code: number; description: string };\n}\n\ninterface EditOutcome {\n results: { addResults?: EditResult[]; updateResults?: EditResult[]; deleteResults?: EditResult[] };\n /** False when rollbackOnFailure undid the whole call. */\n committed: boolean;\n}\n\nfunction missing(id: unknown, useGlobalIds: boolean, error: EditResult['error']): EditResult {\n return {\n objectId: useGlobalIds ? null : Number(id),\n globalId: useGlobalIds ? String(id) : null,\n success: false,\n error,\n };\n}\n\n/**\n * Apply adds, then updates, then deletes to a working copy of the layer and commit it when every\n * edit succeeded, or when the caller opted out of rollback (then each edit stands on its own).\n */\nexport function applyLayerEdits(\n layer: LayerState,\n edits: EditSet,\n opts: { useGlobalIds: boolean; rollbackOnFailure: boolean }\n): EditOutcome {\n const { useGlobalIds } = opts;\n const { objectIdField, globalIdField } = layer.def;\n const work: LayerState = { ...layer, features: structuredClone(layer.features) };\n\n const addResults = edits.adds?.map((input): EditResult => {\n const added = addFeature(work, input, { keepGlobalId: useGlobalIds });\n if ('error' in added) return { objectId: null, globalId: null, success: false, error: added.error };\n return { ...idsOf(work, added.feature), success: true };\n });\n\n const updateResults = edits.updates?.map((input): EditResult => {\n const attributes = canonicalAttributes(work, input.attributes);\n const id = attributes[useGlobalIds && globalIdField ? globalIdField : objectIdField];\n if (id === undefined || id === null) return { objectId: null, globalId: null, success: false, error: INVALID_EDIT };\n const feature = findFeature(work, id, useGlobalIds);\n if (!feature) return missing(id, useGlobalIds, FEATURE_NOT_FOUND);\n // Delta update: only the sent fields change, and the identifiers never do.\n for (const [key, value] of Object.entries(attributes)) {\n if (key !== objectIdField && key !== globalIdField) feature.attributes[key] = value;\n }\n if (input.geometry) feature.geometry = input.geometry;\n return { ...idsOf(work, feature), success: true };\n });\n\n const deleteResults = edits.deletes?.map((id): EditResult => {\n const feature = findFeature(work, id, useGlobalIds);\n if (!feature) return missing(id, useGlobalIds, FEATURE_NOT_FOUND);\n work.features.splice(work.features.indexOf(feature), 1);\n return { ...idsOf(work, feature), success: true };\n });\n\n const all = [...(addResults ?? []), ...(updateResults ?? []), ...(deleteResults ?? [])];\n const committed = !opts.rollbackOnFailure || all.every((r) => r.success);\n if (committed) {\n layer.features = work.features;\n layer.nextObjectId = work.nextObjectId;\n }\n return { results: { addResults, updateResults, deleteResults }, committed };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Param parsing\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport function parseFeatures(name: string, value: string | undefined): Feature[] | undefined {\n if (value === undefined || value === '') return undefined;\n let parsed: unknown;\n try {\n parsed = JSON.parse(value);\n } catch {\n throw badParameter(name);\n }\n if (!Array.isArray(parsed)) throw badParameter(name);\n return parsed.map((item) => {\n if (typeof item !== 'object' || item === null) throw badParameter(name);\n const { attributes, geometry } = item as { attributes?: Attributes; geometry?: Record<string, unknown> };\n return { attributes: attributes ?? {}, ...(geometry ? { geometry } : {}) };\n });\n}\n\n/** `deletes` / `objectIds`: a JSON array or a comma-separated list, at most MAX_IDS. */\nexport function parseIds(name: string, value: string | undefined): Array<string | number> | undefined {\n if (value === undefined || value === '') return undefined;\n let ids: Array<string | number> | undefined;\n if (value.trim().startsWith('[')) {\n try {\n const parsed: unknown = JSON.parse(value);\n if (Array.isArray(parsed)) ids = parsed.map((v) => (typeof v === 'number' ? v : String(v)));\n } catch {\n // falls through to the bad-parameter error\n }\n } else {\n ids = value.split(',').map((v) => v.trim()).filter((v) => v !== '');\n }\n if (!ids || ids.length > MAX_IDS) throw badParameter(name);\n return ids;\n}\n","/** Normalised credential key names: lowercase with `-` and `_` removed, so `accessToken`, `access-token` and `access_token` match. */\nconst CREDENTIAL_KEYS: ReadonlySet<string> = new Set([\n 'token',\n 'password',\n 'passwd',\n 'secret',\n 'apikey',\n 'accesstoken',\n 'refreshtoken',\n 'idtoken',\n 'clientsecret',\n // AWS Secrets Manager writes (CreateSecret, PutSecretValue): the secret's value.\n 'secretstring',\n 'secretbinary',\n // AWS KMS Encrypt / GenerateDataKey: the plaintext being encrypted or the data key.\n 'plaintext',\n // Maximo native auth: the `_lpwd` password parameter, and MAXAUTH (base64 user:password) when sent as a parameter.\n 'lpwd',\n 'maxauth',\n]);\n\n/** Whether a parameter / JSON key holds a credential: its value is redacted from recordings and edit logs. */\nexport function isCredentialKey(key: string): boolean {\n return CREDENTIAL_KEYS.has(key.toLowerCase().replace(/[-_]/g, ''));\n}\n","import { isCredentialKey } from './credential-keys.js';\n\nconst MAX_REDACT_DEPTH = 64;\nexport const UNPARSEABLE_PAYLOAD = '[unparseable payload omitted]';\n\n/** Whether text looks like a JSON object or array payload. */\nexport function looksLikeJson(text: string): boolean {\n const trimmed = text.trimStart();\n return trimmed.startsWith('{') || trimmed.startsWith('[');\n}\n\n/** Walk parsed JSON, hiding credential-keyed values; anything deeper than the cap is hidden whole. */\nfunction redactNested(value: unknown, depth: number): unknown {\n if (depth > MAX_REDACT_DEPTH) return '[redacted]';\n if (Array.isArray(value)) return value.map((v) => redactNested(v, depth + 1));\n if (typeof value === 'object' && value !== null) {\n return Object.fromEntries(\n Object.entries(value).map(([key, v]) => [key, isCredentialKey(key) ? '[redacted]' : redactNested(v, depth + 1)])\n );\n }\n return value;\n}\n\n/**\n * A logged or recorded value: JSON payloads lose credential-keyed values at any depth; other text is kept.\n * It fails closed: JSON-looking text that cannot be parsed and walked is replaced, never kept as sent.\n */\nexport function redactForLog(text: string): string {\n if (!looksLikeJson(text)) return text;\n try {\n return JSON.stringify(redactNested(JSON.parse(text), 0));\n } catch {\n return UNPARSEABLE_PAYLOAD;\n }\n}\n","/**\n * Pure `where` clause compiler for the SQL-like filters ArcGIS clients send:\n * `1=1`, comparisons (= <> != < <= > >=), LIKE, IN, BETWEEN, IS [NOT] NULL,\n * NOT/AND/OR, parentheses, UPPER()/LOWER(), TIMESTAMP/DATE literals, and field names bare\n * or double-quoted (`\"WONUM\"`, standard SQL; matched case-insensitively like bare names).\n * Anything else, or a field the layer does not have, is a bad query.\n *\n * @module\n */\n\nimport { badQuery } from './errors.js';\n\nexport type Attributes = Record<string, unknown>;\ntype Predicate = (attrs: Attributes) => boolean;\ntype Operand = (attrs: Attributes) => unknown;\n\nconst MAX_WHERE_LENGTH = 4096;\nconst MAX_DEPTH = 32;\nconst MAX_LIKE_PATTERN = 256;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Values\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst DATE_LITERAL =\n /^(\\d{4})-(\\d{2})-(\\d{2})(?:[ T](\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.(\\d{1,3}))?)?)?\\s*(?:(Z)|([+-])(\\d{2}):?(\\d{2}))?$/i;\n\n/** `yyyy-mm-dd[ hh:mm[:ss[.fff]]][ Z|+hh:mm]` to epoch ms (no zone means UTC); null when it is not a date. */\nexport function parseDateLiteral(text: string): number | null {\n const m = DATE_LITERAL.exec(text.trim());\n if (!m) return null;\n const [month, day, hour, minute, second] = [m[2], m[3], m[4] ?? '0', m[5] ?? '0', m[6] ?? '0'].map(Number) as [\n number, number, number, number, number,\n ];\n if (month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 || minute > 59 || second > 59) return null;\n const fraction = (m[7] ?? '').padEnd(3, '0');\n const utc = Date.UTC(+m[1]!, +m[2]! - 1, +m[3]!, +(m[4] ?? 0), +(m[5] ?? 0), +(m[6] ?? 0), +fraction || 0);\n const offsetMinutes = m[9] ? (m[9] === '-' ? -1 : 1) * (+m[10]! * 60 + +m[11]!) : 0;\n const ms = utc - offsetMinutes * 60_000;\n return Number.isNaN(ms) ? null : ms;\n}\n\n/** Three-way compare; null when either side is null (SQL comparisons with NULL are never true). */\nfunction compareValues(left: unknown, right: unknown): number | null {\n if (left === null || left === undefined || right === null || right === undefined) return null;\n if (typeof left === 'number' || typeof right === 'number') {\n // An empty string is text, not zero.\n const l = left === '' ? NaN : Number(left);\n const r = right === '' ? NaN : Number(right);\n if (!Number.isNaN(l) && !Number.isNaN(r)) return l - r;\n }\n const l = String(left);\n const r = String(right);\n return l < r ? -1 : l > r ? 1 : 0;\n}\n\n/** Ordering for ORDER BY: nulls sort first ascending (so last descending). */\nexport function compareForSort(left: unknown, right: unknown): number {\n const leftNull = left === null || left === undefined;\n const rightNull = right === null || right === undefined;\n if (leftNull || rightNull) return leftNull === rightNull ? 0 : leftNull ? -1 : 1;\n return compareValues(left, right)!;\n}\n\n/**\n * SQL LIKE (`%` any run, `_` any one char, case-sensitive) without a RegExp: the two-pointer\n * walk with star backtracking is O(value x pattern), so no pattern can stall the host.\n */\nfunction likeMatcher(pattern: string): (value: string) => boolean {\n if (pattern.length > MAX_LIKE_PATTERN) throw badQuery();\n const p = pattern.replace(/%+/g, '%');\n return (s) => {\n let si = 0;\n let pi = 0;\n let star = -1;\n let mark = 0;\n while (si < s.length) {\n if (p[pi] === '%') {\n star = pi++;\n mark = si;\n } else if (pi < p.length && (p[pi] === '_' || p[pi] === s[si])) {\n pi++;\n si++;\n } else if (star !== -1) {\n pi = star + 1;\n si = ++mark;\n } else {\n return false;\n }\n }\n while (p[pi] === '%') pi++;\n return pi === p.length;\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Lexer\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** `field` is a double-quoted identifier: always a field name, never a keyword or function. */\ntype WhereToken = { kind: 'str' | 'num' | 'id' | 'field' | 'op' | 'punct'; value: string };\n\n/** Words after which a `-` starts a negative number rather than subtracting. */\nconst OPERATOR_WORDS = new Set(['AND', 'OR', 'NOT', 'BETWEEN', 'LIKE', 'IN', 'IS']);\n\nconst NUMBER = /-?\\d+(?:\\.\\d+)?/y;\nconst OPERATOR = /<=|>=|<>|!=|=|<|>/y;\nconst IDENTIFIER = /[A-Za-z_][A-Za-z0-9_.]*/y;\n\nfunction matchAt(re: RegExp, input: string, at: number): string | null {\n re.lastIndex = at;\n return re.exec(input)?.[0] ?? null;\n}\n\n/** A `quote`-delimited token starting at `start` (a doubled quote is a literal one): its value and the index after it. */\nfunction readQuoted(input: string, start: number, quote: string): { value: string; end: number } {\n let value = '';\n let i = start + 1;\n for (;;) {\n const close = input.indexOf(quote, i);\n if (close === -1) throw badQuery();\n value += input.substring(i, close);\n if (input[close + 1] !== quote) return { value, end: close + 1 };\n value += quote;\n i = close + 2;\n }\n}\n\n/** Linear in the input length: every step advances the index. */\nfunction tokenize(input: string): WhereToken[] {\n const tokens: WhereToken[] = [];\n let i = 0;\n while (i < input.length) {\n const ch = input[i]!;\n if (ch === ' ' || ch === '\\t' || ch === '\\n' || ch === '\\r') {\n i++;\n } else if (ch === \"'\" || ch === '\"') {\n const { value, end } = readQuoted(input, i, ch);\n // ArcGIS rejects an empty quoted identifier.\n if (ch === '\"' && value === '') throw badQuery();\n tokens.push({ kind: ch === \"'\" ? 'str' : 'field', value });\n i = end;\n } else if (ch === '(' || ch === ')' || ch === ',') {\n tokens.push({ kind: 'punct', value: ch });\n i++;\n } else {\n const prev = tokens[tokens.length - 1];\n const afterValue =\n prev !== undefined &&\n (prev.kind === 'num' ||\n prev.kind === 'str' ||\n prev.kind === 'field' ||\n (prev.kind === 'punct' && prev.value === ')') ||\n (prev.kind === 'id' && !OPERATOR_WORDS.has(prev.value.toUpperCase())));\n const number = matchAt(NUMBER, input, i);\n const op = matchAt(OPERATOR, input, i);\n const id = matchAt(IDENTIFIER, input, i);\n if (number && (ch !== '-' || !afterValue)) {\n tokens.push({ kind: 'num', value: number });\n i += number.length;\n } else if (op) {\n tokens.push({ kind: 'op', value: op });\n i += op.length;\n } else if (id) {\n tokens.push({ kind: 'id', value: id });\n i += id.length;\n } else {\n throw badQuery();\n }\n }\n }\n return tokens;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Parser\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst COMPARATORS: Record<string, (c: number) => boolean> = {\n '=': (c) => c === 0,\n '<>': (c) => c !== 0,\n '!=': (c) => c !== 0,\n '<': (c) => c < 0,\n '<=': (c) => c <= 0,\n '>': (c) => c > 0,\n '>=': (c) => c >= 0,\n};\n\nconst isNull = (value: unknown) => value === null || value === undefined;\n\nexport function compileWhere(where: string, resolveField: (name: string) => string | undefined): Predicate {\n if (where.length > MAX_WHERE_LENGTH) throw badQuery();\n const tokens = tokenize(where);\n let pos = 0;\n let depth = 0;\n\n const peek = () => tokens[pos];\n const isKeyword = (token: WhereToken | undefined, word: string) =>\n token?.kind === 'id' && token.value.toUpperCase() === word;\n const eatKeyword = (word: string) => {\n if (!isKeyword(peek(), word)) return false;\n pos++;\n return true;\n };\n const eatPunct = (value: string) => {\n const token = peek();\n if (token?.kind !== 'punct' || token.value !== value) return false;\n pos++;\n return true;\n };\n\n function operand(): Operand {\n const token = tokens[pos++];\n if (!token) throw badQuery();\n if (token.kind === 'str') return () => token.value;\n if (token.kind === 'num') return () => Number(token.value);\n if (token.kind === 'field') return fieldOperand(token.value);\n if (token.kind !== 'id') throw badQuery();\n const upper = token.value.toUpperCase();\n if ((upper === 'TIMESTAMP' || upper === 'DATE') && peek()?.kind === 'str') {\n const ms = parseDateLiteral(tokens[pos++]!.value);\n if (ms === null) throw badQuery();\n return () => ms;\n }\n if ((upper === 'UPPER' || upper === 'LOWER') && eatPunct('(')) {\n const inner = operand();\n if (!eatPunct(')')) throw badQuery();\n return (attrs) => {\n const value = inner(attrs);\n if (isNull(value)) return null;\n return upper === 'UPPER' ? String(value).toUpperCase() : String(value).toLowerCase();\n };\n }\n return fieldOperand(token.value);\n }\n\n function fieldOperand(name: string): Operand {\n const field = resolveField(name);\n if (!field) throw badQuery();\n return (attrs) => attrs[field];\n }\n\n function comparison(): Predicate {\n const left = operand();\n const next = peek();\n if (next?.kind === 'op') {\n pos++;\n const right = operand();\n const check = COMPARATORS[next.value]!;\n return (attrs) => {\n const c = compareValues(left(attrs), right(attrs));\n return c !== null && check(c);\n };\n }\n if (eatKeyword('IS')) {\n const negate = eatKeyword('NOT');\n if (!eatKeyword('NULL')) throw badQuery();\n return (attrs) => isNull(left(attrs)) !== negate;\n }\n const negate = eatKeyword('NOT');\n if (eatKeyword('LIKE')) {\n // A literal pattern is compiled once; a computed one per row.\n const literal = peek()?.kind === 'str' ? likeMatcher(peek()!.value) : null;\n const right = operand();\n return (attrs) => {\n const value = left(attrs);\n if (isNull(value)) return false;\n const match = literal ?? likeMatcher(String(right(attrs)));\n return match(String(value)) !== negate;\n };\n }\n if (eatKeyword('BETWEEN')) {\n const low = operand();\n if (!eatKeyword('AND')) throw badQuery();\n const high = operand();\n return (attrs) => {\n const value = left(attrs);\n const lo = compareValues(value, low(attrs));\n const hi = compareValues(value, high(attrs));\n if (lo === null || hi === null) return false;\n return (lo >= 0 && hi <= 0) !== negate;\n };\n }\n if (eatKeyword('IN')) {\n if (!eatPunct('(')) throw badQuery();\n const items = [operand()];\n while (eatPunct(',')) items.push(operand());\n if (!eatPunct(')')) throw badQuery();\n return (attrs) => {\n const value = left(attrs);\n if (isNull(value)) return false;\n return items.some((item) => compareValues(value, item(attrs)) === 0) !== negate;\n };\n }\n throw badQuery();\n }\n\n function unary(): Predicate {\n if (++depth > MAX_DEPTH) throw badQuery();\n try {\n if (eatKeyword('NOT')) {\n const inner = unary();\n return (attrs) => !inner(attrs);\n }\n if (eatPunct('(')) {\n const inner = or();\n if (!eatPunct(')')) throw badQuery();\n return inner;\n }\n return comparison();\n } finally {\n depth--;\n }\n }\n\n function and(): Predicate {\n const parts = [unary()];\n while (eatKeyword('AND')) parts.push(unary());\n return (attrs) => parts.every((part) => part(attrs));\n }\n\n function or(): Predicate {\n const parts = [and()];\n while (eatKeyword('OR')) parts.push(and());\n return (attrs) => parts.some((part) => part(attrs));\n }\n\n const predicate = or();\n if (pos !== tokens.length) throw badQuery();\n return predicate;\n}\n","/**\n * Request params: query string plus urlencoded form body, names case-insensitive.\n *\n * @module\n */\n\nimport { JSON_HEADERS } from './errors.js';\nimport type { EmulationRequest, EmulationResponse } from '../../plugin.js';\n\nexport interface Params {\n raw: Record<string, string>;\n get(name: string): string | undefined;\n}\n\nexport function readParams(req: EmulationRequest): Params {\n const raw: Record<string, string> = {};\n req.url.searchParams.forEach((value, key) => {\n raw[key] = value;\n });\n if (req.body) {\n new URLSearchParams(req.body).forEach((value, key) => {\n raw[key] = value;\n });\n }\n const lower = new Map(Object.entries(raw).map(([key, value]) => [key.toLowerCase(), value]));\n return { raw, get: (name) => lower.get(name.toLowerCase()) };\n}\n\n/** A boolean param; 'True' and 'true' are the same. */\nexport function flag(p: Params, name: string, whenAbsent = false): boolean {\n const value = p.get(name);\n return value === undefined ? whenAbsent : value.toLowerCase() === 'true';\n}\n\n/** `f=pjson` pretty-prints; every other format is compact JSON. */\nexport function ok(p: Params, body: object): EmulationResponse {\n if (p.get('f')?.toLowerCase() === 'pjson') {\n return { status: 200, headers: JSON_HEADERS, body: JSON.stringify(body, null, 2) };\n }\n return { status: 200, headers: JSON_HEADERS, body };\n}\n","/**\n * Esri emulator operations: seed a tenant's layer, simulate a GIS user's edit, drop a tenant.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport { z } from 'zod';\nimport { redactForLog } from '../../redact-json.js';\nimport { OperationInputError, type EmulationOperationDef } from '../../plugin.js';\nimport {\n addFeature,\n applyLayerEdits,\n createLayerState,\n layerDefSchema,\n type LayerState,\n} from './layers.js';\nimport { createTenant, logEdit, sweep, type EsriCtx, type EsriFixture, type EsriState } from './tenants.js';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Operations\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Names become path segments; a leading `_` would collide with `/_emulation`. */\nconst nameSchema = z.string().regex(/^[A-Za-z0-9][A-Za-z0-9_-]*$/);\n\nconst seedInput = z.object({\n /** Omit to create a fresh random tenant; a named tenant must already exist (to add another layer to it). */\n tenant: nameSchema.optional(),\n service: nameSchema.optional(),\n layer: layerDefSchema,\n features: z.array(\n z.object({\n attributes: z.record(z.string(), z.unknown()),\n geometry: z.record(z.string(), z.unknown()).optional(),\n })\n ),\n});\n\nconst seedOutput = z.object({\n tenant: z.string(),\n service: z.string(),\n layer: z.number(),\n baseUrl: z.string(),\n layerUrl: z.string(),\n});\n\nconst editFeatureInput = z.object({\n tenant: nameSchema,\n service: nameSchema,\n layer: z.number().int().nonnegative(),\n objectId: z.number().int(),\n attributes: z.record(z.string(), z.unknown()),\n});\n\nconst dropTenantInput = z.object({ tenant: nameSchema });\n\nfunction randomName(prefix: string): string {\n return `${prefix}${crypto.randomBytes(6).toString('hex')}`;\n}\n\nexport const esriOperations: EmulationOperationDef<EsriFixture, EsriState>[] = [\n {\n id: 'seed-layer',\n description:\n 'Create (or replace) a layer with features. Without a tenant, creates a fresh random tenant; a named tenant must already exist.',\n input: seedInput,\n output: seedOutput,\n handler: (ctx: EsriCtx, raw) => {\n const input = raw as z.infer<typeof seedInput>;\n sweep(ctx.state);\n const tenantName = input.tenant ?? randomName('t');\n const tenant = input.tenant ? ctx.state.tenants.get(input.tenant) : createTenant(ctx.state, tenantName);\n if (!tenant) throw new OperationInputError(`Tenant not found: ${input.tenant} (omit tenant to create one)`);\n tenant.touchedAt = Date.now();\n\n const layer = createLayerState(input.layer);\n for (const seeded of input.features) {\n const supplied = seeded.attributes[layer.def.objectIdField];\n const added = addFeature(layer, seeded, {\n objectId: typeof supplied === 'number' ? supplied : undefined,\n keepGlobalId: true,\n });\n if ('error' in added) throw new OperationInputError(`Cannot seed features: ${added.error.description}`);\n }\n\n const serviceName = input.service ?? randomName('svc');\n const layers = tenant.services.get(serviceName) ?? new Map<number, LayerState>();\n layers.set(layer.def.id, layer);\n tenant.services.set(serviceName, layers);\n\n const baseUrl = `https://${ctx.state.config.host}/${tenantName}/arcgis/rest/services`;\n return {\n tenant: tenantName,\n service: serviceName,\n layer: layer.def.id,\n baseUrl,\n layerUrl: `${baseUrl}/${serviceName}/FeatureServer/${layer.def.id}`,\n };\n },\n },\n {\n id: 'edit-feature',\n description: 'Simulate a GIS user editing a feature: merges the attributes and logs the edit with source \"external\".',\n input: editFeatureInput,\n output: z.object({ objectId: z.number() }),\n handler: (ctx: EsriCtx, raw) => {\n const input = raw as z.infer<typeof editFeatureInput>;\n sweep(ctx.state);\n const tenant = ctx.state.tenants.get(input.tenant);\n const layer = tenant?.services.get(input.service)?.get(input.layer);\n if (!tenant || !layer) {\n throw new OperationInputError(`Layer not found: ${input.tenant}/${input.service}/${input.layer}`);\n }\n const outcome = applyLayerEdits(\n layer,\n { updates: [{ attributes: { ...input.attributes, [layer.def.objectIdField]: input.objectId } }] },\n { useGlobalIds: false, rollbackOnFailure: true }\n );\n if (!outcome.committed) throw new OperationInputError(`Feature not found: ${input.objectId}`);\n tenant.touchedAt = Date.now();\n logEdit(tenant, {\n ts: new Date().toISOString(),\n source: 'external',\n endpoint: 'edit-feature',\n service: input.service,\n layerId: input.layer,\n received: { objectId: String(input.objectId), attributes: redactForLog(JSON.stringify(input.attributes)) },\n results: outcome.results,\n rolledBack: false,\n });\n return { objectId: input.objectId };\n },\n },\n {\n id: 'drop-tenant',\n description: 'Drop a tenant and everything in it (flow cleanup).',\n input: dropTenantInput,\n output: z.object({ dropped: z.boolean() }),\n handler: (ctx: EsriCtx, raw) => {\n const input = raw as z.infer<typeof dropTenantInput>;\n return { dropped: ctx.state.tenants.delete(input.tenant) };\n },\n },\n];\n","/**\n * Emulation Plugin Interface\n *\n * Defines the contract for emulation plugins that intercept external service\n * traffic in sandboxed test environments. Each plugin is a self-contained module\n * that declares which domains to intercept and how to respond.\n *\n * Plugins can have two components:\n * 1. Sandbox-side (always): HTTP handlers for server-to-server calls (token exchange, API calls)\n * 2. Browser-side (optional): Playwright context.route() handlers for browser-level interception (OAuth redirects)\n *\n * @module\n */\n\nimport type { ZodType } from 'zod';\nimport type { EnvContractEntry } from './env-contract.js';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Request / Response\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** An HTTP request as seen by the emulation router. */\nexport interface EmulationRequest {\n method: string;\n url: URL;\n headers: Record<string, string>;\n body?: string;\n /** Path parameters extracted by the router (e.g., { issueKey: 'PROJ-123' }) */\n params: Record<string, string>;\n}\n\n/** An HTTP response returned by a plugin handler. */\nexport interface EmulationResponse {\n status: number;\n headers?: Record<string, string>;\n /** String body or object (auto-serialized to JSON with Content-Type: application/json) */\n body?: string | object;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Plugin Context\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Runtime context provided to plugin route handlers.\n * Contains fixture data and mutable state that persists across requests\n * within a sandbox's lifetime.\n */\nexport interface PluginContext<TFixture = unknown, TState = unknown> {\n /** Immutable fixture data configured for this emulation instance */\n fixture: TFixture;\n /** Mutable state that persists across requests (e.g., created Jira issues) */\n state: TState;\n /** Sandbox instance ID */\n sandboxId: string;\n /** Resolved env-contract values (e.g., signingSecret) shared with the sandboxed app */\n env: Record<string, string>;\n log: (level: 'debug' | 'info' | 'warn' | 'error', msg: string) => void;\n instance: {\n /** Public origin of each public port of this copy, by port name (e.g. `emulation`, `web`). */\n publicOrigins: Record<string, string>;\n /** The copy's control-plane secret (EmulationInstanceConfig.controlPlane.token). Plugins must never log or echo it. */\n controlToken: string;\n };\n}\n\n/** Thrown by an operation handler for input the caller got wrong; the control plane answers 400 with the message. */\nexport class OperationInputError extends Error {}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Routes\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Route handler function. Return null to pass through to the real service. */\nexport type RouteHandler<TFixture = unknown, TState = unknown> = (\n req: EmulationRequest,\n ctx: PluginContext<TFixture, TState>\n) => EmulationResponse | null | Promise<EmulationResponse | null>;\n\nexport type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | '*';\n\n/** A declared sandbox-side route that the plugin handles. */\nexport interface EmulationRoute<TFixture = unknown, TState = unknown> {\n method: HttpMethod;\n /** Path pattern with express-style params (e.g., /rest/api/3/issue/:issueKey); a trailing `/*` also matches any further path */\n path: string;\n /** Handler function */\n handler: RouteHandler<TFixture, TState>;\n}\n\n/**\n * Minimal abstraction over Playwright's Route object.\n * Identical to ContextRouteHandle in @chatsdet/browser-core — defined here\n * to avoid a hard dependency from the emulation package to browser-core.\n */\nexport interface BrowserRouteHandle {\n fulfill(opts: {\n status?: number;\n headers?: Record<string, string>;\n body?: string;\n }): Promise<void>;\n continue(): Promise<void>;\n request(): {\n url(): string;\n method(): string;\n postData(): string | null;\n };\n}\n\n/** Browser-side route declaration for Playwright context.route(). */\nexport interface BrowserRoute<TFixture = unknown> {\n /** URL pattern for Playwright context.route() (glob or regex) */\n urlPattern: string | RegExp;\n handler: (route: BrowserRouteHandle, fixture: TFixture) => Promise<void>;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Control-Plane Declarations\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * An inbound event the emulator can fire INTO the sandboxed app\n * (e.g., a signed Slack `app_mention` webhook). `build` produces the full\n * signed HTTP request; signing (HMAC etc.) happens inside `build` using the\n * resolved env-contract values, at fire time, so timestamp windows hold.\n */\nexport interface InboundEventDef {\n /** Event identifier (e.g., 'app-mention') */\n id: string;\n description: string;\n /** Zod schema for the fire params */\n paramsSchema: ZodType;\n build(opts: {\n params: unknown;\n env: Record<string, string>;\n targetPath: string;\n /** Current fixture of the plugin (for defaults like team ids) */\n fixture: unknown;\n }): {\n method: string;\n /** Request path on the app (defaults to targetPath) */\n path: string;\n headers: Record<string, string>;\n body: string;\n };\n}\n\n/**\n * A read-only control endpoint the plugin exposes for assertions\n * (served as GET /_emulation/plugins/:pluginId/<path>).\n */\nexport interface ControlReadDef<TFixture = unknown, TState = unknown> {\n /** Path segment under the plugin's control namespace (e.g., 'posted-messages') */\n path: string;\n handler: (\n req: EmulationRequest,\n ctx: PluginContext<TFixture, TState>\n ) => EmulationResponse;\n}\n\n/**\n * A typed operation the plugin exposes for generic invocation via\n * `POST /_emulation/plugins/:pluginId/operations/:opId` — the framework\n * consumers (Cofactor actions, tests) call generically as `<plugin>.<op>`\n * without knowing the plugin's internals. Distinct from `ControlReadDef`\n * (GET-only, no input) and `ActionInterfaceDef` (a contract implemented\n * outside the emulator) — an operation is both declared AND executed here.\n */\nexport interface EmulationOperationDef<TFixture = unknown, TState = unknown> {\n /** Lowercase kebab id, unique per plugin, e.g. 'sent-emails' */\n id: string;\n description: string;\n /** Zod schema of the operation input object */\n input: ZodType;\n /** Zod schema of the result object */\n output: ZodType;\n /** Handler receives the validated input */\n handler: (\n ctx: PluginContext<TFixture, TState>,\n input: unknown\n ) => unknown | Promise<unknown>;\n}\n\n/**\n * A predefined sandbox-action contract the plugin publishes. The emulator\n * does NOT create actions — the template owner implements each interface as\n * a normal sandbox_action (only they know app specifics like webhook paths),\n * starting from `scaffoldScript`.\n */\nexport interface ActionInterfaceDef {\n /** Action slug the implementation must use (lowercase alphanumeric + hyphens) */\n slug: string;\n label: string;\n description: string;\n /** JSON Schema for the action's params */\n inputSchema: Record<string, unknown>;\n /** JSON Schema for the action's outputs */\n outputSchema: Record<string, unknown>;\n /**\n * Bash starting point for the implementation. May reference\n * $EMULATION_BASE_URL and $EMULATION_CONTROL_TOKEN (exported by the action\n * runner) and must print the JSON result as the last stdout line.\n */\n scaffoldScript: string;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Plugin Interface\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * The core plugin interface. Each emulation (Google OAuth, Jira, Stripe, etc.)\n * implements this as a self-contained module.\n *\n * Type parameters:\n * - TConfig: Plugin-specific configuration (e.g., tenant name, client IDs)\n * - TFixture: Seed data for the emulation (e.g., users, issues, projects)\n * - TState: Mutable runtime state derived from fixture data\n */\nexport interface EmulationPlugin<\n TConfig = unknown,\n TFixture = unknown,\n TState = unknown,\n> {\n /** Unique plugin identifier (e.g., 'google-oauth', 'jira', 'stripe') */\n readonly id: string;\n\n /** Human-readable name */\n readonly name: string;\n\n /** Version string */\n readonly version: string;\n\n /**\n * Domains this plugin intercepts.\n * Used for Docker network aliases (DNS override) and TLS cert generation.\n *\n * Can be a static list or a function of config for tenant-specific domains\n * (e.g., `(config) => [\\`${config.tenant}.atlassian.net\\`]`).\n */\n domains: string[] | ((config: TConfig) => string[]);\n\n /** Serve requests whose Host is not a registered domain (the copy's public emulator address). */\n readonly servesPublicOrigin?: boolean;\n\n /** Sandbox-side endpoint handlers */\n routes: EmulationRoute<TFixture, TState>[];\n\n /** Whether this plugin needs browser-side intercepts (e.g., OAuth redirects) */\n readonly needsBrowserIntercept: boolean;\n\n /**\n * Browser-side routes for Playwright context.route().\n * Only called when `needsBrowserIntercept` is true.\n */\n getBrowserRoutes?(fixture: TFixture): BrowserRoute<TFixture>[];\n\n /**\n * Initialize mutable runtime state from config and fixture data.\n * Called once when the emulation service starts, and again when the\n * control plane replaces the fixture.\n *\n * `env` carries resolved env-contract values (absent for plugins without\n * a contract, or when invoked by pre-contract callers).\n */\n initialize(config: TConfig, fixture: TFixture, env?: Record<string, string>): TState;\n\n /**\n * Zod schema of the plugin's config (a definition's `emulation.<id>` block).\n * When present, definition validation reports config problems at their path\n * instead of the emulator failing at boot. Plugins whose config is a few\n * loose options omit it.\n */\n configSchema?: ZodType;\n\n /**\n * Whether string values in this plugin's config may hold `${params.NAME}`\n * and `${secrets.NAME}`, resolved inside the sandbox at prepare (see the\n * sandbox helper's `emulation-refs.ts`). Only for plugins whose domains and\n * env contract never depend on a referenced value: the API computes those\n * from the unresolved config.\n */\n readonly configReferences?: boolean;\n\n /** Default fixture data for quick setup */\n defaultFixture?: TFixture;\n\n /** Zod schema validating TFixture (drives control-plane fixture writes) */\n fixtureSchema?: ZodType<TFixture>;\n\n /** Logical values shared between emulator and app (resolved at provision) */\n envContract?: EnvContractEntry[];\n\n /** Inbound events the control plane can fire into the app */\n inboundEvents?: InboundEventDef[];\n\n /** Read-only control endpoints for assertions */\n controlReads?: ControlReadDef<TFixture, TState>[];\n\n /**\n * How many tenants (isolated state partitions) were used at or after `sinceMs`\n * (epoch ms). Feeds the control plane's `/_emulation/active` idle gate; plugins\n * without tenants omit it.\n */\n countActive?(ctx: PluginContext<TFixture, TState>, sinceMs: number): number;\n\n /** Typed operations invocable generically as `<pluginId>.<opId>` */\n operations?: EmulationOperationDef<TFixture, TState>[];\n\n /** Predefined sandbox-action contracts for template owners to implement */\n actionInterfaces?: ActionInterfaceDef[];\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Resolve domains from a plugin given its config. */\nexport function resolvePluginDomains<TConfig>(\n plugin: Pick<EmulationPlugin<TConfig>, 'domains'>,\n config: TConfig\n): string[] {\n return typeof plugin.domains === 'function'\n ? plugin.domains(config)\n : plugin.domains;\n}\n","/**\n * Esri emulator config, per-tenant state, token store and expiry.\n *\n * @module\n */\n\nimport { z } from 'zod';\nimport {\n OperationInputError,\n type EmulationRequest,\n type EmulationResponse,\n type PluginContext,\n type RouteHandler,\n} from '../../plugin.js';\nimport { EsriError, errorResponse } from './errors.js';\nimport type { EditLogEntry, LayerState } from './layers.js';\nimport { readParams, type Params } from './params.js';\n\nexport const configSchema = z.object({\n /** Public hostname the connector is pointed at (Service Base URL and Token URL). */\n host: z.string().min(1),\n /** The username/password the connector's connection is configured with. Make the password long and random. */\n username: z.string().min(1),\n password: z.string().min(24),\n /** Lifetime of a generated token unless the request asks for `expiration`. */\n tokenTtlSeconds: z.number().int().positive().default(3600),\n /** A tenant untouched for this long is dropped. */\n tenantTtlMinutes: z.number().positive().default(360),\n /** A tenant older than this is dropped however recently it was used; bounds memory and lets the idle gate settle. */\n tenantMaxAgeMinutes: z.number().positive().default(1440),\n});\n\nexport type EsriConfig = z.input<typeof configSchema>;\n\n/** Tenants are created through operations, never through the fixture. */\nexport type EsriFixture = Record<string, never>;\n\nconst EDIT_LOG_LIMIT = 1000;\nconst MAX_TENANTS = 100;\nconst MAX_TOKENS = 1000;\n\ninterface TenantState {\n services: Map<string, Map<number, LayerState>>;\n edits: EditLogEntry[];\n createdAt: number;\n touchedAt: number;\n}\n\nexport interface EsriState {\n config: z.output<typeof configSchema>;\n tenants: Map<string, TenantState>;\n /** token -> expiry (epoch ms). Tokens and the credential are global, not per tenant. */\n tokens: Map<string, number>;\n}\n\nexport type EsriCtx = PluginContext<EsriFixture, EsriState>;\nexport type Handler = RouteHandler<EsriFixture, EsriState>;\n\n/** Drop tenants idle past the TTL or older than the max age, and expired tokens. */\nexport function sweep(state: EsriState): void {\n const now = Date.now();\n const idleMs = state.config.tenantTtlMinutes * 60_000;\n const maxAgeMs = state.config.tenantMaxAgeMinutes * 60_000;\n for (const [name, tenant] of state.tenants) {\n if (now - tenant.touchedAt > idleMs || now - tenant.createdAt > maxAgeMs) state.tenants.delete(name);\n }\n for (const [token, expires] of state.tokens) {\n if (expires <= now) state.tokens.delete(token);\n }\n}\n\nexport function createTenant(state: EsriState, name: string): TenantState {\n if (state.tenants.size >= MAX_TENANTS) {\n throw new OperationInputError(`Too many tenants (${MAX_TENANTS}); drop one with drop-tenant first`);\n }\n const now = Date.now();\n const tenant: TenantState = { services: new Map(), edits: [], createdAt: now, touchedAt: now };\n state.tenants.set(name, tenant);\n return tenant;\n}\n\nexport function findLayer(call: TenantCall): LayerState {\n const layers = call.tenant.services.get(call.req.params['service']!);\n if (!layers) throw new EsriError(404, 'Service not found');\n const layer = layers.get(Number(call.req.params['layer']));\n if (!layer) throw new EsriError(400, 'Invalid or missing input parameters.');\n return layer;\n}\n\nexport function logEdit(tenant: TenantState, entry: EditLogEntry): void {\n tenant.edits.push(entry);\n if (tenant.edits.length > EDIT_LOG_LIMIT) tenant.edits.shift();\n}\n\n/** Remember a token; beyond MAX_TOKENS the oldest are forgotten. */\nexport function storeToken(state: EsriState, token: string, expires: number): void {\n state.tokens.set(token, expires);\n for (const oldest of state.tokens.keys()) {\n if (state.tokens.size <= MAX_TOKENS) break;\n state.tokens.delete(oldest);\n }\n}\n\nfunction bearer(value: string | undefined): string | undefined {\n const match = value ? /^bearer\\s+(.+)$/i.exec(value) : null;\n return match?.[1]?.trim();\n}\n\n/** The token a request presents: `token` param, Authorization, or X-Esri-Authorization. */\nexport function presentedToken(req: EmulationRequest, p: Params): string | undefined {\n return p.get('token') || bearer(req.headers['authorization']) || bearer(req.headers['x-esri-authorization']);\n}\n\ninterface TenantCall {\n req: EmulationRequest;\n ctx: EsriCtx;\n p: Params;\n tenantName: string;\n tenant: TenantState;\n}\n\n/** Token check, tenant lookup and touch, and EsriError -> error-body conversion for `/:tenant/...` routes. */\nexport function guarded(fn: (call: TenantCall) => EmulationResponse): Handler {\n return (req, ctx) => {\n const state = ctx.state;\n sweep(state);\n const p = readParams(req);\n try {\n const token = presentedToken(req, p);\n if (!token) throw new EsriError(499, 'Token Required');\n if (!state.tokens.has(token)) throw new EsriError(498, 'Invalid token.');\n const tenantName = req.params['tenant']!;\n const tenant = state.tenants.get(tenantName);\n if (!tenant) throw new EsriError(404, 'Item does not exist or is inaccessible.');\n tenant.touchedAt = Date.now();\n return fn({ req, ctx, p, tenantName, tenant });\n } catch (err) {\n if (err instanceof EsriError) return errorResponse(err);\n throw err;\n }\n };\n}\n","/**\n * Service/layer metadata and the `query` operation.\n *\n * @module\n */\n\nimport type { EmulationResponse } from '../../plugin.js';\nimport { badParameter, badQuery } from './errors.js';\nimport { fieldResolver, parseIds, type LayerDef, type LayerState } from './layers.js';\nimport { flag, ok, type Params } from './params.js';\nimport { compareForSort, compileWhere } from './where.js';\n\nexport const CURRENT_VERSION = 11.2;\nconst SPATIAL_REFERENCE = { wkid: 4326, latestWkid: 4326 };\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Metadata\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction layerSummary(layer: LayerState) {\n return {\n id: layer.def.id,\n name: layer.def.name,\n parentLayerId: -1,\n defaultVisibility: true,\n subLayerIds: null,\n geometryType: layer.def.geometryType ?? undefined,\n };\n}\n\nfunction fieldMetadata(def: LayerDef) {\n return def.fields.map((f) => ({\n name: f.name,\n type: f.type,\n alias: f.alias ?? f.name,\n nullable: f.nullable,\n editable: f.editable,\n ...(f.length !== undefined ? { length: f.length } : {}),\n }));\n}\n\nexport function serviceMetadata(layers: Map<number, LayerState>) {\n const all = [...layers.values()];\n return {\n currentVersion: CURRENT_VERSION,\n serviceDescription: '',\n hasVersionedData: false,\n supportsDisconnectedEditing: false,\n hasStaticData: false,\n maxRecordCount: Math.max(...all.map((l) => l.def.maxRecordCount)),\n supportedQueryFormats: 'JSON',\n capabilities: 'Query,Create,Update,Delete,Editing',\n spatialReference: SPATIAL_REFERENCE,\n layers: all.filter((l) => l.def.geometryType !== null).map(layerSummary),\n tables: all.filter((l) => l.def.geometryType === null).map(layerSummary),\n };\n}\n\nexport function layerMetadata(layer: LayerState) {\n const { def } = layer;\n return {\n currentVersion: CURRENT_VERSION,\n id: def.id,\n name: def.name,\n type: def.geometryType === null ? 'Table' : 'Feature Layer',\n geometryType: def.geometryType ?? undefined,\n objectIdField: def.objectIdField,\n globalIdField: def.globalIdField ?? '',\n uniqueIdField: { name: def.objectIdField, isSystemMaintained: true },\n hasAttachments: false,\n hasStaticData: false,\n isDataVersioned: false,\n supportedQueryFormats: 'JSON',\n supportsApplyEditsWithGlobalIds: def.globalIdField !== undefined,\n supportsPagination: true,\n supportsAdvancedQueries: true,\n advancedQueryCapabilities: {\n supportsPagination: true,\n supportsOrderBy: true,\n supportsAdvancedQueries: true,\n supportsStatistics: false,\n supportsDistinct: false,\n supportsCountDistinct: false,\n },\n capabilities: 'Query,Create,Update,Delete,Editing',\n maxRecordCount: def.maxRecordCount,\n fields: fieldMetadata(def),\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Query\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Query features this emulator does not implement; asking for one is an error, not a silent no-op.\n * The spatial companions of `geometry` (geometryType, spatialRel, inSR, distance, units) are absent:\n * real ArcGIS ignores them unless `geometry` is given, and the ArcGIS SDKs send defaults for them on\n * every query. A real spatial filter still fails here, on `geometry`.\n */\nconst UNSUPPORTED_PARAMS = [\n 'geometry',\n 'outStatistics',\n 'groupByFieldsForStatistics',\n 'returnDistinctValues',\n 'returnExtentOnly',\n 'time',\n 'having',\n 'returnZ',\n 'returnM',\n];\nconst UNSUPPORTED_FORMATS = new Set(['geojson', 'pbf', 'html']);\n\nfunction rejectUnsupported(p: Params): void {\n for (const name of UNSUPPORTED_PARAMS) {\n const value = p.get(name);\n if (value !== undefined && value !== '' && value.toLowerCase() !== 'false') throw badParameter(name);\n }\n // `none` is the default; `standard` and `tile` change paging limits, which this emulator does not model.\n const resultType = p.get('resultType')?.toLowerCase();\n if (resultType && resultType !== 'none') throw badParameter('resultType');\n if (UNSUPPORTED_FORMATS.has((p.get('f') ?? '').toLowerCase())) throw badParameter('f');\n}\n\nexport function queryLayer(layer: LayerState, p: Params): EmulationResponse {\n const { def } = layer;\n const resolve = fieldResolver(layer);\n rejectUnsupported(p);\n\n const predicate = compileWhere(p.get('where')?.trim() || '1=1', resolve);\n const ids = parseIds('objectIds', p.get('objectIds'));\n const objectIds = ids && new Set(ids.map(Number));\n\n const sorts = (p.get('orderByFields') ?? '')\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)\n .map((spec) => {\n const [name = '', direction = 'ASC'] = spec.split(/\\s+/);\n const field = resolve(name);\n const dir = direction.toUpperCase();\n if (!field || (dir !== 'ASC' && dir !== 'DESC')) throw badQuery();\n return { field, sign: dir === 'DESC' ? -1 : 1 };\n });\n sorts.push({ field: def.objectIdField, sign: 1 });\n\n const matched = layer.features\n .filter((f) => predicate(f.attributes) && (!objectIds || objectIds.has(f.attributes[def.objectIdField] as number)))\n .sort((a, b) => {\n for (const { field, sign } of sorts) {\n const c = compareForSort(a.attributes[field], b.attributes[field]);\n if (c !== 0) return c * sign;\n }\n return 0;\n });\n\n if (flag(p, 'returnCountOnly')) return ok(p, { count: matched.length });\n if (flag(p, 'returnIdsOnly')) {\n return ok(p, {\n objectIdFieldName: def.objectIdField,\n objectIds: matched.map((f) => f.attributes[def.objectIdField]),\n });\n }\n\n // No outFields means no attributes, per the Esri Query docs.\n const outFieldsParam = p.get('outFields')?.trim();\n const outFields =\n outFieldsParam === '*'\n ? def.fields.map((f) => f.name)\n : (outFieldsParam ? outFieldsParam.split(',').map((s) => s.trim()) : []).map((name) => {\n const field = resolve(name);\n if (!field) throw badQuery();\n return field;\n });\n\n const offset = Math.max(0, Math.floor(Number(p.get('resultOffset'))) || 0);\n const requested = p.get('resultRecordCount') ? Math.floor(Number(p.get('resultRecordCount'))) : NaN;\n const limit = Number.isFinite(requested) ? Math.min(Math.max(requested, 1), def.maxRecordCount) : def.maxRecordCount;\n const page = matched.slice(offset, offset + limit);\n const returnGeometry = flag(p, 'returnGeometry', true);\n\n return ok(p, {\n objectIdFieldName: def.objectIdField,\n globalIdFieldName: def.globalIdField ?? '',\n geometryType: def.geometryType ?? undefined,\n spatialReference: SPATIAL_REFERENCE,\n fields: fieldMetadata(def).filter((f) => outFields.includes(f.name)),\n features: page.map((f) => ({\n attributes: Object.fromEntries(outFields.map((name) => [name, f.attributes[name] ?? null])),\n ...(returnGeometry && f.geometry ? { geometry: f.geometry } : {}),\n })),\n exceededTransferLimit: offset + limit < matched.length,\n });\n}\n","/**\n * Jira Cloud API Emulation Plugin\n *\n * Emulates the Jira REST API v3 the app talks to: the OAuth token endpoint\n * (`auth.atlassian.com`), the 3LO gateway (`api.atlassian.com/ex/jira/<cloudId>`)\n * and the tenant host (`<tenant>.atlassian.net`). Sandbox-side only — Jira is an\n * API service, so no browser interception is needed.\n *\n * State is mutable (created issues, labels, comments and registered webhooks\n * persist for the copy's lifetime). Like Jira, the emulator delivers webhooks to\n * the URLs the app registered through `POST /rest/api/3/webhook`, so nothing\n * app-specific lives here. Operations let a flow drive it: `add-label` tags an\n * issue and delivers `jira:issue_updated` to the registered subscribers. Unlike\n * Slack's `inboundEvents`, operations here may make outbound deliveries to the app.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport { z } from 'zod';\nimport type {\n EmulationPlugin,\n EmulationRequest,\n EmulationResponse,\n EmulationRoute,\n PluginContext,\n} from '../plugin.js';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- parsing untrusted API input\nfunction safeParseJson(body: string | undefined): { ok: true; data: any } | { ok: false; error: EmulationResponse } {\n try {\n return { ok: true, data: JSON.parse(body ?? '{}') };\n } catch {\n return { ok: false, error: { status: 400, body: { errorMessages: ['Invalid JSON body'] } } };\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface JiraConfig {\n /** Tenant subdomain (e.g., 'acme' for acme.atlassian.net) */\n tenant: string;\n}\n\nexport interface JiraUser {\n accountId: string;\n displayName: string;\n emailAddress: string;\n}\n\n/** Atlassian Document Format node — descriptions and comments are ADF in API v3. */\nexport interface AdfNode {\n type: string;\n text?: string;\n content?: AdfNode[];\n version?: number;\n}\n\nexport interface JiraComment {\n id: string;\n author: JiraUser;\n body: AdfNode;\n created: string;\n}\n\nexport interface JiraIssue {\n id: string;\n key: string;\n projectKey: string;\n summary: string;\n description?: AdfNode;\n status: { name: string };\n assignee?: JiraUser;\n reporter?: JiraUser;\n issuetype: { name: string };\n priority?: { name: string };\n created: string;\n updated: string;\n labels: string[];\n comments: JiraComment[];\n attachments: string[];\n}\n\nexport interface JiraProject {\n id: string;\n key: string;\n name: string;\n}\n\n/** Fixture issues give plain-text descriptions; the emulator converts them to ADF. */\nexport interface JiraFixtureIssue\n extends Omit<JiraIssue, 'description' | 'labels' | 'comments' | 'attachments'> {\n description?: string;\n labels?: string[];\n}\n\nexport interface JiraFixture {\n projects: JiraProject[];\n issues: JiraFixtureIssue[];\n users?: JiraUser[];\n}\n\n/** A subscriber the app registered with `POST /rest/api/3/webhook`. */\ninterface JiraWebhook {\n id: number;\n url: string;\n events: string[];\n /** From the `project = \"KEY\"` clause of the registration's `jqlFilter`; null delivers for every project. */\n projectKey: string | null;\n}\n\nexport interface JiraState {\n projects: Map<string, JiraProject>;\n issues: Map<string, JiraIssue>;\n users: Map<string, JiraUser>;\n webhooks: Map<number, JiraWebhook>;\n /** Per-project counter for auto-assigning issue keys */\n issueCounter: Record<string, number>;\n /** Next numeric issue id (Jira ids are numeric strings) */\n nextIssueId: number;\n nextCommentId: number;\n nextWebhookId: number;\n tenant: string;\n}\n\ntype JiraCtx = PluginContext<JiraFixture, JiraState>;\n\nconst EMULATED_USER: JiraUser = {\n accountId: 'emulated',\n displayName: 'Emulated User',\n emailAddress: 'emulated@test.com',\n};\n\nconst ISSUE_UPDATED = 'jira:issue_updated';\n/** The app's webhook handler answers fast (it enqueues a job); keep this below the executor's 30s operation timeout. */\nconst WEBHOOK_TIMEOUT_MS = 15_000;\nconst WEBHOOK_TTL_MS = 30 * 24 * 60 * 60 * 1000;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// ADF helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction textToAdf(text: string): AdfNode {\n return {\n type: 'doc',\n version: 1,\n content: text\n .split(/\\n{2,}/)\n .map((para) => ({ type: 'paragraph', content: [{ type: 'text', text: para }] })),\n };\n}\n\nconst ADF_BLOCKS = new Set(['paragraph', 'heading', 'bulletList', 'orderedList', 'listItem', 'blockquote', 'codeBlock']);\n\nfunction adfToText(node: AdfNode | undefined): string {\n if (!node) return '';\n if (typeof node.text === 'string') return node.text;\n const inner = (node.content ?? []).map(adfToText).join('');\n return ADF_BLOCKS.has(node.type) ? `${inner}\\n` : inner;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Operations\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst createIssueInput = z\n .object({ projectKey: z.string(), summary: z.string(), description: z.string().optional() })\n .strict();\n\nconst addLabelInput = z\n .object({ issueKey: z.string(), label: z.string().regex(/^\\S+$/, 'labels cannot contain spaces') })\n .strict();\n\nconst issueKeyInput = z.object({ issueKey: z.string() }).strict();\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Routes\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * The app reaches Jira through the 3LO gateway (`/ex/jira/<cloudId>/rest/...`);\n * the tenant host serves the same API at the bare `/rest/...` path.\n */\nfunction restRoutes(\n method: EmulationRoute<JiraFixture, JiraState>['method'],\n path: string,\n handler: EmulationRoute<JiraFixture, JiraState>['handler']\n): EmulationRoute<JiraFixture, JiraState>[] {\n return ['', '/ex/jira/:cloudId'].map((prefix) => ({ method, path: `${prefix}/rest/api/3${path}`, handler }));\n}\n\nexport const jiraPlugin: EmulationPlugin<JiraConfig, JiraFixture, JiraState> = {\n id: 'jira',\n name: 'Jira Cloud API',\n version: '2.0.0',\n\n domains: (config) => [`${config.tenant}.atlassian.net`, 'api.atlassian.com', 'auth.atlassian.com'],\n needsBrowserIntercept: false,\n\n routes: [\n // ── OAuth token refresh (auth.atlassian.com) ────────────────────────\n {\n method: 'POST',\n path: '/oauth/token',\n handler: () => ({\n status: 200,\n body: {\n access_token: `emulated-access-${crypto.randomBytes(8).toString('hex')}`,\n refresh_token: 'emulated-refresh',\n expires_in: 3600,\n scope: 'read:jira-work write:jira-work offline_access',\n token_type: 'Bearer',\n },\n }),\n },\n\n // ── Projects ─────────────────────────────────────────────────────────\n ...restRoutes('GET', '/project', (_req, ctx: JiraCtx) => ({\n status: 200,\n body: Array.from(ctx.state.projects.values()),\n })),\n ...restRoutes('GET', '/project/search', (_req, ctx: JiraCtx) => {\n const values = Array.from(ctx.state.projects.values());\n return { status: 200, body: { values, total: values.length, isLast: true } };\n }),\n ...restRoutes('GET', '/project/:projectKey', (req, ctx: JiraCtx) => {\n const project = ctx.state.projects.get(req.params.projectKey);\n if (!project) return { status: 404, body: { errorMessages: ['Project not found'] } };\n return { status: 200, body: project };\n }),\n\n // ── Issues ───────────────────────────────────────────────────────────\n // Before /issue/:issueKey, which would take \"createmeta\" for an issue key. The app's\n // Jira settings page reads the issue types of the project it files tickets into.\n ...restRoutes('GET', '/issue/createmeta', (_req, ctx: JiraCtx) => ({\n status: 200,\n body: {\n projects: Array.from(ctx.state.projects.values()).map((project) => ({\n key: project.key,\n issuetypes: [{ id: '10001', name: 'Task', subtask: false }],\n })),\n },\n })),\n ...restRoutes('GET', '/issue/:issueKey', handleGetIssue),\n ...restRoutes('POST', '/issue', handleCreateIssue),\n ...restRoutes('PUT', '/issue/:issueKey', handleUpdateIssue),\n ...restRoutes('POST', '/issue/:issueKey/comment', handleAddComment),\n ...restRoutes('POST', '/issue/:issueKey/attachments', handleAddAttachment),\n\n // ── Transitions ──────────────────────────────────────────────────────\n ...restRoutes('GET', '/issue/:issueKey/transitions', () => ({\n status: 200,\n body: {\n transitions: [\n { id: '11', name: 'To Do' },\n { id: '21', name: 'In Progress' },\n { id: '31', name: 'Done' },\n ],\n },\n })),\n ...restRoutes('POST', '/issue/:issueKey/transitions', handleTransition),\n\n // ── Search ───────────────────────────────────────────────────────────\n ...restRoutes('POST', '/search', handleSearch),\n ...restRoutes('GET', '/search', handleSearch),\n ...restRoutes('POST', '/search/jql', handleSearch),\n\n // ── Webhooks (the app registers its own delivery URL) ────────────────\n ...restRoutes('POST', '/webhook', handleRegisterWebhooks),\n ...restRoutes('DELETE', '/webhook', handleDeleteWebhooks),\n ...restRoutes('PUT', '/webhook/refresh', () => ({\n status: 200,\n body: { expirationDate: new Date(Date.now() + WEBHOOK_TTL_MS).toISOString() },\n })),\n\n // ── Users / server info ──────────────────────────────────────────────\n ...restRoutes('GET', '/myself', (_req, ctx: JiraCtx) => ({\n status: 200,\n body: ctx.state.users.values().next().value ?? EMULATED_USER,\n })),\n ...restRoutes('GET', '/serverInfo', () => ({\n status: 200,\n body: {\n baseUrl: 'https://emulated.atlassian.net',\n version: '1001.0.0-SNAPSHOT',\n deploymentType: 'Cloud',\n scmInfo: 'emulated',\n },\n })),\n ],\n\n operations: [\n {\n id: 'create-issue',\n description: 'Create an issue (no webhook is delivered).',\n input: createIssueInput,\n output: z.object({ key: z.string(), id: z.string() }),\n handler: (ctx: JiraCtx, raw) => {\n const input = raw as z.infer<typeof createIssueInput>;\n if (!ctx.state.projects.has(input.projectKey)) {\n throw new Error(`Project ${input.projectKey} not found`);\n }\n const issue = createIssue(ctx, {\n projectKey: input.projectKey,\n summary: input.summary,\n description: input.description ? textToAdf(input.description) : undefined,\n });\n return { key: issue.key, id: issue.id };\n },\n },\n {\n id: 'add-label',\n description:\n 'Add a label to an issue and deliver jira:issue_updated to the webhooks the app registered for the issue\\'s project, as Jira does when a person tags a ticket. The label is committed only after every subscriber accepts the delivery. Fails if the label is already present or no webhook is registered.',\n input: addLabelInput,\n output: z.object({ labels: z.string() }),\n handler: async (ctx: JiraCtx, raw) => {\n const input = raw as z.infer<typeof addLabelInput>;\n const issue = requireIssue(ctx, input.issueKey);\n if (issue.labels.includes(input.label)) {\n // A changelog with identical from/to strings is not a tag event — the app would ignore it.\n throw new Error(`Issue ${issue.key} already has the label '${input.label}'`);\n }\n // Commit only once every subscriber accepted the delivery, so a failed step can be retried for real.\n await deliverIssueUpdated(ctx, issue, [...issue.labels, input.label]);\n // The delivery awaited the network; merge into the issue as it is now, not the array read before.\n const current = requireIssue(ctx, issue.key);\n if (current.labels.includes(input.label)) {\n throw new Error(`Issue ${current.key} already has the label '${input.label}'`);\n }\n current.labels = [...current.labels, input.label];\n current.updated = new Date().toISOString();\n return { labels: current.labels.join(' ') };\n },\n },\n {\n id: 'get-issue',\n description: 'Read an issue: its labels (space-separated) and how many attachments the app uploaded.',\n input: issueKeyInput,\n output: z.object({ labels: z.string(), attachmentCount: z.number() }),\n handler: (ctx: JiraCtx, raw) => {\n const issue = requireIssue(ctx, (raw as z.infer<typeof issueKeyInput>).issueKey);\n return { labels: issue.labels.join(' '), attachmentCount: issue.attachments.length };\n },\n },\n {\n id: 'get-comments',\n description: 'Read the comments the app wrote on an issue; lastCommentText is the newest as plain text.',\n input: issueKeyInput,\n output: z.object({ commentCount: z.number(), lastCommentText: z.string() }),\n handler: (ctx: JiraCtx, raw) => {\n const issue = requireIssue(ctx, (raw as z.infer<typeof issueKeyInput>).issueKey);\n return {\n commentCount: issue.comments.length,\n lastCommentText: adfToText(issue.comments.at(-1)?.body),\n };\n },\n },\n ],\n\n initialize(config, fixture) {\n const projects = new Map(fixture.projects.map((p) => [p.key, p]));\n const issues = new Map<string, JiraIssue>(\n fixture.issues.map((i) => [\n i.key,\n {\n ...i,\n description: i.description ? textToAdf(i.description) : undefined,\n labels: i.labels ?? [],\n comments: [],\n attachments: [],\n },\n ])\n );\n const users = new Map((fixture.users ?? []).map((u) => [u.accountId, u]));\n\n const issueCounter: Record<string, number> = {};\n let maxId = 10000;\n for (const issue of fixture.issues) {\n const num = parseInt(issue.key.split('-')[1] ?? '', 10);\n if (!isNaN(num)) {\n issueCounter[issue.projectKey] = Math.max(issueCounter[issue.projectKey] ?? 0, num);\n }\n const id = parseInt(issue.id, 10);\n if (!isNaN(id)) maxId = Math.max(maxId, id);\n }\n\n return {\n projects,\n issues,\n users,\n webhooks: new Map(),\n issueCounter,\n nextIssueId: maxId + 1,\n nextCommentId: 10000,\n nextWebhookId: 1,\n tenant: config.tenant,\n };\n },\n\n defaultFixture: {\n projects: [{ id: '10000', key: 'TEST', name: 'Test Project' }],\n issues: [\n {\n id: '10001',\n key: 'TEST-1',\n projectKey: 'TEST',\n summary: 'Sample issue',\n description: 'This is a sample issue for testing.',\n status: { name: 'To Do' },\n issuetype: { name: 'Task' },\n priority: { name: 'Medium' },\n created: new Date().toISOString(),\n updated: new Date().toISOString(),\n },\n ],\n users: [{ accountId: '100001', displayName: 'Test User', emailAddress: 'test@example.com' }],\n },\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// State helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Jira resolves an issue by key or by numeric id interchangeably. */\nfunction findIssue(state: JiraState, keyOrId: string): JiraIssue | undefined {\n const byKey = state.issues.get(keyOrId);\n if (byKey) return byKey;\n for (const issue of state.issues.values()) {\n if (issue.id === keyOrId) return issue;\n }\n return undefined;\n}\n\nfunction requireIssue(ctx: JiraCtx, keyOrId: string): JiraIssue {\n const issue = findIssue(ctx.state, keyOrId);\n if (!issue) throw new Error(`Issue ${keyOrId} not found`);\n return issue;\n}\n\nfunction createIssue(\n ctx: JiraCtx,\n input: {\n projectKey: string;\n summary: string;\n description?: AdfNode;\n labels?: string[];\n issuetype?: { name: string };\n assignee?: JiraUser;\n reporter?: JiraUser;\n priority?: { name: string };\n }\n): JiraIssue {\n const counter = (ctx.state.issueCounter[input.projectKey] ?? 0) + 1;\n ctx.state.issueCounter[input.projectKey] = counter;\n const key = `${input.projectKey}-${counter}`;\n const now = new Date().toISOString();\n\n const issue: JiraIssue = {\n id: String(ctx.state.nextIssueId++),\n key,\n projectKey: input.projectKey,\n summary: input.summary,\n description: input.description,\n status: { name: 'To Do' },\n issuetype: input.issuetype ?? { name: 'Task' },\n priority: input.priority ?? { name: 'Medium' },\n assignee: input.assignee,\n reporter: input.reporter,\n labels: input.labels ?? [],\n comments: [],\n attachments: [],\n created: now,\n updated: now,\n };\n\n ctx.state.issues.set(key, issue);\n ctx.log('info', `Created issue ${key}: ${issue.summary}`);\n return issue;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Webhook delivery\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Drop the URL (whole, then its userinfo, path and query) and each query value on its own from\n * text that may echo it. The app puts its webhook secret in the query; an error body might echo\n * the whole URL or just the value.\n */\nfunction redactQuery(text: string, url: URL): string {\n // Longest first: the href contains everything below it.\n let redacted = text;\n for (const part of [url.href, url.username && `${url.username}:${url.password}@`, url.pathname.length > 1 ? url.pathname : '', url.search]) {\n if (part) redacted = redacted.split(part).join('');\n }\n for (const value of url.searchParams.values()) {\n // Short values (\"a=1\") would mangle ordinary text; secrets in the query are long tokens.\n if (value.length < 8) continue;\n for (const form of new Set([value, encodeURIComponent(value)])) redacted = redacted.split(form).join('[redacted]');\n }\n return redacted;\n}\n\n/**\n * Deliver `jira:issue_updated` with a `labels` changelog item to every webhook\n * the app registered for it, in parallel. Jira sends labels in the changelog as\n * space-separated strings. Throws when none is registered, or when any delivery\n * fails (one error naming each failing target's origin), so a flow fails at the\n * step that tagged the ticket instead of timing out later. Delivery to several\n * subscribers is not transactional: those that succeeded have already been told.\n * Errors never include the target's path or query string.\n */\nasync function deliverIssueUpdated(ctx: JiraCtx, issue: JiraIssue, labelsAfter: string[]): Promise<void> {\n // Like Jira, deliver only to subscribers whose event list and project filter cover this issue.\n const subscribers = [...ctx.state.webhooks.values()].filter(\n (hook) => hook.events.includes(ISSUE_UPDATED) && (hook.projectKey === null || hook.projectKey === issue.projectKey)\n );\n if (subscribers.length === 0) {\n throw new Error(\n `No webhook is registered for ${ISSUE_UPDATED} on project ${issue.projectKey}; the app must register one with POST /rest/api/3/webhook before an issue can be tagged`\n );\n }\n\n const basePayload = {\n timestamp: Date.now(),\n webhookEvent: ISSUE_UPDATED,\n issue_event_type_name: 'issue_generic',\n user: EMULATED_USER,\n issue: {\n id: issue.id,\n key: issue.key,\n fields: {\n summary: issue.summary,\n status: { name: issue.status.name, statusCategory: { key: issue.status.name === 'Done' ? 'done' : 'new' } },\n labels: labelsAfter,\n project: { key: issue.projectKey },\n },\n },\n changelog: {\n id: crypto.randomUUID(),\n items: [\n {\n field: 'labels',\n fieldtype: 'jira',\n from: null,\n to: null,\n fromString: issue.labels.join(' '),\n toString: labelsAfter.join(' '),\n },\n ],\n },\n };\n\n const payload = {\n ...basePayload,\n matchedWebhookIds: subscribers.map((hook) => hook.id),\n };\n\n const results = await Promise.allSettled(subscribers.map((hook) => deliverTo(ctx, hook, issue.key, payload)));\n const failures = results.flatMap((result) => (result.status === 'rejected' ? [errorMessage(result.reason)] : []));\n if (failures.length > 0) throw new Error(failures.join('; '));\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/** POST one delivery. Errors name the target's origin only and never echo its query string. */\nasync function deliverTo(ctx: JiraCtx, hook: JiraWebhook, issueKey: string, payload: object): Promise<void> {\n const target = new URL(hook.url);\n const where = target.origin;\n let res: Response;\n try {\n res = await fetch(hook.url, {\n method: 'POST',\n // A redirect would resend the payload (and the secret in the query) to a host the app never registered.\n redirect: 'manual',\n headers: {\n 'content-type': 'application/json',\n 'x-atlassian-webhook-identifier': crypto.randomUUID(),\n // Real Jira does not send this header (the event is only in the body's `webhookEvent`).\n // The app's Jira provider reads it to classify deliveries, so the emulator sets it.\n 'x-atlassian-webhook-event': ISSUE_UPDATED,\n },\n body: JSON.stringify(payload),\n signal: AbortSignal.timeout(WEBHOOK_TIMEOUT_MS),\n });\n } catch (err) {\n throw new Error(`Webhook delivery to ${where} failed: ${redactQuery(errorMessage(err), target)}`);\n }\n if (!res.ok) {\n let text = '';\n try {\n text = await res.text();\n } catch {\n // The body aborted mid-read; the status and target are still worth reporting.\n }\n // Redact before truncating, so a secret straddling the cut can't leave a prefix behind.\n throw new Error(\n `App rejected the ${ISSUE_UPDATED} webhook at ${where} (${res.status}): ${redactQuery(text, target).slice(0, 300)}`\n );\n }\n await res.body?.cancel();\n ctx.log('info', `Delivered ${ISSUE_UPDATED} for ${issueKey} to ${where} (${res.status})`);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Route Handlers\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction jiraBaseUrl(tenant: string): string {\n return `https://${tenant}.atlassian.net`;\n}\n\nfunction formatIssueResponse(issue: JiraIssue, baseUrl: string): object {\n return {\n id: issue.id,\n key: issue.key,\n self: `${baseUrl}/rest/api/3/issue/${issue.key}`,\n fields: {\n summary: issue.summary,\n description: issue.description ?? null,\n status: issue.status,\n assignee: issue.assignee ?? null,\n reporter: issue.reporter ?? null,\n issuetype: issue.issuetype,\n priority: issue.priority ?? { name: 'Medium' },\n created: issue.created,\n updated: issue.updated,\n labels: issue.labels,\n project: { key: issue.projectKey },\n },\n };\n}\n\nconst notFound = (key: string): EmulationResponse => ({\n status: 404,\n body: { errorMessages: [`Issue ${key} not found`] },\n});\n\nfunction handleGetIssue(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const issue = findIssue(ctx.state, req.params.issueKey);\n if (!issue) return notFound(req.params.issueKey);\n return { status: 200, body: formatIssueResponse(issue, jiraBaseUrl(ctx.state.tenant)) };\n}\n\nfunction handleCreateIssue(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return parsed.error;\n const fields = parsed.data.fields ?? {};\n const projectKey = fields.project?.key;\n\n if (!projectKey || !ctx.state.projects.has(projectKey)) {\n return { status: 400, body: { errorMessages: [`Project ${projectKey} not found`] } };\n }\n\n const issue = createIssue(ctx, {\n projectKey,\n summary: fields.summary ?? '',\n // The app sends an ADF document; keep it verbatim.\n description: fields.description ?? undefined,\n labels: fields.labels ?? [],\n issuetype: fields.issuetype,\n assignee: fields.assignee ?? undefined,\n reporter: fields.reporter ?? undefined,\n priority: fields.priority ?? undefined,\n });\n\n return {\n status: 201,\n body: { id: issue.id, key: issue.key, self: `${jiraBaseUrl(ctx.state.tenant)}/rest/api/3/issue/${issue.key}` },\n };\n}\n\nfunction handleUpdateIssue(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const issue = findIssue(ctx.state, req.params.issueKey);\n if (!issue) return notFound(req.params.issueKey);\n\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return parsed.error;\n const fields = parsed.data.fields ?? {};\n\n if (fields.summary !== undefined) issue.summary = fields.summary;\n if (fields.description !== undefined) issue.description = fields.description;\n if (fields.assignee !== undefined) issue.assignee = fields.assignee;\n if (fields.priority !== undefined) issue.priority = fields.priority;\n if (fields.labels !== undefined) issue.labels = fields.labels;\n issue.updated = new Date().toISOString();\n\n ctx.log('info', `Updated issue ${issue.key}`);\n return { status: 204 };\n}\n\nfunction handleTransition(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const issue = findIssue(ctx.state, req.params.issueKey);\n if (!issue) return notFound(req.params.issueKey);\n\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return parsed.error;\n\n const transitionNames = new Map([\n ['11', 'To Do'],\n ['21', 'In Progress'],\n ['31', 'Done'],\n ]);\n const newStatus = transitionNames.get(String(parsed.data.transition?.id));\n if (newStatus) {\n issue.status = { name: newStatus };\n issue.updated = new Date().toISOString();\n ctx.log('info', `Transitioned ${issue.key} to ${newStatus}`);\n }\n\n return { status: 204 };\n}\n\nfunction handleAddComment(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const issue = findIssue(ctx.state, req.params.issueKey);\n if (!issue) return notFound(req.params.issueKey);\n\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return parsed.error;\n const body = parsed.data.body;\n const comment: JiraComment = {\n id: String(ctx.state.nextCommentId++),\n author: EMULATED_USER,\n body: typeof body === 'string' ? textToAdf(body) : body,\n created: new Date().toISOString(),\n };\n issue.comments.push(comment);\n issue.updated = comment.created;\n ctx.log('info', `Comment ${comment.id} added to ${issue.key}`);\n return { status: 201, body: comment };\n}\n\n/** Records that an attachment arrived; the multipart body itself is not retained. */\nfunction handleAddAttachment(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const issue = findIssue(ctx.state, req.params.issueKey);\n if (!issue) return notFound(req.params.issueKey);\n const id = `att-${issue.attachments.length + 1}`;\n issue.attachments.push(id);\n return {\n status: 200,\n body: [{ id, filename: id, content: `${jiraBaseUrl(ctx.state.tenant)}/secure/attachment/${id}` }],\n };\n}\n\n/** `POST /rest/api/3/webhook` — one subscriber per entry in `webhooks`, all delivering to `url`. */\nfunction handleRegisterWebhooks(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return parsed.error;\n const { url, webhooks } = parsed.data as {\n url?: unknown;\n webhooks?: Array<{ events?: unknown; jqlFilter?: unknown }>;\n };\n if (typeof url !== 'string' || !URL.canParse(url) || !Array.isArray(webhooks)) {\n return { status: 400, body: { errorMessages: ['Body must be {url, webhooks: [{events}]}'] } };\n }\n const protocol = new URL(url).protocol;\n if (protocol !== 'http:' && protocol !== 'https:') {\n return { status: 400, body: { errorMessages: [`Webhook url must be http or https, got ${protocol}`] } };\n }\n\n const webhookRegistrationResult = webhooks.map((entry) => {\n const events = Array.isArray(entry.events) ? entry.events.filter((e): e is string => typeof e === 'string') : [];\n const jqlFilter = typeof entry.jqlFilter === 'string' ? entry.jqlFilter : '';\n const projectKey = /project\\s*=\\s*\"?([A-Z][A-Z0-9_]*)\"?/i.exec(jqlFilter)?.[1] ?? null;\n const id = ctx.state.nextWebhookId++;\n ctx.state.webhooks.set(id, { id, url, events, projectKey });\n ctx.log('info', `Registered webhook ${id} (${events.join(', ')}) -> ${new URL(url).origin}`);\n return { createdWebhookId: id };\n });\n return { status: 200, body: { webhookRegistrationResult } };\n}\n\n/** `DELETE /rest/api/3/webhook` with `{webhookIds}`. */\nfunction handleDeleteWebhooks(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return parsed.error;\n const ids: unknown[] = Array.isArray(parsed.data.webhookIds) ? parsed.data.webhookIds : [];\n for (const id of ids) ctx.state.webhooks.delete(Number(id));\n return { status: 202 };\n}\n\n/**\n * Search understands exactly the clause the app generates for the Tickets page:\n * `labels = \"<label>\"`. Any other JQL returns every issue.\n */\nfunction handleSearch(req: EmulationRequest, ctx: JiraCtx): EmulationResponse {\n const parsed = req.method === 'POST' ? safeParseJson(req.body) : { ok: true as const, data: {} };\n if (!parsed.ok) return parsed.error;\n const jql: string = parsed.data.jql ?? req.url.searchParams.get('jql') ?? '';\n const labelMatch = /labels\\s*=\\s*(?:\"((?:[^\"\\\\]|\\\\.)*)\"|(\\S+))/i.exec(jql);\n const label = labelMatch ? (labelMatch[1] ?? labelMatch[2]) : undefined;\n\n const issues = Array.from(ctx.state.issues.values()).filter((i) => (label ? i.labels.includes(label) : true));\n const baseUrl = jiraBaseUrl(ctx.state.tenant);\n\n return {\n status: 200,\n body: {\n startAt: 0,\n maxResults: issues.length,\n total: issues.length,\n isLast: true,\n issues: issues.map((i) => formatIssueResponse(i, baseUrl)),\n },\n };\n}\n","/**\n * Maximo Stub\n *\n * A slice of the IBM Maximo (MAS) MBO REST API, enough for a connector to test its\n * connection, list entities, read records and create or update them with AddChange:\n *\n * - `GET /<root>/restapi/mbo/<OBJECT>`, where `<root>` is any single segment (the\n * context root a connector is configured with, such as a run-unique `maximo-<x>`).\n * - Objects: `MAXOBJECT` (the catalogue), `MAXOBJECTCFG` (the catalogue's configuration\n * table, which a Maximo client's entity picker queries with\n * `_uw=INTERNAL=0 AND ISVIEW=0 AND PERSISTENT=1`), `MAXATTRIBUTE` (attribute metadata),\n * `CLASSSTRUCTURE` (a small classification hierarchy), and seeded `ORGANIZATION`,\n * `WORKORDER`, `ASSET`, `LOCATIONS`, `SR` (maximo-stub-data.ts).\n * - Query parameters, as in the Maximo 7.6 REST API guide (\"Integrating data with\n * external applications\", REST API chapter): attribute filters (`status=APPR` is a\n * contains match, `status=~eq~APPR` or `_exactmatch=1` exact; number and yes/no\n * attributes by equality), ANDed unless\n * `_opmodeor=1`; `_uw` (a where clause of `ATTR = 'v'` clauses joined by `and`);\n * `_orderby`/`_orderbyasc`/`_orderbydesc` (comma-separated attributes);\n * `_rsStart`/`_maxItems` paging; `_compact`; and `_dropnulls=0` (or `false`), which adds the\n * attributes a row has no value for (null, `{}` when not compact). Responses are\n * always JSON (`_format` is accepted and ignored; real Maximo defaults to XML).\n * - Like Maximo, which errors only on a bad URI or resource, other parameters are\n * ignored: any other `_` system parameter (session and presentation ones such as\n * `_lid`/`_lpwd`, `_tc`, `_verbose`; `_includecols`/`_excludecols`/`_field` are\n * accepted but every attribute is returned), `lean` (an OSLC API parameter), and a filter\n * on an attribute the object lacks or with an empty value. A connector's\n * connection check can carry any of them; the recorder still shows them.\n * - What the emulator cannot evaluate answers 400/404 rather than silently\n * returning the wrong rows: an unknown object (404), another filter operator,\n * QBE value syntax (`=`, `!=`, `<`, `>` prefixes, `,` lists, `%`/`*`), a\n * modifier on an attribute such as `status.ormode`, other where syntax, a where clause\n * or order-by on an attribute the object lacks (Maximo turns both into SQL, where\n * that column is an error), a filter value that does not parse on a number\n * or yes/no attribute, a bad paging value.\n * - Response: `{\"<OBJECT>MboSet\": {rsStart, rsCount, rsTotal, \"<OBJECT>\": [...]}}`;\n * with `_compact=1` each row is plain `{ATTR: value}`, otherwise\n * `{rowstamp, Attributes: {ATTR: {content: value}}}`, where the object's unique id\n * (WORKORDERID, ASSETID, LOCATIONSID, TICKETUID) is `{content: value, resourceid: true}`.\n * The marker is the contract an observed MAS connector requires (it builds the\n * record's URI from the marked attribute); the guide documents only that compact\n * drops per-field metadata (\"_format and _compact parameters\") and that a record's\n * URI ID is its unique id (\"GET method\"), not the marker itself. Both shapes are\n * served because connectors ask for both; every write reply uses them too.\n * - `POST /<root>/restapi/mbo/<OBJECT>` on `WORKORDER`, `ASSET`, `LOCATIONS` or `SR`\n * (the objects with a unique id) writes the attributes in its form body (system\n * parameters such as `_action` may be in the query or the body):\n * `_action=AddChange` updates the row with the same primary key (WONUM+SITEID on\n * WORKORDER) or creates one, `_action=Change` only updates, and no `_action` (or\n * `Add`) only creates (actions are case-insensitive; any other is 400). It answers\n * 200 with the saved row as `{\"<OBJECT>\": row}` in the shape above, with a new\n * rowstamp on every save, the way Maximo returns the record it saved (IBM support,\n * \"Creating a Work Order and approving it using Maximo REST\", reads\n * `WORKORDER.WORKORDERID` from the reply). Like Maximo, a new row gets the next unique\n * id (WORKORDERID, ...) and its site's ORGID. A new WORKORDER defaults to STATUS=WAPPR\n * when STATUS is omitted. A missing key attribute, an unknown\n * attribute, site or site/ORGID pair, the read-only unique id, and an over-long or\n * unparseable value are 400 (a `rowstamp` field, which clients echo from a read, is the\n * record version and not an attribute: it is accepted and ignored, not stored and not\n * checked against the stored rowstamp. IBM documents a stale rowstamp failing with\n * BMXAA8229W \"updated by another user\" only for integration-framework messages (APAR\n * IJ21622), not for a REST MBO update, so no conflict is modelled), and Change on a missing row is 404. A WORKORDER STATUS\n * outside the WOSTATUS domain (WAPPR, APPR, WSCH, WMATL, WPCOND, INPRG, COMP, CLOSE, CAN,\n * HISTEDIT; IBM \"Work order statuses\") is 400 with Maximo's BMXAA4190E \"Status <value> is not\n * in the value list.\" and stores nothing. That is the only status rule modelled: IBM\n * documents a status change through the changeStatus web method (IBM support, \"Creating a\n * Work Order and approving it using Maximo REST\": \"you cannot just update the Work Order\"),\n * but no source says what a plain Add or Change that sets STATUS does, so the stub still\n * stores an in-domain STATUS as sent and does not check status transitions. ASSET,\n * LOCATIONS and SR STATUS values are not checked either. Saved rows are kept\n * per `<root>`, so each run-unique root is its own data partition: reads of that root return\n * them in place of the seeded row with the same key, or after the seeded rows. A root\n * holds at most 1,000 saved rows and the host at most 100 roots (a new root past that\n * replaces the least recently used one); a root is dropped 6 hours after its last\n * request or 24 hours after its first write, and reports as\n * active to the idle gate (`GET /_emulation/active`) while in use.\n * - `POST /<root>/restapi/mbo/<OBJECT>/<id>` (the object's unique id, e.g. WORKORDERID) updates that\n * row in place with the form body's attributes, as `_action=Change` does, with or without\n * `x-method-override: PATCH`. An unknown id is 404 (as Change on a missing row), and a body\n * that changes a key attribute (WONUM, SITEID) is 400.\n * - `POST /<osRoot>/api/os/mxapiwo/<id>` with `x-method-override: PATCH` takes\n * a JSON body containing `status` and `statusdate`, applies the WOSTATUS/date\n * validation and updates that saved work order, then returns 204. A SITEID query\n * parameter must match when supplied. This is the status-only OSLC slice, not\n * arbitrary object-structure updates or encoded OSLC resource identifiers.\n * Assigned WORKORDERIDs are host-unique because this path has no MBO tenant root;\n * roots partition test data and share the host's API-key authorization.\n * a missing saved id is 404 and an ambiguous seeded id is 409. The owning MBO\n * root retains its rows and expiry rules. Invalid inputs store nothing.\n * https://ibm-maximo-dev.github.io/maximo-restapi-documentation/crud/create_and_update/\n *\n * Every request needs the configured API key in the `apikey` header or query\n * parameter, as on MAS; otherwise HTTP 401 with Maximo's BMXAA7901E error. Any\n * other authenticated request records as unmatched in `GET /_emulation/requests`:\n * other reads get 404, and other writes (outside `<root>/restapi/mbo/<OBJECT>`) get\n * HTTP 200 `{}` and are not stored. Requests the MBO routes reject (400/404 above)\n * record as matched; find them by status.\n *\n * @module\n */\n\nimport { z } from 'zod';\nimport type { EmulationPlugin, EmulationRequest, EmulationResponse, RouteHandler } from '../plugin.js';\nimport { tokensMatch } from '../token-match.js';\nimport {\n CLASSSTRUCTURE_RECORDS,\n MAXATTRIBUTE_RECORDS,\n MAXOBJECT_RECORDS,\n MAXOBJECTCFG_RECORDS,\n MBO_OBJECTS,\n type AttributeDef,\n type MboObjectDef,\n type MboRecord,\n type MboValue,\n} from './maximo-stub-data.js';\n\nconst configSchema = z.object({\n host: z.string().min(1),\n /** The API key a connector must send; on a public host make it long and random. */\n apiKey: z.string().min(24),\n});\ntype MaximoStubConfig = z.infer<typeof configSchema>;\n/** A row as served: its values and its rowstamp. */\ntype Row = { row: MboRecord; rowstamp: string };\n/** One root's saved rows, by object then primary key. */\ntype RootState = { objects: Map<string, Map<string, Row>>; createdAt: number; touchedAt: number };\ntype MaximoStubState = {\n apiKey: string;\n roots: Map<string, RootState>;\n nextRowstamp: number;\n nextWorkOrderId: number;\n};\ntype Handler = RouteHandler<Record<string, never>, MaximoStubState>;\n\n/** Metadata objects, whose attribute set is their seeded columns. */\nconst METADATA: readonly [string, readonly MboRecord[]][] = [\n ['MAXOBJECT', MAXOBJECT_RECORDS],\n ['MAXOBJECTCFG', MAXOBJECTCFG_RECORDS],\n ['MAXATTRIBUTE', MAXATTRIBUTE_RECORDS],\n ['CLASSSTRUCTURE', CLASSSTRUCTURE_RECORDS],\n];\n\nconst RECORDS: ReadonlyMap<string, readonly MboRecord[]> = new Map([\n ...METADATA,\n ...MBO_OBJECTS.map((o): [string, readonly MboRecord[]] => [o.name, o.records]),\n]);\n\nconst columns = (rows: readonly MboRecord[]) => new Set(rows.flatMap((r) => Object.keys(r)));\n\n/** Seeded rows as served: a synthetic rowstamp from their place, stable across requests. */\nconst SEEDED: ReadonlyMap<string, readonly Row[]> = new Map(\n [...RECORDS].map(([name, rows]) => [name, rows.map((row, i): Row => ({ row, rowstamp: String(1000 + i) }))])\n);\n\n/**\n * Each business object's unique id attribute, the one Maximo marks `resourceid` in a\n * non-compact row. Each served object has exactly one BIGINT column (WORKORDERID,\n * ASSETID, ...) and it is the unique id; a BIGINT foreign key would break this. Objects whose served columns hold\n * no unique id (ORGANIZATION and the metadata objects) have none.\n */\nconst UNIQUE_IDS: ReadonlyMap<string, string> = new Map(\n MBO_OBJECTS.flatMap((o): [string, string][] => {\n const id = o.attributes.find((a) => a.type === 'BIGINT');\n return id ? [[o.name, id.name]] : [];\n })\n);\n\n/** Each object's attribute names: `_uw` and order-by on any other name are rejected, attribute filters ignored. */\nconst ATTRIBUTES: ReadonlyMap<string, ReadonlySet<string>> = new Map([\n ...METADATA.map(([name, rows]): [string, ReadonlySet<string>] => [name, columns(rows)]),\n ...MBO_OBJECTS.map((o): [string, ReadonlySet<string>] => [o.name, new Set(o.attributes.map((a) => a.name))]),\n]);\n\nclass MaximoError extends Error {\n constructor(\n readonly status: number,\n message: string,\n /** The BMXAA message id, for errors that mirror a real Maximo message */\n readonly reasonCode?: string\n ) {\n super(message);\n }\n}\n\nconst errorBody = (status: number, message: string, reasonCode?: string): EmulationResponse => ({\n status,\n body: { Error: { ...(reasonCode ? { reasonCode } : {}), message, statusCode: String(status) } },\n});\n\n/** MAS answers a missing or wrong API key with this generic login error. */\nconst UNAUTHORIZED = errorBody(\n 401,\n 'BMXAA7901E - You cannot log in at this time. Contact the system administrator.',\n 'BMXAA7901E'\n);\n\n/** A query parameter by name, case-insensitive. */\nfunction queryParam(req: EmulationRequest, name: string): string | undefined {\n const want = name.toLowerCase();\n for (const [key, value] of req.url.searchParams) if (key.toLowerCase() === want) return value;\n return undefined;\n}\n\n/** Wrap a handler so it first checks the API key (header, else query parameter). */\nfunction authed(handler: Handler): Handler {\n return (req, ctx) => {\n const provided = req.headers['apikey'] ?? queryParam(req, 'apikey') ?? '';\n return tokensMatch(provided, ctx.state.apiKey) ? handler(req, ctx) : UNAUTHORIZED;\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Filtering\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype Predicate = (row: MboRecord) => boolean;\n\nconst text = (v: MboValue | undefined) => (v === undefined ? undefined : String(v).toLowerCase());\n\n/** A boolean system parameter: `1`/`true` on, `0`/`false` off, otherwise unset. */\nfunction flag(raw: string | undefined): boolean | undefined {\n const v = raw?.toLowerCase();\n return v === '1' || v === 'true' ? true : v === '0' || v === 'false' ? false : undefined;\n}\n\nconst isAttribute = (object: string, attr: string) => ATTRIBUTES.get(object)!.has(attr);\n\n/** For `_uw` and order-by: Maximo puts both in SQL, where an unknown column is an error. */\nfunction knownAttribute(object: string, name: string): string {\n const attr = name.toUpperCase();\n if (!isAttribute(object, attr)) throw new MaximoError(400, `Unknown attribute ${attr.slice(0, 64)} on ${object}`);\n return attr;\n}\n\n/** Yes/no values Maximo accepts in a filter. */\nconst YES_NO: ReadonlyMap<string, boolean> = new Map([\n ['1', true], ['y', true], ['true', true],\n ['0', false], ['n', false], ['false', false],\n]);\n\n/**\n * An attribute's value type, from its seeded values: Maximo compares numbers and yes/no\n * attributes by equality, never as a contains match.\n */\nfunction kindOf(object: string, attr: string): 'number' | 'boolean' | 'text' {\n const value = RECORDS.get(object)!.find((row) => row[attr] !== undefined)?.[attr];\n return typeof value === 'number' ? 'number' : typeof value === 'boolean' ? 'boolean' : 'text';\n}\n\n/** `attr` equals `raw`: numerically, as yes/no, or as case-insensitive text by the attribute's type. */\nfunction equals(object: string, attr: string, raw: string): Predicate {\n const kind = kindOf(object, attr);\n if (kind === 'number') {\n const want = Number(raw);\n if (raw.trim() === '' || !Number.isFinite(want)) throw new MaximoError(400, `Invalid number for ${attr}`);\n return (row) => row[attr] === want;\n }\n if (kind === 'boolean') {\n const want = YES_NO.get(raw.toLowerCase());\n if (want === undefined) throw new MaximoError(400, `Invalid yes/no value for ${attr}; expected 1, 0, Y, N, true or false`);\n return (row) => row[attr] === want;\n }\n const want = raw.toLowerCase();\n return (row) => text(row[attr]) === want;\n}\n\n/** QBE value syntax Maximo evaluates (`=APPR`, `!=`, `>5`, `APPR,WAPPR` as OR, `%`/`*` wildcards); the emulator does not. */\nconst QBE_SYNTAX = /^[=!<>]|[,%*]/;\n\n/**\n * On a text attribute `status=APPR` contains-matches like Maximo's default;\n * `status=~eq~APPR`, or any plain filter under `_exactmatch=1`, is exact. Number and\n * yes/no attributes always compare by equality. Undefined when Maximo's QBE ignores the\n * filter: an attribute the object lacks, or an empty value.\n */\nfunction attributeFilter(object: string, name: string, raw: string, exact: boolean): Predicate | undefined {\n const attr = name.toUpperCase();\n if (raw.startsWith('~') && !raw.startsWith('~eq~')) {\n throw new MaximoError(400, 'Unsupported filter operator in emulator; only ~eq~ is served');\n }\n const value = raw.startsWith('~eq~') ? raw.slice(4) : raw;\n if (!isAttribute(object, attr) || value === '') return undefined;\n if (QBE_SYNTAX.test(value)) throw new MaximoError(400, 'Unsupported QBE value syntax in emulator; send a plain value or ~eq~');\n if (exact || raw.startsWith('~eq~') || kindOf(object, attr) !== 'text') return equals(object, attr, value);\n const want = value.toLowerCase();\n return (row) => text(row[attr])?.includes(want) ?? false;\n}\n\n/** One `ATTR = 'v'` (or `= 12`) clause, then `and` or the end. Sticky, so `and` inside a quoted value is part of it. */\nconst CLAUSE = /\\s*([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*('(?:[^']|'')*'|-?\\d+(?:\\.\\d+)?)\\s*(?:(and)\\b|$)/iy;\nconst UNSUPPORTED_UW = \"Unsupported _uw in emulator; only ATTR = 'value' clauses joined by and are served\";\n\n/** `_uw`: `ATTR = 'v'` clauses joined by `and`, case-insensitive. */\nfunction whereFilter(object: string, uw: string): Predicate {\n const clauses: Predicate[] = [];\n CLAUSE.lastIndex = 0;\n for (;;) {\n const m = CLAUSE.exec(uw);\n if (!m) throw new MaximoError(400, UNSUPPORTED_UW);\n const attr = knownAttribute(object, m[1]!);\n const literal = m[2]!;\n clauses.push(equals(object, attr, literal.startsWith(\"'\") ? literal.slice(1, -1).replace(/''/g, \"'\") : literal));\n if (!m[3]) break;\n }\n return (row) => clauses.every((c) => c(row));\n}\n\nfunction nonNegativeInt(req: EmulationRequest, name: string): number | undefined {\n const raw = queryParam(req, name);\n if (raw === undefined || raw === '') return undefined;\n if (!/^\\d{1,9}$/.test(raw)) throw new MaximoError(400, `Invalid ${name}; expected a non-negative integer`);\n return Number(raw);\n}\n\ntype Comparator = (a: MboRecord, b: MboRecord) => number;\n\n/**\n * A missing value sorts as the greatest, so last ascending and first descending, like SQL\n * NULLs on Oracle and DB2. Numbers compare numerically; anything else (including a number\n * against a string) as text by code unit, like a binary collation, so the order does not\n * depend on the host locale.\n */\nfunction compareValues(a: MboValue | undefined, b: MboValue | undefined): number {\n if (a === undefined || b === undefined) return a === b ? 0 : a === undefined ? 1 : -1;\n if (typeof a === 'number' && typeof b === 'number') return a - b;\n const x = String(a);\n const y = String(b);\n return x < y ? -1 : x > y ? 1 : 0;\n}\n\n/**\n * `_orderby`/`_orderbyasc` (ascending) and `_orderbydesc`, each a comma-separated attribute\n * list. Keys apply in the order they appear in the query string (the guide does not say how\n * the lists combine). The sort is stable, so ties keep seed order.\n */\nfunction orderBy(req: EmulationRequest, object: string): Comparator | undefined {\n const keys: { attr: string; sign: number }[] = [];\n for (const [key, value] of req.url.searchParams) {\n const name = key.toLowerCase();\n const sign = name === '_orderby' || name === '_orderbyasc' ? 1 : name === '_orderbydesc' ? -1 : 0;\n if (sign === 0) continue;\n for (const part of value.split(',')) if (part.trim()) keys.push({ attr: knownAttribute(object, part.trim()), sign });\n }\n if (keys.length === 0) return undefined;\n return (a, b) => {\n for (const { attr, sign } of keys) {\n const c = compareValues(a[attr], b[attr]);\n if (c !== 0) return sign * c;\n }\n return 0;\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Saved rows\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst MAX_ROWS_PER_ROOT = 1000;\nconst MAX_ROOTS = 100;\nconst ROOT_IDLE_MS = 6 * 3_600_000;\nconst ROOT_MAX_AGE_MS = 24 * 3_600_000;\n\ninterface WritableObject {\n def: MboObjectDef;\n attributes: ReadonlyMap<string, AttributeDef>;\n keyAttributes: readonly string[];\n /** The unique id Maximo assigns (the object's BIGINT attribute); read-only. */\n idAttribute: string;\n /** Seeded rows by primary key. */\n seededByKey: ReadonlyMap<string, Row>;\n seededMaxId: number;\n}\n\nconst primaryKey = (keyAttributes: readonly string[], row: Readonly<Record<string, MboValue | undefined>>) =>\n JSON.stringify(keyAttributes.map((a) => row[a] ?? null));\n\n/** The objects writes are served for: business objects with a unique id. */\nconst WRITABLE: ReadonlyMap<string, WritableObject> = new Map(\n MBO_OBJECTS.flatMap((def): [string, WritableObject][] => {\n const idAttribute = UNIQUE_IDS.get(def.name);\n if (!idAttribute) return [];\n const keyAttributes = def.attributes.filter((a) => a.keySeq !== undefined).map((a) => a.name);\n const seeded = SEEDED.get(def.name)!;\n return [\n [\n def.name,\n {\n def,\n attributes: new Map(def.attributes.map((a) => [a.name, a])),\n keyAttributes,\n idAttribute,\n seededByKey: new Map(seeded.map((r) => [primaryKey(keyAttributes, r.row), r])),\n seededMaxId: Math.max(0, ...seeded.map((r) => Number(r.row[idAttribute] ?? 0))),\n },\n ],\n ];\n })\n);\n\n/** Each site's organization, from the seeded rows. */\nconst SITE_ORGS: ReadonlyMap<string, MboValue> = new Map(\n MBO_OBJECTS.flatMap((o) => o.records).flatMap((r) => (r['SITEID'] && r['ORGID'] ? [[String(r['SITEID']), r['ORGID']] as const] : []))\n);\n\n/** Drop roots idle past the TTL or older than the max age. */\nfunction sweep(state: MaximoStubState): void {\n const now = Date.now();\n for (const [name, root] of state.roots) {\n if (now - root.touchedAt > ROOT_IDLE_MS || now - root.createdAt > ROOT_MAX_AGE_MS) state.roots.delete(name);\n }\n}\n\n/**\n * An object's rows for one root: the seeded rows, each replaced by the row saved under\n * its key, then the other saved rows.\n */\nfunction rowsFor(state: MaximoStubState, root: string, object: string): readonly Row[] {\n const seeded = SEEDED.get(object)!;\n const saved = state.roots.get(root)?.objects.get(object);\n const writable = WRITABLE.get(object);\n if (!saved || !writable) return seeded;\n const rows = seeded.map((r) => saved.get(primaryKey(writable.keyAttributes, r.row)) ?? r);\n for (const [key, r] of saved) if (!writable.seededByKey.has(key)) rows.push(r);\n return rows;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Query Records\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * `allAttributes` (`_dropnulls=0`) adds the attributes the row has no value for. Not compact,\n * the unique id attribute also carries `resourceid: true`, the field metadata compact drops.\n */\nfunction serialize(\n { row, rowstamp }: Row,\n compact: boolean,\n allAttributes: ReadonlySet<string> | undefined,\n uniqueId: string | undefined\n): object {\n const nulls = allAttributes ? [...allAttributes].filter((a) => !(a in row)) : [];\n if (compact) return { ...row, ...Object.fromEntries(nulls.map((a) => [a, null])) };\n const attributes = Object.fromEntries([\n ...Object.entries(row).map(([k, v]) => [k, k === uniqueId ? { content: v, resourceid: true } : { content: v }]),\n ...nulls.map((a) => [a, {}]),\n ]);\n return { rowstamp, Attributes: attributes };\n}\n\n/** The `_compact` and `_dropnulls` options of a response. */\nfunction serializer(req: EmulationRequest, object: string): (row: Row) => object {\n const compact = flag(queryParam(req, '_compact')) === true;\n // Maximo drops null attributes unless `_dropnulls=0`.\n const allAttributes = flag(queryParam(req, '_dropnulls')) === false ? ATTRIBUTES.get(object) : undefined;\n const uniqueId = UNIQUE_IDS.get(object);\n return (row) => serialize(row, compact, allAttributes, uniqueId);\n}\n\nfunction queryRecords(req: EmulationRequest, state: MaximoStubState): EmulationResponse {\n const object = req.params['object']!.toUpperCase();\n if (!RECORDS.has(object)) throw new MaximoError(404, `Unsupported object in emulator: ${object.slice(0, 64)}`);\n const records = rowsFor(state, req.params['root']!, object);\n\n const exact = flag(queryParam(req, '_exactmatch')) === true;\n const where: Predicate[] = [];\n const attributeFilters: Predicate[] = [];\n for (const [key, value] of req.url.searchParams) {\n const name = key.toLowerCase();\n if (name === '_uw') where.push(whereFilter(object, value));\n // Other `_` system parameters and the API key are not row filters.\n else if (!name.startsWith('_') && name !== 'apikey') {\n // `status.ormode=1` and other modifiers on an attribute change how its filters combine;\n // other dotted names (`oslc.select`, an unknown attribute's modifier) are ignored like unknown attributes.\n if (name.includes('.') && isAttribute(object, name.split('.')[0]!.toUpperCase())) {\n throw new MaximoError(400, `Unsupported attribute modifier in emulator: ${name.slice(0, 64)}`);\n }\n const filter = attributeFilter(object, key, value, exact);\n if (filter) attributeFilters.push(filter);\n }\n }\n // `_opmodeor=1` ORs the attribute filters; `_uw` is always ANDed with them. With no\n // filter left (all ignored), every row matches, as with no filter at all.\n const or = flag(queryParam(req, '_opmodeor')) === true;\n const matchAttributes: Predicate = (row) =>\n attributeFilters.length === 0 || (or ? attributeFilters.some((f) => f(row)) : attributeFilters.every((f) => f(row)));\n const indexed = records.filter(({ row }) => matchAttributes(row) && where.every((f) => f(row)));\n const compare = orderBy(req, object);\n if (compare) indexed.sort((a, b) => compare(a.row, b.row));\n\n const rsStart = nonNegativeInt(req, '_rsStart') ?? 0;\n const maxItems = nonNegativeInt(req, '_maxItems');\n const page = indexed.slice(rsStart, maxItems === undefined ? undefined : rsStart + maxItems);\n return {\n status: 200,\n body: {\n [`${object}MboSet`]: {\n rsStart,\n rsCount: page.length,\n rsTotal: indexed.length,\n [object]: page.map(serializer(req, object)),\n },\n },\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Writes\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** A form value as the attribute's type stores it; undefined clears the attribute. */\nfunction attributeValue(object: string, def: AttributeDef, raw: string): MboValue | undefined {\n if (raw === '') return undefined;\n if (def.type === 'INTEGER') {\n const n = Number(raw);\n if (raw.trim() === '' || !Number.isInteger(n)) throw new MaximoError(400, `Invalid integer for ${def.name}`);\n return n;\n }\n if (def.type === 'YORN') {\n const yes = YES_NO.get(raw.toLowerCase());\n if (yes === undefined) throw new MaximoError(400, `Invalid yes/no value for ${def.name}; expected 1, 0, Y, N, true or false`);\n return yes;\n }\n if (def.type === 'DATETIME') {\n if (Number.isNaN(Date.parse(raw))) throw new MaximoError(400, `Invalid date for ${def.name}`);\n return raw;\n }\n const value = def.type === 'UPPER' ? raw.toUpperCase() : raw;\n if (value.length > def.length) throw new MaximoError(400, `${def.name} on ${object} is longer than ${def.length} characters`);\n // Maximo's message for a value outside the attribute's domain is BMXAA4190E \"<title> <value> is not\n // in the value list.\", as in IBM support 7027815 (\"BMXAA4190E - Status BOBA is not in the value\n // list.\") and APAR IJ31643 (\"BMXAA4190E - Type CAUSE is not in the value list.\").\n if (def.domain && !def.domain.has(value)) {\n throw new MaximoError(400, `BMXAA4190E - ${def.title} ${value.slice(0, 64)} is not in the value list.`, 'BMXAA4190E');\n }\n return value;\n}\n\n/** `_action` (case-insensitive): which of a missing and an existing row it may save. */\nconst WRITE_MODES: ReadonlyMap<string, { create: boolean; update: boolean }> = new Map([\n ['', { create: true, update: false }],\n ['add', { create: true, update: false }],\n ['change', { create: false, update: true }],\n ['addchange', { create: true, update: true }],\n]);\n\nfunction writeRecord(req: EmulationRequest, state: MaximoStubState): EmulationResponse {\n const object = req.params['object']!.toUpperCase();\n const writable = WRITABLE.get(object);\n if (!writable) throw new MaximoError(404, `Unsupported object in emulator: ${object.slice(0, 64)}`);\n // Like Maximo (servlet parameters), system parameters may come in the query or the form body.\n const form = new URLSearchParams(req.body ?? '');\n // Id route (`.../<OBJECT>/<id>`): always a Change of that row; `_action` and `x-method-override` are ignored.\n const id = req.params['id'];\n const target = id === undefined ? undefined : rowsFor(state, req.params['root']!, object).find((r) => String(r.row[writable.idAttribute]) === id);\n if (id !== undefined && !target) throw new MaximoError(404, `No ${object} record with ${writable.idAttribute} ${id.slice(0, 64)}`);\n const action = id !== undefined ? 'Change' : (queryParam(req, '_action') ?? form.get('_action') ?? '');\n const mode = WRITE_MODES.get(action.toLowerCase());\n if (!mode) throw new MaximoError(400, `Unsupported _action in emulator: ${action.slice(0, 64)}`);\n\n const changes = new Map<string, MboValue | undefined>();\n for (const [key, raw] of form) {\n // System parameters (`_format`, `_lid`, ...) and the API key are not attributes.\n if (key.startsWith('_') || key.toLowerCase() === 'apikey') continue;\n // Clients echo the record's rowstamp. It is Maximo's record version, not an attribute: accepted, never stored.\n if (key.toLowerCase() === 'rowstamp') continue;\n const def = writable.attributes.get(key.toUpperCase());\n if (!def) throw new MaximoError(400, `Unknown attribute ${key.toUpperCase().slice(0, 64)} on ${object}`);\n if (def.name === writable.idAttribute) throw new MaximoError(400, `${def.name} on ${object} is read-only`);\n changes.set(def.name, attributeValue(object, def, raw));\n }\n if (target) {\n for (const name of writable.keyAttributes) {\n if (changes.has(name) && changes.get(name) !== target.row[name]) throw new MaximoError(400, `${name} on ${object} cannot be changed`);\n changes.set(name, target.row[name]);\n }\n }\n for (const name of writable.keyAttributes) {\n if (changes.get(name) === undefined) {\n throw new MaximoError(400, `A value is required for the ${writable.attributes.get(name)!.title} field on the ${object} object.`);\n }\n }\n\n const rootName = req.params['root']!;\n const saved = state.roots.get(rootName)?.objects.get(object);\n const key = primaryKey(writable.keyAttributes, Object.fromEntries(changes));\n const existing = saved?.get(key) ?? writable.seededByKey.get(key);\n if (existing && !mode.update) throw new MaximoError(400, `A ${object} record with this key already exists`);\n if (!existing && !mode.create) throw new MaximoError(404, `No ${object} record with this key`);\n const row: Record<string, MboValue> = { ...existing?.row };\n for (const [name, value] of changes) {\n if (value === undefined) delete row[name];\n else row[name] = value;\n }\n if (writable.def.siteOrgType === 'SITE' && row['SITEID'] !== undefined) {\n const site = String(row['SITEID']);\n const org = SITE_ORGS.get(site);\n if (org === undefined) throw new MaximoError(400, `Site ${site.slice(0, 64)} is not valid`);\n if (row['ORGID'] !== undefined && row['ORGID'] !== org) throw new MaximoError(400, `Site ${site} is not in organization ${String(row['ORGID']).slice(0, 64)}`);\n row['ORGID'] = org;\n }\n if (!existing) {\n // Maximo's out-of-the-box initial work-order status (IBM, \"Work order statuses\").\n if (object === 'WORKORDER' && !changes.has('STATUS')) row['STATUS'] = 'WAPPR';\n const savedIds = [...(saved?.values() ?? [])].map((r) => Number(r.row[writable.idAttribute] ?? 0));\n row[writable.idAttribute] = object === 'WORKORDER' ? state.nextWorkOrderId++ : Math.max(writable.seededMaxId, ...savedIds) + 1;\n }\n\n const result = saveRecord(state, rootName, object, key, row);\n return { status: 200, body: { [object]: serializer(req, object)(result) } };\n}\n\n/** Save through the same tenant limits and rowstamp rules for attribute and web-method writes. */\nfunction saveRecord(state: MaximoStubState, rootName: string, object: string, key: string, row: Readonly<MboRecord>): Row {\n const root = state.roots.get(rootName);\n if (!root?.objects.get(object)?.has(key)) {\n const rootRows = root ? [...root.objects.values()].reduce((n, m) => n + m.size, 0) : 0;\n if (rootRows >= MAX_ROWS_PER_ROOT) throw new MaximoError(400, `Emulator write limit reached (${MAX_ROWS_PER_ROOT} rows per root)`);\n }\n const result: Row = { row, rowstamp: String(state.nextRowstamp++) };\n const now = Date.now();\n let target = root;\n if (!target) {\n // At the limit, a new root replaces the least recently used one rather than failing every new run.\n if (state.roots.size >= MAX_ROOTS) {\n const [lru] = [...state.roots].reduce((a, b) => (b[1].touchedAt < a[1].touchedAt ? b : a));\n state.roots.delete(lru);\n }\n state.roots.set(rootName, (target = { objects: new Map(), createdAt: now, touchedAt: now }));\n }\n let objectRows = target.objects.get(object);\n if (!objectRows) target.objects.set(object, (objectRows = new Map()));\n objectRows.set(key, result);\n target.touchedAt = now;\n return result;\n}\n\n/** The status-only OSLC update emitted after an MBO AddChange, on a separate API path. */\nfunction updateOslcStatus(req: EmulationRequest, state: MaximoStubState): EmulationResponse {\n if (req.headers['x-method-override']?.toUpperCase() !== 'PATCH') {\n throw new MaximoError(400, 'OSLC status updates require x-method-override: PATCH');\n }\n let body: unknown;\n try {\n body = JSON.parse(req.body ?? '');\n } catch {\n throw new MaximoError(400, 'Invalid JSON status update');\n }\n const parsed = z.object({ status: z.string().min(1), statusdate: z.string().min(1) }).strict().safeParse(body);\n if (!parsed.success) throw new MaximoError(400, 'Expected status and statusdate in the OSLC status update');\n const writable = WRITABLE.get('WORKORDER')!;\n const status = attributeValue('WORKORDER', writable.attributes.get('STATUS')!, parsed.data.status)!;\n const date = attributeValue('WORKORDER', writable.attributes.get('STATUSDATE')!, parsed.data.statusdate)!;\n const id = req.params['id']!;\n const matches: { root: string; key: string; value: Row }[] = [];\n for (const [root, tenant] of state.roots) {\n for (const [key, value] of tenant.objects.get('WORKORDER') ?? []) {\n if (String(value.row['WORKORDERID']) === id) matches.push({ root, key, value });\n }\n }\n if (matches.length === 0) throw new MaximoError(404, `No saved WORKORDER resource ${id.slice(0, 64)}`);\n if (matches.length !== 1) throw new MaximoError(409, 'WORKORDER id is ambiguous across emulator roots');\n const match = matches[0]!;\n const site = queryParam(req, 'SITEID');\n if (site !== undefined && site !== match.value.row['SITEID']) throw new MaximoError(404, 'WORKORDER is not in the requested site');\n saveRecord(state, match.root, 'WORKORDER', match.key, { ...match.value.row, STATUS: status, STATUSDATE: date });\n return { status: 204 };\n}\n\n/** Sweep idle roots, mark this one used, and answer MaximoError as Maximo's error body. */\nfunction mbo(handler: (req: EmulationRequest, state: MaximoStubState) => EmulationResponse): Handler {\n return authed((req, ctx) => {\n sweep(ctx.state);\n const rootName = req.params['root'];\n const root = rootName === undefined ? undefined : ctx.state.roots.get(rootName);\n if (root) root.touchedAt = Date.now();\n try {\n return handler(req, ctx.state);\n } catch (err) {\n if (err instanceof MaximoError) return errorBody(err.status, err.message, err.reasonCode);\n throw err;\n }\n });\n}\n\n/**\n * Anything else records as unmatched, so real traffic shows what to add next. A read\n * outside the served slice gets 404 rather than an empty answer. A write gets 200 `{}`\n * and is not stored: tests drive a connector's writes into the stub and assert on the\n * request log, so the connector must not fail the run on them.\n */\nconst recordOnly = authed((req) =>\n req.method === 'GET'\n ? errorBody(404, `Unsupported request in emulator: GET ${req.url.pathname.slice(0, 200)}`)\n : { status: 200, body: {} }\n);\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Plugin\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const maximoStubPlugin: EmulationPlugin<MaximoStubConfig, Record<string, never>, MaximoStubState> = {\n id: 'maximo-stub',\n name: 'Maximo MBO REST Stub',\n version: '1.8.0',\n\n domains: (config) => [config.host.toLowerCase()],\n needsBrowserIntercept: false,\n\n routes: [\n { method: 'GET', path: '/:root/restapi/mbo/:object', handler: mbo(queryRecords) },\n { method: 'POST', path: '/:root/restapi/mbo/:object', handler: mbo(writeRecord) },\n { method: 'POST', path: '/:root/restapi/mbo/:object/:id', handler: mbo(writeRecord) },\n { method: 'POST', path: '/:osRoot/api/os/mxapiwo/:id', handler: mbo(updateOslcStatus) },\n { method: '*', path: '*', handler: recordOnly },\n ],\n\n initialize: (config) => ({\n apiKey: configSchema.parse(config).apiKey,\n roots: new Map(),\n // Above every seeded row's rowstamp (1000 + its place).\n nextRowstamp: 100_000,\n // The fixed OSLC path carries no MBO tenant root, so assigned ids must be host-unique.\n nextWorkOrderId: WRITABLE.get('WORKORDER')!.seededMaxId + 1,\n }),\n\n countActive(ctx, sinceMs) {\n sweep(ctx.state);\n return [...ctx.state.roots.values()].filter((r) => r.touchedAt >= sinceMs).length;\n },\n};\n","/**\n * Inline catalogue and seeded records for the Maximo stub (maximo-stub.ts).\n * Neutral example data only: organization ACME, site SITE1.\n *\n * @module\n */\n\n/** A Maximo attribute value as the MBO REST API serializes it in JSON. */\nexport type MboValue = string | number | boolean;\n/** One MBO row, keyed by upper-case attribute name. */\nexport type MboRecord = Readonly<Record<string, MboValue>>;\n\nexport interface AttributeDef {\n name: string;\n /** MAXATTRIBUTE.MAXTYPE (ALN, UPPER, INTEGER, DECIMAL, DATETIME, YORN, ...) */\n type: string;\n length: number;\n required: boolean;\n title: string;\n /** MAXATTRIBUTE.PRIMARYKEYCOLSEQNO, for primary-key columns only */\n keySeq?: number;\n /** The values a write may set, for an attribute bound to a domain the stub models (see WOSTATUS); compared with the stored (for UPPER, upper-cased) value */\n domain?: ReadonlySet<string>;\n}\n\nexport interface MboObjectDef {\n name: string;\n description: string;\n /** MAXOBJECT.SITEORGTYPE */\n siteOrgType: 'SITE' | 'ORG' | 'SYSTEM';\n /** MAXOBJECTCFG.SERVICENAME: the MAXSERVICE owning the object's Java package (psdi.app.site → SITE, psdi.app.ticket → TICKET) */\n service: string;\n attributes: readonly AttributeDef[];\n records: readonly MboRecord[];\n}\n\nconst attr = (name: string, type: string, length: number, required: boolean, title: string, keySeq?: number): AttributeDef => ({\n name,\n type,\n length,\n required,\n title,\n ...(keySeq === undefined ? {} : { keySeq }),\n});\n\n/**\n * WOSTATUS, the synonym domain WORKORDER.STATUS is bound to: its internal values, as IBM\n * documents them (\"Work order statuses\", Maximo Asset Management 7.6.1.2). A real site may\n * add synonyms for these values; the stub serves only the out-of-the-box ones, whose\n * default synonym is the internal value itself.\n */\nconst WOSTATUS: ReadonlySet<string> = new Set(['WAPPR', 'APPR', 'WSCH', 'WMATL', 'WPCOND', 'INPRG', 'COMP', 'CLOSE', 'CAN', 'HISTEDIT']);\n\nconst SITE = { ORGID: 'ACME', SITEID: 'SITE1' };\n\n/** The business objects the stub serves, in MAXOBJECT order. */\nexport const MBO_OBJECTS: readonly MboObjectDef[] = [\n {\n name: 'ORGANIZATION',\n description: 'Organizations',\n siteOrgType: 'SYSTEM',\n service: 'SITE',\n attributes: [\n attr('ORGID', 'UPPER', 8, true, 'Organization', 1),\n attr('DESCRIPTION', 'ALN', 100, false, 'Description'),\n attr('ACTIVE', 'YORN', 1, true, 'Active'),\n attr('BASECURRENCY1', 'UPPER', 8, true, 'Base Currency 1'),\n ],\n records: [{ ORGID: 'ACME', DESCRIPTION: 'Acme Utilities', ACTIVE: true, BASECURRENCY1: 'USD' }],\n },\n {\n name: 'WORKORDER',\n description: 'Work Orders',\n siteOrgType: 'SITE',\n service: 'WORKORDER',\n attributes: [\n attr('WONUM', 'UPPER', 25, true, 'Work Order', 1),\n attr('SITEID', 'UPPER', 8, true, 'Site', 2),\n attr('ORGID', 'UPPER', 8, true, 'Organization'),\n attr('DESCRIPTION', 'ALN', 100, false, 'Description'),\n { ...attr('STATUS', 'UPPER', 16, true, 'Status'), domain: WOSTATUS },\n attr('STATUSDATE', 'DATETIME', 10, false, 'Status Date'),\n attr('WORKTYPE', 'UPPER', 5, false, 'Work Type'),\n attr('ASSETNUM', 'UPPER', 25, false, 'Asset'),\n attr('LOCATION', 'UPPER', 50, false, 'Location'),\n attr('WOPRIORITY', 'INTEGER', 12, false, 'Priority'),\n attr('REPORTDATE', 'DATETIME', 10, false, 'Reported Date'),\n attr('WORKORDERID', 'BIGINT', 19, true, 'Work Order ID'),\n ],\n records: [\n { WONUM: '1001', ...SITE, DESCRIPTION: 'Inspect main pump', STATUS: 'APPR', WORKTYPE: 'PM', ASSETNUM: 'PUMP-100', LOCATION: 'PLANT-A', WOPRIORITY: 2, REPORTDATE: '2026-01-05T08:00:00-05:00', WORKORDERID: 501 },\n { WONUM: '1002', ...SITE, DESCRIPTION: 'Replace valve seal', STATUS: 'WAPPR', WORKTYPE: 'CM', ASSETNUM: 'VALVE-200', LOCATION: 'PLANT-A', WOPRIORITY: 1, REPORTDATE: '2026-01-06T09:30:00-05:00', WORKORDERID: 502 },\n { WONUM: '1003', ...SITE, DESCRIPTION: 'Lubricate conveyor bearings', STATUS: 'APPR', WORKTYPE: 'PM', ASSETNUM: 'CONV-300', LOCATION: 'PLANT-B', WOPRIORITY: 3, REPORTDATE: '2026-01-07T10:15:00-05:00', WORKORDERID: 503 },\n { WONUM: '1004', ...SITE, DESCRIPTION: 'Repair hydrant leak', STATUS: 'INPRG', WORKTYPE: 'EM', ASSETNUM: 'HYD-400', LOCATION: 'STREET-12', WOPRIORITY: 1, REPORTDATE: '2026-01-08T14:45:00-05:00', WORKORDERID: 504 },\n { WONUM: '1005', ...SITE, DESCRIPTION: 'Calibrate flow meter', STATUS: 'COMP', WORKTYPE: 'PM', ASSETNUM: 'METER-500', LOCATION: 'PLANT-B', WOPRIORITY: 3, REPORTDATE: '2026-01-09T07:20:00-05:00', WORKORDERID: 505 },\n ],\n },\n {\n name: 'ASSET',\n description: 'Assets',\n siteOrgType: 'SITE',\n service: 'ASSET',\n attributes: [\n attr('ASSETNUM', 'UPPER', 25, true, 'Asset', 1),\n attr('SITEID', 'UPPER', 8, true, 'Site', 2),\n attr('ORGID', 'UPPER', 8, true, 'Organization'),\n attr('DESCRIPTION', 'ALN', 100, false, 'Description'),\n attr('STATUS', 'UPPER', 20, true, 'Status'),\n attr('LOCATION', 'UPPER', 50, false, 'Location'),\n attr('SERIALNUM', 'ALN', 64, false, 'Serial #'),\n attr('ASSETID', 'BIGINT', 19, true, 'Asset ID'),\n ],\n records: [\n { ASSETNUM: 'PUMP-100', ...SITE, DESCRIPTION: 'Main water pump', STATUS: 'OPERATING', LOCATION: 'PLANT-A', SERIALNUM: 'SN-1001', ASSETID: 201 },\n { ASSETNUM: 'VALVE-200', ...SITE, DESCRIPTION: 'Isolation valve', STATUS: 'OPERATING', LOCATION: 'PLANT-A', SERIALNUM: 'SN-2002', ASSETID: 202 },\n { ASSETNUM: 'CONV-300', ...SITE, DESCRIPTION: 'Conveyor belt line 3', STATUS: 'OPERATING', LOCATION: 'PLANT-B', SERIALNUM: 'SN-3003', ASSETID: 203 },\n { ASSETNUM: 'HYD-400', ...SITE, DESCRIPTION: 'Fire hydrant', STATUS: 'BROKEN', LOCATION: 'STREET-12', SERIALNUM: 'SN-4004', ASSETID: 204 },\n { ASSETNUM: 'METER-500', ...SITE, DESCRIPTION: 'Booster pump flow meter', STATUS: 'NOT READY', LOCATION: 'PLANT-B', SERIALNUM: 'SN-5005', ASSETID: 205 },\n ],\n },\n {\n name: 'LOCATIONS',\n description: 'Locations',\n siteOrgType: 'SITE',\n service: 'LOCATION',\n attributes: [\n attr('LOCATION', 'UPPER', 50, true, 'Location', 1),\n attr('SITEID', 'UPPER', 8, true, 'Site', 2),\n attr('ORGID', 'UPPER', 8, true, 'Organization'),\n attr('DESCRIPTION', 'ALN', 100, false, 'Description'),\n attr('TYPE', 'UPPER', 16, true, 'Type'),\n attr('STATUS', 'UPPER', 20, true, 'Status'),\n attr('LOCATIONSID', 'BIGINT', 19, true, 'Locations ID'),\n ],\n records: [\n { LOCATION: 'PLANT-A', ...SITE, DESCRIPTION: 'Treatment plant A', TYPE: 'OPERATING', STATUS: 'OPERATING', LOCATIONSID: 301 },\n { LOCATION: 'PLANT-B', ...SITE, DESCRIPTION: 'Treatment plant B', TYPE: 'OPERATING', STATUS: 'OPERATING', LOCATIONSID: 302 },\n { LOCATION: 'STREET-12', ...SITE, DESCRIPTION: '12th Street distribution', TYPE: 'OPERATING', STATUS: 'OPERATING', LOCATIONSID: 303 },\n ],\n },\n {\n name: 'SR',\n description: 'Service Requests',\n siteOrgType: 'SITE',\n service: 'TICKET',\n attributes: [\n attr('TICKETID', 'UPPER', 10, true, 'Service Request', 1),\n attr('CLASS', 'UPPER', 16, true, 'Class', 2),\n attr('SITEID', 'UPPER', 8, false, 'Site'),\n attr('ORGID', 'UPPER', 8, false, 'Organization'),\n attr('DESCRIPTION', 'ALN', 100, false, 'Summary'),\n attr('STATUS', 'UPPER', 10, true, 'Status'),\n attr('REPORTEDBY', 'UPPER', 30, false, 'Reported By'),\n attr('REPORTDATE', 'DATETIME', 10, false, 'Reported Date'),\n attr('TICKETUID', 'BIGINT', 19, true, 'Ticket ID'),\n ],\n records: [\n { TICKETID: 'SR-2001', CLASS: 'SR', ...SITE, DESCRIPTION: 'Low water pressure on Elm St', STATUS: 'NEW', REPORTEDBY: 'JDOE', REPORTDATE: '2026-01-10T11:00:00-05:00', TICKETUID: 401 },\n { TICKETID: 'SR-2002', CLASS: 'SR', ...SITE, DESCRIPTION: 'Streetlight out near park', STATUS: 'QUEUED', REPORTEDBY: 'ASMITH', REPORTDATE: '2026-01-11T16:20:00-05:00', TICKETUID: 402 },\n ],\n },\n];\n\n/** MAXOBJECT rows: the object catalogue a connector's entity picker lists. */\nexport const MAXOBJECT_RECORDS: readonly MboRecord[] = MBO_OBJECTS.map((o) => ({\n OBJECTNAME: o.name,\n DESCRIPTION: o.description,\n ENTITYNAME: o.name,\n SITEORGTYPE: o.siteOrgType,\n PERSISTENT: true,\n}));\n\n/**\n * MAXOBJECTCFG rows: the object configuration table behind MAXOBJECT. A Maximo client's\n * entity picker lists it with `_uw=INTERNAL=0 AND ISVIEW=0 AND PERSISTENT=1`; every\n * served object is a persistent, non-internal table.\n */\nexport const MAXOBJECTCFG_RECORDS: readonly MboRecord[] = MBO_OBJECTS.map((o) => ({\n OBJECTNAME: o.name,\n DESCRIPTION: o.description,\n ENTITYNAME: o.name,\n SERVICENAME: o.service,\n SITEORGTYPE: o.siteOrgType,\n PERSISTENT: true,\n ISVIEW: false,\n INTERNAL: false,\n}));\n\n/**\n * CLASSSTRUCTURE rows: a small classification hierarchy for the seeded assets. HIERARCHYPATH\n * joins the CLASSIFICATIONIDs from the top with ` \\ ` (the form Maximo shows for a classification).\n */\nexport const CLASSSTRUCTURE_RECORDS: readonly MboRecord[] = [\n { CLASSSTRUCTUREID: '1001', CLASSIFICATIONID: 'PUMP', DESCRIPTION: 'Pumps', HIERARCHYPATH: 'PUMP', HASCHILDREN: true, ORGID: 'ACME' },\n { CLASSSTRUCTUREID: '1002', CLASSIFICATIONID: 'CENTRIFUGAL', DESCRIPTION: 'Centrifugal pumps', HIERARCHYPATH: 'PUMP \\\\ CENTRIFUGAL', PARENT: '1001', HASCHILDREN: false, ORGID: 'ACME' },\n { CLASSSTRUCTUREID: '1003', CLASSIFICATIONID: 'VALVE', DESCRIPTION: 'Valves', HIERARCHYPATH: 'VALVE', HASCHILDREN: false, ORGID: 'ACME' },\n { CLASSSTRUCTUREID: '1004', CLASSIFICATIONID: 'HYDRANT', DESCRIPTION: 'Fire hydrants', HIERARCHYPATH: 'HYDRANT', HASCHILDREN: false, ORGID: 'ACME' },\n];\n\n/** MAXATTRIBUTE rows: each object's attribute metadata. */\nexport const MAXATTRIBUTE_RECORDS: readonly MboRecord[] = MBO_OBJECTS.flatMap((o) =>\n o.attributes.map((a) => ({\n OBJECTNAME: o.name,\n ATTRIBUTENAME: a.name,\n MAXTYPE: a.type,\n LENGTH: a.length,\n REQUIRED: a.required,\n TITLE: a.title,\n PERSISTENT: true,\n ...(a.keySeq === undefined ? {} : { PRIMARYKEYCOLSEQNO: a.keySeq }),\n }))\n);\n","import { createHmac } from 'node:crypto';\n\nexport const GOOGLE_AUTHORIZE_LABEL = 'cofactor-google-authorize';\n\n/**\n * A key derived from the control token for one narrow purpose: base64url(HMAC-SHA256(key = controlToken, msg = label)).\n * It can be handed to a remote browser executor without exposing the control token.\n */\nexport function scopedKey(controlToken: string, label: string): string {\n return createHmac('sha256', controlToken).update(label).digest('base64url');\n}\n","/**\n * Per-copy sign-in gate for the `oidc` emulator.\n *\n * Both values derive from the copy's control token (nothing new is stored):\n * the sign-in key travels in the \"Open sign-in\" link; the gate value is the\n * cookie a browser holds after opening it, and the bearer automated paths\n * send. They differ so the key in a URL is never the cookie. The raw control\n * token is never accepted by the gate.\n *\n * @module\n */\n\nimport { scopedKey } from './authorize-key.js';\nimport { tokensMatch } from './token-match.js';\n\nexport const GATE_COOKIE = 'cofactor_oidc_gate';\n\nexport function signInKey(controlToken: string): string {\n return scopedKey(controlToken, 'cofactor-oidc-sign-in');\n}\n\nexport function gateCookieValue(controlToken: string): string {\n return scopedKey(controlToken, 'cofactor-oidc-gate');\n}\n\nexport function signInUrl(emulationOrigin: string, controlToken: string): string {\n return `${emulationOrigin}/oidc/enter?key=${signInKey(controlToken)}`;\n}\n\n/**\n * True for a Cookie header carrying `GATE_COOKIE=<gateCookieValue>`, or\n * `Authorization: Bearer <gateCookieValue>`. `headers` are keyed lowercase.\n */\nexport function gateAllows(headers: Record<string, string>, controlToken: string): boolean {\n const expected = gateCookieValue(controlToken);\n\n const authorization = headers['authorization'] ?? '';\n if (authorization.startsWith('Bearer ') && tokensMatch(authorization.slice('Bearer '.length).trim(), expected)) {\n return true;\n }\n\n for (const pair of (headers['cookie'] ?? '').split(';')) {\n const separator = pair.indexOf('=');\n if (separator < 0) continue;\n if (pair.slice(0, separator).trim() === GATE_COOKIE && tokensMatch(pair.slice(separator + 1).trim(), expected)) {\n return true;\n }\n }\n return false;\n}\n","/**\n * Generic OpenID Connect provider emulation plugin.\n *\n * One standards-conformant provider that any OIDC relying party (Auth0, Okta,\n * Cognito, Keycloak, ... configurations on the customer's side) points its\n * issuer at. It owns no domain: the router sends it every request whose Host\n * is not a registered domain, which is the copy's public emulator address.\n *\n * `/authorize` is gated: it answers only a browser that opened the copy's\n * sign-in link (cookie from `/oidc/enter`) or a caller holding the derived gate\n * value as a bearer. Token, userinfo, JWKS and discovery are ungated; a code\n * is redeemable only if `/authorize` issued it.\n *\n * @module\n */\n\nimport type { EmulationPlugin, EmulationRequest, EmulationResponse, PluginContext } from '../plugin.js';\nimport { GATE_COOKIE, gateAllows, gateCookieValue, signInKey } from '../sign-in-gate.js';\nimport { tokensMatch } from '../token-match.js';\nimport {\n authorize,\n handleDiscovery,\n handleJwks,\n handleToken,\n handleUserinfo,\n initializeOidcState,\n oidcFixtureSchema,\n type OidcContext,\n type OidcFixture,\n type OidcFlavor,\n type OidcState,\n} from './oidc-core.js';\n\n/** Declared `emulation: { oidc: {} }`; there are no options. */\nexport type OidcConfig = Record<string, never>;\n\n/**\n * The issuer: exactly the copy's public emulator origin, no trailing slash.\n * buildRouter guarantees `publicOrigins.emulation` is set for this plugin.\n */\nfunction issuerOrigin(ctx: PluginContext): string {\n return new URL(ctx.instance.publicOrigins['emulation']!).origin;\n}\n\nconst genericFlavor: OidcFlavor = {\n label: 'Cofactor sandbox',\n issuer: issuerOrigin,\n endpoints: (ctx) => {\n const issuer = issuerOrigin(ctx);\n return {\n authorization_endpoint: `${issuer}/authorize`,\n token_endpoint: `${issuer}/token`,\n userinfo_endpoint: `${issuer}/userinfo`,\n jwks_uri: `${issuer}/jwks`,\n };\n },\n extraClaims: {},\n};\n\nconst NO_STORE_HEADERS = {\n 'cache-control': 'no-store',\n 'referrer-policy': 'no-referrer',\n};\n\n// title and message are interpolated unescaped: pass literals only.\nfunction page(status: number, title: string, message: string, headers: Record<string, string> = {}): EmulationResponse {\n return {\n status,\n headers: { 'content-type': 'text/html; charset=utf-8', ...NO_STORE_HEADERS, ...headers },\n body: `<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>${title}</title></head><body style=\"font-family:system-ui,sans-serif;max-width:28rem;margin:4rem auto;padding:0 1rem\"><h1>${title}</h1><p>${message}</p></body></html>`,\n };\n}\n\n/** The redirect_uri must be http(s) and on one of the copy's public origins; the callback belongs to this copy. */\nfunction redirectUriIsOnThisCopy(redirectUri: string, ctx: PluginContext): boolean {\n try {\n const parsed = new URL(redirectUri);\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return false;\n return Object.values(ctx.instance.publicOrigins).some((origin) => new URL(origin).origin === parsed.origin);\n } catch {\n return false;\n }\n}\n\nfunction handleAuthorize(req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n if (!gateAllows(req.headers, ctx.instance.controlToken)) {\n return page(403, 'Sign-in is locked', \"Open this sandbox's sign-in link from Cofactor to sign in here.\");\n }\n\n const params = req.url.searchParams;\n const redirectUri = params.get('redirect_uri');\n if (params.get('response_type') !== 'code' || !params.get('client_id') || !redirectUri) {\n return page(400, 'Invalid sign-in request', 'The request needs response_type=code, client_id and redirect_uri.');\n }\n if (!redirectUriIsOnThisCopy(redirectUri, ctx)) {\n return page(400, 'Invalid sign-in request', \"The redirect_uri is not an address of this sandbox, so sign-in was not completed.\");\n }\n\n return authorize(genericFlavor, ctx, req.url);\n}\n\nfunction handleEnter(req: EmulationRequest, ctx: OidcContext): EmulationResponse {\n const key = req.url.searchParams.get('key') ?? '';\n if (!tokensMatch(key, signInKey(ctx.instance.controlToken))) {\n return page(403, 'Sign-in link not valid', \"This sign-in link is not valid for this sandbox. Open the current link from Cofactor.\");\n }\n return {\n status: 303,\n headers: {\n location: '/oidc/ready',\n 'set-cookie': `${GATE_COOKIE}=${gateCookieValue(ctx.instance.controlToken)}; HttpOnly; Secure; SameSite=Lax; Path=/`,\n ...NO_STORE_HEADERS,\n },\n body: '',\n };\n}\n\nfunction handleReady(): EmulationResponse {\n return page(200, 'Sign-in is unlocked', 'Sign-in is unlocked for this browser. Return to the app and sign in.');\n}\n\nexport const oidcPlugin: EmulationPlugin<OidcConfig, OidcFixture, OidcState> = {\n id: 'oidc',\n name: 'OpenID Connect provider',\n version: '1.0.0',\n domains: [],\n servesPublicOrigin: true,\n needsBrowserIntercept: false,\n routes: [\n { method: 'GET', path: '/.well-known/openid-configuration', handler: (req, ctx) => handleDiscovery(genericFlavor, req, ctx) },\n { method: 'GET', path: '/jwks', handler: handleJwks },\n { method: 'GET', path: '/oidc/enter', handler: handleEnter },\n { method: 'GET', path: '/oidc/ready', handler: handleReady },\n { method: 'GET', path: '/authorize', handler: handleAuthorize },\n { method: 'POST', path: '/token', handler: (req, ctx) => handleToken(genericFlavor, req, ctx) },\n { method: 'GET', path: '/userinfo', handler: (req, ctx) => handleUserinfo(genericFlavor, req, ctx) },\n { method: 'POST', path: '/userinfo', handler: (req, ctx) => handleUserinfo(genericFlavor, req, ctx) },\n ],\n initialize: (_config, fixture) => initializeOidcState(fixture, null),\n fixtureSchema: oidcFixtureSchema,\n};\n","/**\n * Slack API Emulation Plugin\n *\n * Emulates the Slack Web API for sandboxed apps so customers can test their\n * Slack integration end-to-end without a real workspace:\n *\n * - Sandbox-side: OAuth token exchange, auth.test, conversations, chat.postMessage\n * (recorded into state for assertions), users/team info.\n * - Browser-side: intercepts the slack.com/oauth/v2/authorize redirect so the\n * connect flow completes headlessly.\n * - Inbound events: builds signed `event_callback` webhooks (app_mention,\n * message, reaction_added) that the control plane fires INTO the app. The\n * HMAC scheme is byte-compatible with Slack's `v0=` signing, so the app's\n * production signature verification passes using the shared signing secret\n * from the env contract.\n *\n * Response shapes mirror the zod schemas in @chatsdet/slack (types.ts) —\n * conformance is asserted in slack.test.ts.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\nimport { z } from 'zod';\nimport type {\n ActionInterfaceDef,\n EmulationPlugin,\n EmulationRequest,\n EmulationResponse,\n InboundEventDef,\n PluginContext,\n} from '../plugin.js';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface SlackEmuConfig {\n /** Override the app_id reported by oauth.v2.access */\n appId?: string;\n}\n\nconst SlackEmuChannelSchema = z.object({\n id: z.string(),\n name: z.string(),\n is_private: z.boolean().optional(),\n is_member: z.boolean().optional(),\n is_archived: z.boolean().optional(),\n});\n\nconst SlackEmuUserSchema = z.object({\n id: z.string(),\n name: z.string(),\n real_name: z.string().optional(),\n email: z.string().optional(),\n is_bot: z.boolean().optional(),\n});\n\nexport const slackFixtureSchema = z.object({\n team: z.object({\n id: z.string(),\n name: z.string(),\n domain: z.string().optional(),\n }),\n botUserId: z.string(),\n channels: z.array(SlackEmuChannelSchema),\n users: z.array(SlackEmuUserSchema),\n});\n\nexport type SlackEmuChannel = z.infer<typeof SlackEmuChannelSchema>;\nexport type SlackEmuUser = z.infer<typeof SlackEmuUserSchema>;\nexport type SlackFixture = z.infer<typeof slackFixtureSchema>;\n\nexport interface PostedMessage {\n channel: string;\n text: string;\n ts: string;\n thread_ts?: string;\n user: string;\n blocks?: unknown;\n attachments?: unknown;\n}\n\nexport interface SlackState {\n team: SlackFixture['team'];\n botUserId: string;\n appId: string;\n channels: Map<string, SlackEmuChannel>;\n users: Map<string, SlackEmuUser>;\n /** Messages the app posted via chat.postMessage — the assertion surface */\n postedMessages: PostedMessage[];\n botToken: string;\n tsCounter: number;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Constants\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst EMULATED_CODE_PREFIX = 'emulated_code_';\nconst DEFAULT_APP_ID = 'A_EMULATED';\n\n/** Mirrors SLACK_BOT_SCOPES in @chatsdet/slack (kept local — runtime dep is dev-only) */\nconst EMULATED_BOT_SCOPES =\n 'chat:write,channels:read,groups:read,team:read,app_mentions:read,channels:history,groups:history,reactions:read,users:read,users:read.email,files:write';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype SlackCtx = PluginContext<SlackFixture, SlackState>;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- parsing untrusted API input\nfunction safeParseJson(body: string | undefined): { ok: true; data: any } | { ok: false; error: EmulationResponse } {\n try {\n return { ok: true, data: JSON.parse(body ?? '{}') };\n } catch {\n return { ok: false, error: slackError('invalid_json') };\n }\n}\n\n/** Slack returns HTTP 200 with `{ok:false, error}` for API-level failures. */\nfunction slackError(error: string): EmulationResponse {\n return { status: 200, body: { ok: false, error } };\n}\n\n/**\n * Enforce bot-token auth the way Slack does: bearer must match the token\n * minted at provision. Returns null when authorized.\n */\nfunction requireBot(req: EmulationRequest, ctx: SlackCtx): EmulationResponse | null {\n const auth = req.headers['authorization'] ?? '';\n const token = auth.startsWith('Bearer ') ? auth.slice('Bearer '.length).trim() : '';\n if (!token) return slackError('not_authed');\n if (token !== ctx.state.botToken) return slackError('invalid_auth');\n return null;\n}\n\n/** Mint a Slack-style message ts: unix seconds + monotonic counter suffix. */\nfunction mintTs(state: SlackState): string {\n const seconds = Math.floor(Date.now() / 1000);\n state.tsCounter += 1;\n return `${seconds}.${String(state.tsCounter).padStart(6, '0')}`;\n}\n\n/** Read a param from query string (GET) or JSON body (POST). */\nfunction readParam(req: EmulationRequest, key: string): string | undefined {\n const fromQuery = req.url.searchParams.get(key);\n if (fromQuery !== null) return fromQuery;\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return undefined;\n const value = parsed.data[key];\n return value === undefined || value === null ? undefined : String(value);\n}\n\nfunction signSlackRequest(signingSecret: string, timestamp: string, body: string): string {\n const basestring = `v0:${timestamp}:${body}`;\n return `v0=${crypto.createHmac('sha256', signingSecret).update(basestring).digest('hex')}`;\n}\n\n/** Build a signed event_callback request aimed at the app's webhook path. */\nfunction buildSignedEvent(opts: {\n env: Record<string, string>;\n targetPath: string;\n teamId: string;\n event: Record<string, unknown>;\n}): ReturnType<InboundEventDef['build']> {\n const body = JSON.stringify({\n type: 'event_callback',\n token: 'emulated-verification-token',\n team_id: opts.teamId,\n event: opts.event,\n event_id: `Ev${crypto.randomUUID().replaceAll('-', '').slice(0, 16).toUpperCase()}`,\n });\n // Timestamp is minted at fire time so the app's 5-minute window holds.\n const timestamp = String(Math.floor(Date.now() / 1000));\n const signingSecret = opts.env.signingSecret ?? '';\n return {\n method: 'POST',\n path: opts.targetPath,\n headers: {\n 'content-type': 'application/json',\n 'x-slack-request-timestamp': timestamp,\n 'x-slack-signature': signSlackRequest(signingSecret, timestamp, body),\n },\n body,\n };\n}\n\nfunction teamIdFrom(fixture: unknown, override?: string): string {\n if (override) return override;\n const parsed = slackFixtureSchema.safeParse(fixture);\n return parsed.success ? parsed.data.team.id : 'T_EMULATED';\n}\n\nfunction nowEventTs(): string {\n return `${Math.floor(Date.now() / 1000)}.000001`;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Inbound events\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst appMentionParamsSchema = z.object({\n channel: z.string(),\n user: z.string(),\n text: z.string(),\n ts: z.string().optional(),\n thread_ts: z.string().optional(),\n team_id: z.string().optional(),\n});\n\nconst messageParamsSchema = z.object({\n channel: z.string(),\n user: z.string(),\n text: z.string(),\n thread_ts: z.string().optional(),\n ts: z.string().optional(),\n channel_type: z.enum(['channel', 'group', 'im', 'mpim']).optional(),\n team_id: z.string().optional(),\n});\n\nconst reactionAddedParamsSchema = z.object({\n user: z.string(),\n reaction: z.string(),\n channel: z.string(),\n message_ts: z.string(),\n item_user: z.string().optional(),\n team_id: z.string().optional(),\n});\n\nconst inboundEvents: InboundEventDef[] = [\n {\n id: 'app-mention',\n description: 'A user @-mentions the app in a channel (signed app_mention event_callback)',\n paramsSchema: appMentionParamsSchema,\n build: ({ params, env, targetPath, fixture }) => {\n const p = appMentionParamsSchema.parse(params);\n return buildSignedEvent({\n env,\n targetPath,\n teamId: teamIdFrom(fixture, p.team_id),\n event: {\n type: 'app_mention',\n user: p.user,\n text: p.text,\n channel: p.channel,\n ts: p.ts ?? nowEventTs(),\n ...(p.thread_ts ? { thread_ts: p.thread_ts } : {}),\n },\n });\n },\n },\n {\n id: 'message',\n description: 'A user posts a (thread) message in a channel (signed message event_callback)',\n paramsSchema: messageParamsSchema,\n build: ({ params, env, targetPath, fixture }) => {\n const p = messageParamsSchema.parse(params);\n return buildSignedEvent({\n env,\n targetPath,\n teamId: teamIdFrom(fixture, p.team_id),\n event: {\n type: 'message',\n user: p.user,\n text: p.text,\n channel: p.channel,\n ts: p.ts ?? nowEventTs(),\n ...(p.thread_ts ? { thread_ts: p.thread_ts } : {}),\n ...(p.channel_type ? { channel_type: p.channel_type } : {}),\n },\n });\n },\n },\n {\n id: 'reaction-added',\n description: 'A user reacts to a message (signed reaction_added event_callback)',\n paramsSchema: reactionAddedParamsSchema,\n build: ({ params, env, targetPath, fixture }) => {\n const p = reactionAddedParamsSchema.parse(params);\n return buildSignedEvent({\n env,\n targetPath,\n teamId: teamIdFrom(fixture, p.team_id),\n event: {\n type: 'reaction_added',\n user: p.user,\n reaction: p.reaction,\n item: { type: 'message', channel: p.channel, ts: p.message_ts },\n ...(p.item_user ? { item_user: p.item_user } : {}),\n event_ts: nowEventTs(),\n },\n });\n },\n },\n];\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Action interfaces\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst actionInterfaces: ActionInterfaceDef[] = [\n {\n slug: 'slack-seed-data',\n label: 'Seed Slack data',\n description:\n 'Replace the emulated Slack workspace fixture (team, channels, users). Idempotent — re-running resets to exactly the given data.',\n inputSchema: {\n type: 'object',\n properties: {\n fixture: {\n type: 'string',\n description: 'JSON fixture: { team, botUserId, channels, users }',\n },\n },\n required: ['fixture'],\n },\n outputSchema: {\n type: 'object',\n properties: { ok: { type: 'boolean' } },\n },\n scaffoldScript: `# Replace the emulated Slack workspace data.\n# $INPUT_FIXTURE is the JSON fixture; the runner exports EMULATION_BASE_URL\n# and EMULATION_CONTROL_TOKEN automatically when emulation is enabled.\ncurl -sf -X POST \"$EMULATION_BASE_URL/plugins/slack/fixture\" \\\\\n -H \"Authorization: Bearer $EMULATION_CONTROL_TOKEN\" \\\\\n -H \"Content-Type: application/json\" \\\\\n -d \"{\\\\\"fixture\\\\\": $INPUT_FIXTURE}\"`,\n },\n {\n slug: 'slack-fire-event',\n label: 'Fire a Slack event into the app',\n description:\n \"Send a signed Slack webhook (app-mention | message | reaction-added) into the app's Slack events endpoint. Set the target path to YOUR app's webhook route.\",\n inputSchema: {\n type: 'object',\n properties: {\n event: {\n type: 'string',\n enum: ['app-mention', 'message', 'reaction-added'],\n description: 'Inbound event id',\n },\n params: { type: 'string', description: 'JSON params for the event (channel, user, text, …)' },\n },\n required: ['event', 'params'],\n },\n outputSchema: {\n type: 'object',\n properties: {\n ok: { type: 'boolean' },\n status: { type: 'number' },\n },\n },\n scaffoldScript: `# Fire a signed Slack event into the app.\n# EDIT the targetPath to your app's Slack webhook route before saving.\ncurl -sf -X POST \"$EMULATION_BASE_URL/fire\" \\\\\n -H \"Authorization: Bearer $EMULATION_CONTROL_TOKEN\" \\\\\n -H \"Content-Type: application/json\" \\\\\n -d \"{\\\\\"pluginId\\\\\": \\\\\"slack\\\\\", \\\\\"eventId\\\\\": \\\\\"$INPUT_EVENT\\\\\", \\\\\"params\\\\\": $INPUT_PARAMS, \\\\\"targetPath\\\\\": \\\\\"/integrations/slack/events\\\\\"}\"`,\n },\n {\n slug: 'slack-recorded-messages',\n label: 'Read messages the app posted to Slack',\n description:\n 'Return the messages the app sent via chat.postMessage since boot (or the last seed/reset) for assertions.',\n inputSchema: { type: 'object', properties: {} },\n outputSchema: {\n type: 'object',\n properties: {\n messages: { type: 'array', description: 'Posted messages: { channel, text, ts, thread_ts?, user }' },\n },\n },\n scaffoldScript: `# Read messages the app posted to the emulated Slack.\ncurl -sf \"$EMULATION_BASE_URL/plugins/slack/posted-messages\" \\\\\n -H \"Authorization: Bearer $EMULATION_CONTROL_TOKEN\"`,\n },\n];\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Plugin\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport const slackPlugin: EmulationPlugin<SlackEmuConfig, SlackFixture, SlackState> = {\n id: 'slack',\n name: 'Slack API',\n version: '1.0.0',\n\n domains: ['slack.com'],\n needsBrowserIntercept: true,\n\n fixtureSchema: slackFixtureSchema,\n\n envContract: [\n {\n logicalKey: 'signingSecret',\n strategy: 'random-hex',\n bytes: 32,\n sensitive: true,\n description: \"Signs inbound webhooks — map to your app's Slack signing-secret env var\",\n },\n {\n logicalKey: 'botToken',\n strategy: 'random-hex',\n bytes: 16,\n prefix: 'xoxb-emulated-',\n sensitive: true,\n description: 'Bot token the emulator accepts — issued by oauth.v2.access, or map it directly',\n },\n {\n logicalKey: 'clientId',\n strategy: 'static',\n staticValue: '1234567890.0987654321',\n description: \"OAuth client id — map to your app's Slack client-id env var\",\n },\n {\n logicalKey: 'clientSecret',\n strategy: 'static',\n staticValue: 'emulated-client-secret',\n sensitive: true,\n description: \"OAuth client secret — map to your app's Slack client-secret env var\",\n },\n ],\n\n inboundEvents,\n actionInterfaces,\n\n controlReads: [\n {\n path: 'posted-messages',\n handler: (_req, ctx: SlackCtx) => ({\n status: 200,\n body: { messages: ctx.state.postedMessages },\n }),\n },\n {\n path: 'channels',\n handler: (_req, ctx: SlackCtx) => ({\n status: 200,\n body: { channels: Array.from(ctx.state.channels.values()) },\n }),\n },\n ],\n\n // ── Sandbox-side routes ──────────────────────────────────────────────────\n\n routes: [\n { method: 'POST', path: '/api/oauth.v2.access', handler: handleOAuthAccess },\n { method: 'POST', path: '/api/auth.test', handler: handleAuthTest },\n { method: 'GET', path: '/api/conversations.list', handler: handleConversationsList },\n { method: 'POST', path: '/api/conversations.list', handler: handleConversationsList },\n { method: 'POST', path: '/api/chat.postMessage', handler: handlePostMessage },\n { method: 'POST', path: '/api/conversations.join', handler: handleConversationsJoin },\n { method: 'GET', path: '/api/conversations.history', handler: handleConversationsHistory },\n { method: 'GET', path: '/api/conversations.replies', handler: handleConversationsReplies },\n { method: 'GET', path: '/api/users.info', handler: handleUsersInfo },\n { method: 'POST', path: '/api/users.info', handler: handleUsersInfo },\n { method: 'GET', path: '/api/team.info', handler: handleTeamInfo },\n { method: 'POST', path: '/api/team.info', handler: handleTeamInfo },\n // Best-effort Assistant status — emulate the missing-scope soft failure\n {\n method: 'POST',\n path: '/api/assistant.threads.setStatus',\n handler: (req, ctx: SlackCtx) => requireBot(req, ctx) ?? slackError('missing_scope'),\n },\n // File uploads are not emulated — fail closed so nothing leaks to real Slack\n {\n method: 'GET',\n path: '/api/files.getUploadURLExternal',\n handler: (req, ctx: SlackCtx) => requireBot(req, ctx) ?? slackError('not_emulated'),\n },\n {\n method: 'POST',\n path: '/api/files.completeUploadExternal',\n handler: (req, ctx: SlackCtx) => requireBot(req, ctx) ?? slackError('not_emulated'),\n },\n ],\n\n // ── Browser-side routes ──────────────────────────────────────────────────\n\n getBrowserRoutes(_fixture) {\n return [\n {\n urlPattern: '**/slack.com/oauth/v2/authorize**',\n handler: async (route, _fix) => {\n const url = new URL(route.request().url());\n const redirectUri = url.searchParams.get('redirect_uri');\n const state = url.searchParams.get('state') || '';\n\n if (!redirectUri) {\n await route.continue();\n return;\n }\n\n const callbackUrl = new URL(redirectUri);\n callbackUrl.searchParams.set('code', `${EMULATED_CODE_PREFIX}${crypto.randomUUID()}`);\n if (state) callbackUrl.searchParams.set('state', state);\n\n await route.fulfill({\n status: 302,\n headers: { location: callbackUrl.toString() },\n body: '',\n });\n },\n },\n ];\n },\n\n // ── Initialization ───────────────────────────────────────────────────────\n\n initialize(config, fixture, env) {\n return {\n team: fixture.team,\n botUserId: fixture.botUserId,\n appId: config.appId ?? DEFAULT_APP_ID,\n channels: new Map(fixture.channels.map((c) => [c.id, c])),\n users: new Map(fixture.users.map((u) => [u.id, u])),\n postedMessages: [],\n botToken: env?.botToken ?? 'xoxb-emulated-fallback',\n tsCounter: 0,\n };\n },\n\n defaultFixture: {\n team: { id: 'T_EMULATED', name: 'Emulated Workspace', domain: 'emulated' },\n botUserId: 'U_BOT',\n channels: [{ id: 'C_GENERAL', name: 'general', is_private: false, is_member: false, is_archived: false }],\n users: [\n { id: 'U_BOT', name: 'canary-bot', real_name: 'Canary Bot', is_bot: true },\n { id: 'U_HUMAN', name: 'testuser', real_name: 'Test User', email: 'testuser@example.com', is_bot: false },\n ],\n },\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Route Handlers\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction handleOAuthAccess(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const params = new URLSearchParams(req.body ?? '');\n const code = params.get('code') ?? '';\n const clientId = params.get('client_id') ?? '';\n const clientSecret = params.get('client_secret') ?? '';\n\n if (ctx.env.clientId && clientId !== ctx.env.clientId) return slackError('invalid_client_id');\n if (ctx.env.clientSecret && clientSecret !== ctx.env.clientSecret) return slackError('bad_client_secret');\n if (!code.startsWith(EMULATED_CODE_PREFIX)) {\n ctx.log('warn', `OAuth exchange with non-emulated code: ${code}`);\n return slackError('invalid_code');\n }\n\n const firstHuman = Array.from(ctx.state.users.values()).find((u) => !u.is_bot);\n ctx.log('info', `Issued bot token for team ${ctx.state.team.id}`);\n\n return {\n status: 200,\n body: {\n ok: true,\n access_token: ctx.state.botToken,\n token_type: 'bot',\n scope: EMULATED_BOT_SCOPES,\n bot_user_id: ctx.state.botUserId,\n app_id: ctx.state.appId,\n team: { id: ctx.state.team.id, name: ctx.state.team.name },\n authed_user: { id: firstHuman?.id ?? 'U_HUMAN' },\n },\n };\n}\n\nfunction handleAuthTest(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const denied = requireBot(req, ctx);\n if (denied) return denied;\n\n return {\n status: 200,\n body: {\n ok: true,\n url: `https://${ctx.state.team.domain ?? 'emulated'}.slack.com/`,\n team: ctx.state.team.name,\n user: 'canary-bot',\n team_id: ctx.state.team.id,\n user_id: ctx.state.botUserId,\n bot_id: 'B_EMULATED',\n },\n };\n}\n\nfunction handleConversationsList(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const denied = requireBot(req, ctx);\n if (denied) return denied;\n\n const excludeArchived = req.url.searchParams.get('exclude_archived') === 'true';\n const channels = Array.from(ctx.state.channels.values()).filter(\n (c) => !excludeArchived || !c.is_archived\n );\n\n return {\n status: 200,\n body: {\n ok: true,\n channels: channels.map((c) => ({\n id: c.id,\n name: c.name,\n is_channel: true,\n is_private: c.is_private ?? false,\n is_member: c.is_member ?? false,\n is_archived: c.is_archived ?? false,\n })),\n response_metadata: { next_cursor: '' },\n },\n };\n}\n\nfunction handlePostMessage(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const denied = requireBot(req, ctx);\n if (denied) return denied;\n\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return parsed.error;\n const { channel, text } = parsed.data;\n if (!channel) return slackError('channel_not_found');\n\n const ts = mintTs(ctx.state);\n const message: PostedMessage = {\n channel: String(channel),\n text: String(text ?? ''),\n ts,\n user: ctx.state.botUserId,\n ...(parsed.data.thread_ts ? { thread_ts: String(parsed.data.thread_ts) } : {}),\n ...(parsed.data.blocks ? { blocks: parsed.data.blocks } : {}),\n ...(parsed.data.attachments ? { attachments: parsed.data.attachments } : {}),\n };\n ctx.state.postedMessages.push(message);\n ctx.log('info', `chat.postMessage → ${message.channel}: ${message.text.slice(0, 80)}`);\n\n return {\n status: 200,\n body: {\n ok: true,\n channel: message.channel,\n ts,\n message: { type: 'message', text: message.text, user: ctx.state.botUserId, ts },\n },\n };\n}\n\nfunction handleConversationsJoin(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const denied = requireBot(req, ctx);\n if (denied) return denied;\n\n const parsed = safeParseJson(req.body);\n if (!parsed.ok) return parsed.error;\n const channelId = String(parsed.data.channel ?? '');\n const channel = ctx.state.channels.get(channelId);\n if (!channel) return slackError('channel_not_found');\n\n channel.is_member = true;\n return {\n status: 200,\n body: { ok: true, channel: { id: channel.id, name: channel.name, is_member: true } },\n };\n}\n\n/** Serve message lookups from postedMessages (parents only). */\nfunction handleConversationsHistory(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const denied = requireBot(req, ctx);\n if (denied) return denied;\n\n const channel = req.url.searchParams.get('channel') ?? '';\n const latest = req.url.searchParams.get('latest');\n let messages = ctx.state.postedMessages.filter((m) => m.channel === channel && !m.thread_ts);\n if (latest) messages = messages.filter((m) => m.ts === latest);\n\n return {\n status: 200,\n body: {\n ok: true,\n messages: messages.map((m) => ({ type: 'message', user: m.user, text: m.text, ts: m.ts })),\n has_more: false,\n },\n };\n}\n\nfunction handleConversationsReplies(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const denied = requireBot(req, ctx);\n if (denied) return denied;\n\n const channel = req.url.searchParams.get('channel') ?? '';\n const ts = req.url.searchParams.get('ts') ?? '';\n const thread = ctx.state.postedMessages.filter(\n (m) => m.channel === channel && (m.ts === ts || m.thread_ts === ts)\n );\n\n return {\n status: 200,\n body: {\n ok: true,\n messages: thread.map((m) => ({\n type: 'message',\n user: m.user,\n text: m.text,\n ts: m.ts,\n // Everything here was posted by the app, so mirror real Slack and\n // mark it as a bot message — the addressing resolver relies on that\n // to classify alert cards it did not author conversationally.\n bot_id: 'B_EMULATED',\n ...(m.thread_ts ? { thread_ts: m.thread_ts } : {}),\n })),\n has_more: false,\n },\n };\n}\n\nfunction handleUsersInfo(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const denied = requireBot(req, ctx);\n if (denied) return denied;\n\n const userId = readParam(req, 'user') ?? '';\n const user = ctx.state.users.get(userId);\n if (!user) return slackError('user_not_found');\n\n return {\n status: 200,\n body: {\n ok: true,\n user: {\n id: user.id,\n name: user.name,\n real_name: user.real_name ?? user.name,\n is_bot: user.is_bot ?? false,\n deleted: false,\n profile: {\n display_name: user.name,\n real_name: user.real_name ?? user.name,\n ...(user.email ? { email: user.email } : {}),\n },\n },\n },\n };\n}\n\nfunction handleTeamInfo(req: EmulationRequest, ctx: SlackCtx): EmulationResponse {\n const denied = requireBot(req, ctx);\n if (denied) return denied;\n\n return {\n status: 200,\n body: {\n ok: true,\n team: {\n id: ctx.state.team.id,\n name: ctx.state.team.name,\n domain: ctx.state.team.domain ?? 'emulated',\n },\n },\n };\n}\n","/**\n * Emulation Plugin Registry\n *\n * Central registry of all available emulation plugins. Add new plugins here\n * to make them available for sandbox configuration.\n *\n * @module\n */\n\nimport type { EmulationPlugin } from '../plugin.js';\nimport { awsPlugin } from './aws/index.js';\nimport { emailPlugin } from './email.js';\nimport { googleOAuthPlugin } from './google-oauth.js';\nimport { esriPlugin } from './esri/index.js';\nimport { jiraPlugin } from './jira.js';\nimport { maximoStubPlugin } from './maximo-stub.js';\nimport { oidcPlugin } from './oidc.js';\nimport { slackPlugin } from './slack.js';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- type-erased registry for heterogeneous plugins\ntype AnyPlugin = EmulationPlugin<any, any, any>;\n\n/** All registered emulation plugins, keyed by ID. */\nconst pluginRegistry = new Map<string, AnyPlugin>([\n [awsPlugin.id, awsPlugin],\n [emailPlugin.id, emailPlugin],\n [esriPlugin.id, esriPlugin],\n [googleOAuthPlugin.id, googleOAuthPlugin],\n [jiraPlugin.id, jiraPlugin],\n [maximoStubPlugin.id, maximoStubPlugin],\n [oidcPlugin.id, oidcPlugin],\n [slackPlugin.id, slackPlugin],\n]);\n\n/** Look up a plugin by ID. Returns undefined if not found. */\nexport function getPlugin(pluginId: string): AnyPlugin | undefined {\n return pluginRegistry.get(pluginId);\n}\n\n/** Get all registered plugin IDs. */\nexport function getPluginIds(): string[] {\n return Array.from(pluginRegistry.keys());\n}\n\n/** Get all registered plugins. */\nexport function getAllPlugins(): AnyPlugin[] {\n return Array.from(pluginRegistry.values());\n}\n\n/** Register a new plugin at runtime (for custom/third-party plugins). */\nexport function registerPlugin(plugin: AnyPlugin): void {\n pluginRegistry.set(plugin.id, plugin);\n}\n\nexport { emailPlugin, emailFixtureSchema } from './email.js';\nexport type { CapturedEmail, EmailEmuConfig, EmailFixture, EmailState, EmailProvider } from './email.js';\nexport { googleOAuthPlugin } from './google-oauth.js';\nexport { oidcFixture } from './oidc-core.js';\nexport { oidcPlugin } from './oidc.js';\nexport { esriPlugin } from './esri/index.js';\nexport type { EsriConfig, EsriFixture, EsriState } from './esri/index.js';\nexport { jiraPlugin } from './jira.js';\nexport { maximoStubPlugin } from './maximo-stub.js';\nexport { slackPlugin, slackFixtureSchema } from './slack.js';\nexport type { SlackFixture, SlackState, PostedMessage } from './slack.js';\n","/**\n * Operation Catalog\n *\n * Pure helpers over the plugin registry's `operations` declarations, so\n * consumers outside the emulator sidecar (Cofactor actions, tests) can list\n * and validate typed operations without reaching into plugin internals.\n *\n * @module\n */\n\nimport { z } from 'zod';\nimport { getPlugin } from './plugins/index.js';\nimport type { EmulationOperationDef } from './plugin.js';\n\n/** The JSON-Schema subset the validator and UI read from an operation's input. */\nexport interface OperationInputSchema {\n properties?: Record<string, { type?: string; description?: string; default?: unknown; enum?: unknown[] }>;\n required?: string[];\n}\n\nexport interface OperationCatalogEntry {\n id: string;\n description: string;\n inputSchema: OperationInputSchema;\n outputSchema: Record<string, unknown>;\n}\n\n/** List a plugin's operations as a JSON-Schema catalog. Empty array if the plugin is unknown or has none. */\nexport function pluginOperations(pluginId: string): OperationCatalogEntry[] {\n const plugin = getPlugin(pluginId);\n if (!plugin) return [];\n return (plugin.operations ?? []).map((op) => ({\n id: op.id,\n description: op.description,\n inputSchema: z.toJSONSchema(op.input) as OperationInputSchema,\n outputSchema: z.toJSONSchema(op.output) as Record<string, unknown>,\n }));\n}\n\n/** A single operation's schemas, for validating input before invoking it. */\nexport function findOperation(\n pluginId: string,\n opId: string\n): Pick<EmulationOperationDef, 'id' | 'description' | 'input' | 'output'> | undefined {\n const op = getPlugin(pluginId)?.operations?.find((candidate) => candidate.id === opId);\n return op && { id: op.id, description: op.description, input: op.input, output: op.output };\n}\n\n/** Split an operation slug (`<plugin>.<op>`) at its first dot; null when it is not one. */\nexport function parseOperationRef(slug: string): { pluginId: string; operationId: string } | null {\n const dot = slug.indexOf('.');\n if (dot <= 0 || dot === slug.length - 1) return null;\n return { pluginId: slug.slice(0, dot), operationId: slug.slice(dot + 1) };\n}\n","/**\n * Emulation Env Contract\n *\n * Plugins declare logical values (signing secrets, client IDs, bot tokens)\n * that must be shared between the emulation sidecar and the sandboxed app.\n * At provision time the contract is resolved into concrete values: random\n * secrets are minted per-provision (never persisted to the template), static\n * values come from the plugin, and `from-config` values come from the\n * template's plugin config.\n *\n * The resolved map is injected into the sidecar (via EMULATION_CONFIG_B64,\n * exposed to handlers as `PluginContext.env`) and — through the template's\n * `envMapping` — into the sandboxed app's environment, so both sides hold\n * byte-identical values.\n *\n * @module\n */\n\nimport crypto from 'node:crypto';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type EnvStrategy = 'random-hex' | 'random-uuid' | 'static' | 'from-config';\n\n/** One logical value a plugin produces or consumes. */\nexport interface EnvContractEntry {\n /** Logical name (e.g., 'signingSecret') — mapped to app env vars via the template's envMapping */\n logicalKey: string;\n strategy: EnvStrategy;\n /** Number of random bytes for 'random-hex' (default 32) */\n bytes?: number;\n /** Literal prefix prepended to generated values (e.g., 'xoxb-emulated-') */\n prefix?: string;\n /** Literal value for 'static' */\n staticValue?: string;\n /** Plugin-config key to read for 'from-config' */\n configKey?: string;\n /** Marks secrets that must never be echoed back through read APIs */\n sensitive?: boolean;\n description?: string;\n}\n\n/** Randomness source — injectable so tests are deterministic. */\nexport interface RngAdapter {\n randomHex(bytes: number): string;\n randomUuid(): string;\n}\n\nexport const defaultRng: RngAdapter = {\n randomHex: (bytes) => crypto.randomBytes(bytes).toString('hex'),\n randomUuid: () => crypto.randomUUID(),\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Resolution\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Resolve an env contract into concrete values.\n * Pure given the injected rng. Throws on an unsatisfiable entry\n * (missing staticValue / configKey / config value).\n */\nexport function resolveEnvContract(\n contract: EnvContractEntry[],\n config: Record<string, unknown>,\n rng: RngAdapter = defaultRng\n): Record<string, string> {\n const resolved: Record<string, string> = {};\n\n for (const entry of contract) {\n const prefix = entry.prefix ?? '';\n switch (entry.strategy) {\n case 'random-hex':\n resolved[entry.logicalKey] = prefix + rng.randomHex(entry.bytes ?? 32);\n break;\n case 'random-uuid':\n resolved[entry.logicalKey] = prefix + rng.randomUuid();\n break;\n case 'static':\n if (entry.staticValue === undefined) {\n throw new Error(`Env contract '${entry.logicalKey}': strategy 'static' requires staticValue`);\n }\n resolved[entry.logicalKey] = entry.staticValue;\n break;\n case 'from-config': {\n if (!entry.configKey) {\n throw new Error(`Env contract '${entry.logicalKey}': strategy 'from-config' requires configKey`);\n }\n const value = config[entry.configKey];\n if (value === undefined || value === null || value === '') {\n throw new Error(\n `Env contract '${entry.logicalKey}': plugin config is missing '${entry.configKey}'`\n );\n }\n resolved[entry.logicalKey] = String(value);\n break;\n }\n }\n }\n\n return resolved;\n}\n","/** Google authorization interception, including an app's initial HTTP redirect. */\nimport type { BrowserRouteHandle } from './plugin.js';\n\nconst PROVIDER_URL_PATTERN = '**/accounts.google.com/o/oauth2/**';\n\nexport type GoogleOAuthBrowserConfig = {\n applicationOrigins: string[];\n urlContext: { sourceOrigin: string; targetOrigin: string } | null;\n /** The emulator control plane and the key scoped to its authorize read (never the raw control token). */\n control: { baseUrl: string; authorizeKey: string };\n};\n\ntype RouteResponse = {\n status: number;\n headers: Record<string, string>;\n body: Uint8Array;\n};\n\ninterface GoogleOAuthRouteHandle extends Omit<BrowserRouteHandle, 'fulfill'> {\n fulfill(response: {\n status?: number;\n headers?: Record<string, string>;\n body?: string | Uint8Array;\n }): Promise<void>;\n isMainFrameNavigation(): boolean;\n fallback?(): Promise<void>;\n /** Fetch this request once, preserving browser cookies, without following redirects. */\n fetchResponse(): Promise<RouteResponse>;\n}\n\nconst ENTITY_HEADERS = new Set(['content-length', 'content-encoding', 'transfer-encoding', 'content-type', 'location']);\n\n/** The app's response headers minus those describing its own body or redirect (keeps `set-cookie` etc.). */\nfunction withoutEntityHeaders(headers: Record<string, string>): Record<string, string> {\n return Object.fromEntries(Object.entries(headers).filter(([name]) => !ENTITY_HEADERS.has(name.toLowerCase())));\n}\n\nconst FAILURE_PREFIX = 'Cofactor sandbox emulator: Google authorize failed:';\n\nexport function googleOAuthBrowserRoutes(config: GoogleOAuthBrowserConfig) {\n const origins = new Set(config.applicationOrigins.map((value) => new URL(value).origin));\n\n /** Swap the app's source origin for the copy's; any other URL is returned unchanged. */\n const toCopyOrigin = (value: string): string => {\n const url = new URL(value);\n if (!config.urlContext || url.origin !== config.urlContext.sourceOrigin) return url.href;\n return new URL(config.urlContext.targetOrigin + url.href.slice(url.origin.length)).href;\n };\n\n /** Ask the emulator's authorize read about `authorizeUrl` and fulfill the route with its answer. */\n const authorize = async (\n route: GoogleOAuthRouteHandle,\n authorizeUrl: string,\n headers: Record<string, string>\n ) => {\n const carried = withoutEntityHeaders(headers);\n const failed = (reason: string) =>\n route.fulfill({\n status: 502,\n headers: { 'content-type': 'text/plain; charset=utf-8' },\n body: `${FAILURE_PREFIX} ${reason}`,\n });\n\n let response: Response;\n try {\n response = await fetch(`${config.control.baseUrl}/plugins/google-oauth/authorize${new URL(authorizeUrl).search}`, {\n headers: { authorization: `Bearer ${config.control.authorizeKey}` },\n redirect: 'manual',\n signal: AbortSignal.timeout(15_000),\n });\n } catch (error) {\n await failed(`${config.control.baseUrl} unreachable (${error instanceof Error ? error.message : String(error)})`);\n return;\n }\n\n if (response.status === 302) {\n const location = response.headers.get('location');\n if (!location) {\n await failed('the emulator redirect has no Location');\n return;\n }\n const callback = new URL(toCopyOrigin(location));\n if (!origins.has(callback.origin)) {\n await route.fulfill({\n status: 400,\n body: 'OAuth callback must belong to this sandbox copy',\n });\n return;\n }\n await route.fulfill({ status: 302, headers: { ...carried, location: callback.href }, body: '' });\n return;\n }\n\n if (response.status !== 200 && response.status !== 400) {\n await failed(`HTTP ${response.status} from the emulator control plane (is the copy on a platform version with the Google authorize endpoint?)`);\n return;\n }\n // The fetch's AbortSignal timeout also covers the body read; a stall there would otherwise leave the route unfulfilled.\n let body: string;\n try {\n body = await response.text();\n } catch (error) {\n await failed(`reading the emulator answer from ${config.control.baseUrl} (${error instanceof Error ? error.message : String(error)})`);\n return;\n }\n await route.fulfill({\n status: response.status,\n headers: { ...carried, 'content-type': response.headers.get('content-type') ?? 'text/plain' },\n body,\n });\n };\n\n return [\n {\n urlPattern: PROVIDER_URL_PATTERN,\n handler: (route: GoogleOAuthRouteHandle) => authorize(route, route.request().url(), {}),\n },\n ...[...origins].map((origin) => ({\n urlPattern: `${origin}/**`,\n handler: async (route: GoogleOAuthRouteHandle) => {\n if (!route.isMainFrameNavigation() || route.request().method() !== 'GET') {\n if (!route.fallback)\n throw new Error('Browser client cannot preserve context route owners');\n await route.fallback();\n return;\n }\n // Playwright only routes the first URL of a redirect chain. Inspect the\n // app response before the browser follows its Google authorization URL.\n const response = await route.fetchResponse();\n const location = response.headers.location;\n if (response.status >= 300 && response.status < 400 && location) {\n const redirect = new URL(location, route.request().url());\n if (\n redirect.hostname === 'accounts.google.com' &&\n redirect.pathname.startsWith('/o/oauth2/')\n ) {\n await authorize(route, redirect.href, response.headers);\n return;\n }\n }\n await route.fulfill(response);\n },\n })),\n ];\n}\n","/** Browser-side sign-in gate for a native v2 sandbox copy's OIDC emulator: carries the gate value on `/authorize`. */\n\nexport type OidcGateBrowserConfig = {\n /** The emulator's origin (the copy's `emulation` port URL). */\n origin: string;\n /** `gateCookieValue(controlToken)`, sent as a bearer. */\n gateValue: string;\n};\n\n/** Distinct from Google's `emulation` group so both can be armed on one context. */\nexport const OIDC_GATE_ROUTE_KEY = 'emulation-oidc-gate';\n\ninterface OidcGateRouteHandle {\n continue(): Promise<void>;\n request(): { url(): string; headers(): Record<string, string> };\n fallback?(): Promise<void>;\n /** Fetch once without following redirects; `headers` replace the request headers. */\n fetchResponse(opts?: {\n headers?: Record<string, string>;\n }): Promise<{ status: number; headers: Record<string, string>; body: Uint8Array }>;\n fulfill(response: { status?: number; headers?: Record<string, string>; body?: Uint8Array }): Promise<void>;\n}\n\n/**\n * One route on `${origin}/authorize**`: `/authorize` is fetched once with\n * `authorization: Bearer <gateValue>` added and the response fulfilled as-is.\n * Not `continue({ headers })`: Playwright carries overridden headers across\n * redirects, which would leak the bearer to the app's callback. A fulfilled 302\n * is followed by the browser itself, without the header. Anything else goes to\n * the next route owner.\n */\nexport function oidcGateBrowserRoutes(config: OidcGateBrowserConfig) {\n const origin = new URL(config.origin).origin;\n return [\n {\n urlPattern: `${origin}/authorize**`,\n handler: async (route: OidcGateRouteHandle) => {\n const url = new URL(route.request().url());\n if (url.origin === origin && url.pathname === '/authorize') {\n const response = await route.fetchResponse({\n headers: { ...route.request().headers(), authorization: `Bearer ${config.gateValue}` },\n });\n await route.fulfill(response);\n return;\n }\n if (route.fallback) await route.fallback();\n else await route.continue();\n },\n },\n ];\n}\n"],"mappings":"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","names":["z","message","maxResults","text","message","withDecryption","invalid","operation","crypto","existsSync","readFileSync","crypto","existsSync","readFileSync","crypto","validation","message","OPERATIONS","operation","notFound","message","OPERATIONS","operation","z","z","crypto","crypto","headers","text","captured","crypto","server","text","page","value","z","z","crypto","z","crypto","z","z","crypto","crypto","message","crypto","z","text","text","l","r","negate","z","crypto","crypto","z","z","z","z","crypto","page","crypto","crypto","z","safeParseJson","text","notFound","z","configSchema","z","message","flag","attr","want","compareValues","sweep","page","key","headers","message","headers","crypto","z","safeParseJson","text","message","z","z","crypto","headers","authorize"]}
|