@devlab.group/agent-commerce 2.1.0 → 2.2.1
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 +35 -5
- package/dist/ap2.js +3 -3
- package/dist/{chunk-LZS5BL3W.js → chunk-2DAJAJI7.js} +23 -5
- package/dist/chunk-2DAJAJI7.js.map +1 -0
- package/dist/{chunk-UHMYRV3J.js → chunk-BNUD4RBN.js} +22 -7
- package/dist/chunk-BNUD4RBN.js.map +1 -0
- package/dist/{chunk-IFGRCXME.js → chunk-REBY2IEP.js} +24 -20
- package/dist/chunk-REBY2IEP.js.map +1 -0
- package/dist/{chunk-SY6GUYSQ.js → chunk-XYHDQ22D.js} +3 -3
- package/dist/{chunk-SY6GUYSQ.js.map → chunk-XYHDQ22D.js.map} +1 -1
- package/dist/cli/ap2-HLBIUSTK.js +678 -0
- package/dist/cli/ap2-HLBIUSTK.js.map +1 -0
- package/dist/cli/chunk-2LN5PO5I.js +1352 -0
- package/dist/cli/chunk-2LN5PO5I.js.map +1 -0
- package/dist/cli/chunk-3EQBCFZY.js +53 -0
- package/dist/cli/chunk-3EQBCFZY.js.map +1 -0
- package/dist/cli/chunk-3M6U7ILB.js +8 -0
- package/dist/cli/chunk-3M6U7ILB.js.map +1 -0
- package/dist/cli/chunk-3MGAJ5FX.js +70 -0
- package/dist/cli/chunk-3MGAJ5FX.js.map +1 -0
- package/dist/cli/chunk-5K4XEAZV.js +113 -0
- package/dist/cli/chunk-5K4XEAZV.js.map +1 -0
- package/dist/cli/chunk-AA3FIEAR.js +27 -0
- package/dist/cli/chunk-AA3FIEAR.js.map +1 -0
- package/dist/cli/chunk-FHCFR2GS.js +17 -0
- package/dist/cli/chunk-FHCFR2GS.js.map +1 -0
- package/dist/cli/chunk-ILUYEQSV.js +1744 -0
- package/dist/cli/chunk-ILUYEQSV.js.map +1 -0
- package/dist/cli/chunk-KTV52MCU.js +338 -0
- package/dist/cli/chunk-KTV52MCU.js.map +1 -0
- package/dist/cli/chunk-OSTCU6ZK.js +44 -0
- package/dist/cli/chunk-OSTCU6ZK.js.map +1 -0
- package/dist/cli/chunk-OZ4LAWBK.js +256 -0
- package/dist/cli/chunk-OZ4LAWBK.js.map +1 -0
- package/dist/cli/chunk-QQ3WY5L3.js +271 -0
- package/dist/cli/chunk-QQ3WY5L3.js.map +1 -0
- package/dist/cli/chunk-QY3K6PEQ.js +8 -0
- package/dist/cli/chunk-QY3K6PEQ.js.map +1 -0
- package/dist/cli/chunk-QZ6TOMX6.js +1413 -0
- package/dist/cli/chunk-QZ6TOMX6.js.map +1 -0
- package/dist/cli/chunk-SNM3OVCY.js +625 -0
- package/dist/cli/chunk-SNM3OVCY.js.map +1 -0
- package/dist/cli/chunk-SPAYKVUP.js +118 -0
- package/dist/cli/chunk-SPAYKVUP.js.map +1 -0
- package/dist/cli/chunk-TPC4EJLT.js +11 -0
- package/dist/cli/chunk-TPC4EJLT.js.map +1 -0
- package/dist/cli/config-VYAJGZXE.js +11 -0
- package/dist/cli/config-VYAJGZXE.js.map +1 -0
- package/dist/cli/index.js +150 -3627
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-HFD7ZNCQ.js +559 -0
- package/dist/cli/mcp-HFD7ZNCQ.js.map +1 -0
- package/dist/cli/near-5AY3HWYF.js +58 -0
- package/dist/cli/near-5AY3HWYF.js.map +1 -0
- package/dist/cli/provider-JV5HCQGR.js +396 -0
- package/dist/cli/provider-JV5HCQGR.js.map +1 -0
- package/dist/cli/run-WV44B62Y.js +7301 -0
- package/dist/cli/run-WV44B62Y.js.map +1 -0
- package/dist/cli/svm-3MMYFPC7.js +33 -0
- package/dist/cli/svm-3MMYFPC7.js.map +1 -0
- package/dist/cli/x402-NADFV5CD.js +96 -0
- package/dist/cli/x402-NADFV5CD.js.map +1 -0
- package/dist/index.d.ts +12 -3
- package/dist/index.js +82 -11
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +6 -16
- package/dist/mcp.js.map +1 -1
- package/dist/mpp.js +3 -3
- package/dist/{networks-olfflCI_.d.ts → networks-DTWRlj-K.d.ts} +2 -2
- package/dist/x402.d.ts +7 -2
- package/dist/x402.js +4 -4
- package/package.json +2 -2
- package/dist/chunk-IFGRCXME.js.map +0 -1
- package/dist/chunk-LZS5BL3W.js.map +0 -1
- package/dist/chunk-UHMYRV3J.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/config/filename.ts","../../src/core/execution/backend-request.ts","../../src/core/execution/backend-http.ts","../../src/core/execution/validation.ts","../../src/core/execution/pipeline/authorization.ts","../../src/core/execution/pipeline/challenge.ts","../../src/core/execution/pipeline/admission.ts","../../src/core/execution/pipeline/context.ts","../../src/core/execution/pipeline/settlement.ts","../../src/core/execution/pipeline/index.ts","../../src/core/execution/registry.ts","../../src/core/execution/store-event-sink.ts","../../src/protocols/acp/constants.ts"],"names":["url","durationMs"],"mappings":";;;;;;AASO,IAAM,uBAAA,GAA0B;;;ACCvC,IAAM,sBAAA,GACJ,0JAAA;AAMF,IAAM,kBAAA,GAAqB,wBAAA;AAOpB,SAAS,0BAA0B,GAAA,EAAuB;AAC/D,EAAA,OAAO,CAAC,GAAG,GAAA,CAAI,QAAA,CAAS,kBAAkB,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,KAAA,KAAU,KAAA,CAAM,CAAC,CAAW,CAAA;AAChF;AAUO,SAAS,uBAAuB,GAAA,EAAiC;AACtE,EAAA,MAAM,OAAA,GAAU,GAAA,CAAI,OAAA,CAAQ,kBAAA,EAAoB,EAAE,CAAA;AAClD,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA;AACnC,EAAA,IAAI,KAAA,KAAU,IAAI,OAAO,MAAA;AAEzB,EAAA,MAAM,QAAQ,gBAAA,CAAiB,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,KAAK,CAAC,CAAA;AACxD,EAAA,OAAO,KAAA,GAAQ,CAAC,CAAA,IAAK,OAAA,CAAQ,KAAK,CAAA;AACpC;AAQO,SAAS,2BAAA,CACd,OAAA,EACA,KAAA,EACA,OAAA,EACA,cAAA,EACM;AACN,EAAA,MAAM,WAAA,GAAc,QAAA,CAAS,KAAK,CAAA,GAAI,QAAQ,EAAC;AAI/C,EAAA,MAAM,KAAA,GAAQ,wBAAA,CAAyB,OAAA,EAAS,WAAA,EAAa,OAAO,CAAA;AAEpE,EAAA,YAAA,CAAa,OAAA,EAAS,SAAS,cAAc,CAAA;AAE7C,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAI,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA;AAAA,EAC5B,CAAA,CAAA,MAAQ;AACN,IAAA;AAAA,EACF;AACA,EAAA,mBAAA,CAAoB,MAAA,EAAQ,KAAA,CAAM,KAAA,EAAO,OAAO,CAAA;AAClD;AAYA,SAAS,YAAY,MAAA,EAAgC;AACnD,EAAA,OAAO,MAAA,KAAW,SAAS,MAAA,KAAW,QAAA;AACxC;AAQO,SAAS,wBAAA,CACd,OAAA,EACA,KAAA,EACA,OAAA,EACqB;AACrB,EAAA,MAAM,WAAW,OAAA,CAAQ,aAAA;AACzB,EAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,IAAA,MAAM,EAAE,KAAAA,IAAAA,EAAK,SAAA,KAAc,iBAAA,CAAkB,OAAA,CAAQ,GAAA,EAAK,KAAA,EAAO,OAAO,CAAA;AACxE,IAAA,OAAO,WAAA,CAAY,QAAQ,MAAM,CAAA,GAC7B,EAAE,GAAA,EAAAA,IAAAA,EAAK,OAAO,EAAC,EAAG,MAAM,EAAE,KAAA,EAAO,WAAU,EAAE,GAC7C,EAAE,GAAA,EAAAA,IAAAA,EAAK,OAAO,SAAA,EAAU;AAAA,EAC9B;AAEA,EAAA,MAAM,UAAA,GACJ,QAAA,CAAS,IAAA,KAAS,MAAA,GAAY,EAAC,GAAI,iBAAA,CAAkB,KAAA,EAAO,QAAA,CAAS,IAAA,EAAM,MAAA,EAAQ,OAAO,CAAA;AAC5F,EAAA,MAAM,EAAE,GAAA,EAAI,GAAI,kBAAkB,OAAA,CAAQ,GAAA,EAAK,YAAY,OAAO,CAAA;AAClE,EAAA,MAAM,KAAA,GACJ,QAAA,CAAS,KAAA,KAAU,MAAA,GAAY,EAAC,GAAI,iBAAA,CAAkB,KAAA,EAAO,QAAA,CAAS,KAAA,EAAO,OAAA,EAAS,OAAO,CAAA;AAI/F,EAAA,MAAM,YAAY,QAAA,CAAS,IAAA,KAAS,SAAY,MAAA,GAAY,KAAA,CAAM,SAAS,IAAI,CAAA;AAC/E,EAAA,IAAI,SAAA,KAAc,MAAA,IAAa,CAAC,WAAA,CAAY,OAAA,CAAQ,MAAM,CAAA,EAAG,OAAO,EAAE,GAAA,EAAK,KAAA,EAAM;AACjF,EAAA,OAAO,EAAE,GAAA,EAAK,KAAA,EAAO,MAAM,EAAE,KAAA,EAAO,WAAU,EAAE;AAClD;AAEA,SAAS,iBAAA,CACP,KAAA,EACA,GAAA,EACA,IAAA,EACA,OAAA,EACyB;AACzB,EAAA,MAAM,KAAA,GAAQ,MAAM,GAAG,CAAA;AACvB,EAAA,IAAI,KAAA,KAAU,MAAA,EAAW,OAAO,EAAC;AACjC,EAAA,IAAI,CAAC,QAAA,CAAS,KAAK,CAAA,EAAG;AACpB,IAAA,MAAM,IAAI,aAAA;AAAA,MACR,eAAA;AAAA,MACA,CAAA,OAAA,EAAU,GAAG,CAAA,uBAAA,EAA0B,IAAI,CAAA,WAAA,CAAA;AAAA,MAC3C,EAAE,GAAG,OAAA,EAAS,SAAS,EAAE,KAAA,EAAO,KAAI;AAAE,KACxC;AAAA,EACF;AACA,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,mBAAA,CACd,MAAA,EACA,SAAA,EACA,OAAA,EACM;AACN,EAAA,MAAM,eAAe,IAAI,GAAA,CAAI,MAAA,CAAO,YAAA,CAAa,MAAM,CAAA;AACvD,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,SAAS,CAAA,EAAG;AACxC,IAAA,IAAI,YAAA,CAAa,GAAA,CAAI,GAAG,CAAA,EAAG;AACzB,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,eAAA;AAAA,QACA,cAAc,GAAG,CAAA,4DAAA,CAAA;AAAA,QACjB,EAAE,SAAA,EAAW,OAAA,CAAQ,SAAA,EAAW,UAAA,EAAY,OAAA,CAAQ,UAAA,EAAY,OAAA,EAAS,EAAE,KAAA,EAAO,GAAA,EAAI;AAAE,OAC1F;AAAA,IACF;AAAA,EACF;AACF;AAKA,IAAM,wCAAwB,IAAI,GAAA,CAAI,CAAC,EAAA,EAAI,GAAA,EAAK,IAAI,CAAC,CAAA;AAErD,SAAS,iBAAA,CACP,QAAA,EACA,KAAA,EACA,OAAA,EACqD;AACrD,EAAA,MAAM,SAAA,GAAqC,EAAE,GAAG,KAAA,EAAM;AACtD,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,OAAA;AACJ,EAAA,MAAM,MAAM,QAAA,CAAS,OAAA,CAAQ,kBAAA,EAAoB,CAAC,QAAQ,GAAA,KAAgB;AAGxE,IAAA,IAAI,CAAC,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,GAAG,CAAA,EAAG;AAClC,MAAA,OAAA,GAAU,GAAA;AACV,MAAA,OAAO,EAAA;AAAA,IACT;AACA,IAAA,MAAM,KAAA,GAAQ,UAAU,GAAG,CAAA;AAC3B,IAAA,OAAO,UAAU,GAAG,CAAA;AACpB,IAAA,MAAM,GAAA,GAAM,mBAAmB,KAAK,CAAA;AACpC,IAAA,IAAI,qBAAA,CAAsB,GAAA,CAAI,GAAG,CAAA,EAAG;AAClC,MAAA,OAAA,GAAU,GAAA;AACV,MAAA,OAAO,EAAA;AAAA,IACT;AACA,IAAA,OAAO,mBAAmB,GAAG,CAAA;AAAA,EAC/B,CAAC,CAAA;AACD,EAAA,IAAI,YAAY,MAAA,EAAW;AAKzB,IAAA,MAAM,IAAI,aAAA,CAAc,eAAA,EAAiB,CAAA,gBAAA,EAAmB,OAAO,CAAA,kBAAA,CAAA,EAAsB;AAAA,MACvF,GAAG,OAAA;AAAA,MACH,OAAA,EAAS,EAAE,KAAA,EAAO,OAAA;AAAQ,KAC3B,CAAA;AAAA,EACH;AACA,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,MAAM,IAAI,aAAA,CAAc,eAAA,EAAiB,CAAA,gBAAA,EAAmB,OAAO,CAAA,sBAAA,CAAA,EAA0B;AAAA,MAC3F,GAAG,OAAA;AAAA,MACH,OAAA,EAAS,EAAE,KAAA,EAAO,OAAA;AAAQ,KAC3B,CAAA;AAAA,EACH;AACA,EAAA,OAAO,EAAE,KAAK,SAAA,EAAU;AAC1B;AAEO,SAAS,mBAAmB,KAAA,EAAwB;AACzD,EAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM,OAAO,EAAA;AAClD,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,EAAA,IAAI,OAAO,UAAU,QAAA,IAAY,OAAO,UAAU,SAAA,EAAW,OAAO,OAAO,KAAK,CAAA;AAChF,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,UAAU,KAAK,CAAA;AAAA,EAC7B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,OAAO,KAAK,CAAA;AAAA,EACrB;AACF;AAKO,SAAS,YAAA,CACd,OAAA,EACA,OAAA,EACA,SAAA,GAA8C,EAAC,EACtC;AACT,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACF,IAAA,OAAA,GAAU,IAAI,OAAA,CAAQ,OAAA,CAAQ,OAAO,CAAA;AAAA,EACvC,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,mBAAmB,OAAO,CAAA;AAAA,EAClC;AAEA,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA,EAAG;AACrD,IAAA,IAAI,sBAAA,CAAuB,IAAA,CAAK,IAAA,CAAK,WAAA,EAAa,CAAA,EAAG;AACrD,IAAA,IAAI;AACF,MAAA,IAAI,CAAC,QAAQ,GAAA,CAAI,IAAI,GAAG,OAAA,CAAQ,GAAA,CAAI,MAAM,KAAK,CAAA;AAAA,IACjD,CAAA,CAAA,MAAQ;AACN,MAAA,MAAM,IAAI,aAAA,CAAc,eAAA,EAAiB,uCAAA,EAAyC;AAAA,QAChF,GAAG,OAAA;AAAA,QACH,OAAA,EAAS,EAAE,MAAA,EAAQ,0BAAA;AAA2B,OAC/C,CAAA;AAAA,IACH;AAAA,EACF;AACA,EAAA,OAAO,OAAA;AACT;AAEO,SAAS,SAAA,CACd,OAAA,EACA,IAAA,EACA,KAAA,EACA,OAAA,EACM;AACN,EAAA,IAAI;AACF,IAAA,OAAA,CAAQ,GAAA,CAAI,MAAM,KAAK,CAAA;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,mBAAmB,OAAO,CAAA;AAAA,EAClC;AACF;AAEA,SAAS,mBAAmB,OAAA,EAAsC;AAChE,EAAA,OAAO,IAAI,aAAA,CAAc,eAAA,EAAiB,qCAAA,EAAuC;AAAA,IAC/E,GAAG,OAAA;AAAA,IACH,OAAA,EAAS,EAAE,MAAA,EAAQ,gBAAA;AAAiB,GACrC,CAAA;AACH;;;AC9OA,IAAM,uBAAA,GAA0B,GAAA;AAIhC,IAAM,sBAAA,GAAyB,iBAAA;AAI/B,IAAM,0BAA0B,IAAA,GAAO,IAAA;AAahC,IAAM,uBAAN,MAA2B;AAAA,EAChC,WAAA,CACW,MAAA,EACA,IAAA,EAEA,OAAA,GAA4C,EAAC,EACtD;AAJS,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAEA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EACR;AAAA,EAJQ,MAAA;AAAA,EACA,IAAA;AAAA,EAEA,OAAA;AAEb;AAEO,IAAM,sBAAN,MAAqD;AAAA,EACzC,SAAA;AAAA,EACA,MAAA;AAAA,EAEjB,WAAA,CAAY,OAAA,GAAsC,EAAC,EAAG;AACpD,IAAA,IAAA,CAAK,SAAA,GAAY,QAAQ,SAAA,IAAa,KAAA;AACtC,IAAA,IAAA,CAAK,MAAA,GAAS,QAAQ,MAAA,IAAU,WAAA;AAAA,EAClC;AAAA,EAEA,MAAM,IAAA,CAAK,OAAA,EAAyB,OAAA,EAAmD;AACrF,IAAA,MAAM,SAAA,GAAY,QAAQ,SAAA,IAAa,0BAAA;AACvC,IAAA,MAAM,cAAc,QAAA,CAAS,OAAA,CAAQ,KAAK,CAAA,GAAI,OAAA,CAAQ,QAAQ,EAAC;AAE/D,IAAA,MAAM,UAAU,EAAE,SAAA,EAAW,QAAQ,SAAA,EAAW,UAAA,EAAY,QAAQ,UAAA,EAAW;AAI/E,IAAA,MAAM,KAAA,GAAQ,wBAAA,CAAyB,OAAA,EAAS,WAAA,EAAa,OAAO,CAAA;AAEpE,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,IAAI,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA;AAAA,IAC5B,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,IAAI,aAAA,CAAc,eAAA,EAAiB,iDAAA,EAAmD;AAAA,QAC1F,GAAG,OAAA;AAAA,QACH,OAAA,EAAS,EAAE,MAAA,EAAQ,aAAA,EAAc;AAAA,QACjC,KAAA,EAAO;AAAA,OACR,CAAA;AAAA,IACH;AAIA,IAAA,MAAM,cAAA,GAAiB,sBAAsB,OAAO,CAAA;AACpD,IAAA,IAAI,mBAAmB,MAAA,IAAa,CAAC,OAAO,QAAA,CAAS,UAAA,CAAW,cAAc,CAAA,EAAG;AAC/E,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,eAAA;AAAA,QACA,8DAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,GAAU,YAAA,CAAa,OAAA,EAAS,OAAA,EAAS,QAAQ,cAAc,CAAA;AAGrE,IAAA,IAAI,OAAA,CAAQ,mBAAmB,MAAA,EAAW;AACxC,MAAA,SAAA,CAAU,OAAA,EAAS,sBAAA,EAAwB,OAAA,CAAQ,cAAA,EAAgB,OAAO,CAAA;AAAA,IAC5E;AACA,IAAA,IAAI,IAAA;AAMJ,IAAA,mBAAA,CAAoB,MAAA,EAAQ,KAAA,CAAM,KAAA,EAAO,OAAO,CAAA;AAChD,IAAA,KAAA,MAAW,CAAC,KAAK,KAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,KAAA,CAAM,KAAK,CAAA,EAAG;AACtD,MAAA,MAAA,CAAO,YAAA,CAAa,GAAA,CAAI,GAAA,EAAK,kBAAA,CAAmB,KAAK,CAAC,CAAA;AAAA,IACxD;AACA,IAAA,IAAI,KAAA,CAAM,SAAS,MAAA,EAAW;AAC5B,MAAA,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,KAAA,CAAM,IAAA,CAAK,KAAK,CAAA;AAEtC,MAAA,IAAI,CAAC,QAAQ,GAAA,CAAI,cAAc,GAAG,OAAA,CAAQ,GAAA,CAAI,gBAAgB,kBAAkB,CAAA;AAAA,IAClF;AAEA,IAAA,MAAM,OAAA,GAAU,YAAY,GAAA,EAAI;AAChC,IAAA,IAAI,QAAA;AACJ,IAAA,IAAI;AACF,MAAA,QAAA,GAAW,MAAM,IAAA,CAAK,SAAA,CAAU,MAAA,EAAQ;AAAA,QACtC,QAAQ,OAAA,CAAQ,MAAA;AAAA,QAChB,OAAA;AAAA,QACA,GAAI,IAAA,KAAS,KAAA,CAAA,GAAY,EAAE,IAAA,KAAS,EAAC;AAAA,QACrC,QAAA,EAAU,QAAA;AAAA,QACV,MAAA,EAAQ,WAAA,CAAY,OAAA,CAAQ,SAAS;AAAA,OACtC,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,MAAMC,cAAa,IAAA,CAAK,KAAA,CAAM,WAAA,CAAY,GAAA,KAAQ,OAAO,CAAA;AACzD,MAAA,IAAI,YAAA,CAAa,KAAK,CAAA,EAAG;AACvB,QAAA,MAAM,IAAI,aAAA;AAAA,UACR,iBAAA;AAAA,UACA,mCAAmC,SAAS,CAAA,EAAA,CAAA;AAAA,UAC5C;AAAA,YACE,WAAW,OAAA,CAAQ,SAAA;AAAA,YACnB,YAAY,OAAA,CAAQ,UAAA;AAAA,YACpB,OAAA,EAAS,EAAE,SAAA,EAAW,UAAA,EAAAA,WAAAA,EAAW;AAAA,YACjC,KAAA,EAAO;AAAA;AACT,SACF;AAAA,MACF;AACA,MAAA,MAAM,IAAI,aAAA,CAAc,eAAA,EAAiB,0CAAA,EAA4C;AAAA,QACnF,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,OAAA,CAAQ,UAAA;AAAA,QACpB,OAAA,EAAS,EAAE,UAAA,EAAAA,WAAAA,EAAW;AAAA,QACtB,KAAA,EAAO;AAAA,OACR,CAAA;AAAA,IACH;AACA,IAAA,MAAM,aAAa,IAAA,CAAK,KAAA,CAAM,WAAA,CAAY,GAAA,KAAQ,OAAO,CAAA;AAEzD,IAAA,MAAM,UAAA,GACJ,SAAS,IAAA,KAAS,gBAAA,IAAqB,SAAS,MAAA,IAAU,GAAA,IAAO,SAAS,MAAA,GAAS,GAAA;AACrF,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,eAAA;AAAA,QACA,0DAAA;AAAA,QACA;AAAA,UACE,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,OAAA,CAAQ,UAAA;AAAA,UACpB,SAAS,EAAE,MAAA,EAAQ,QAAA,CAAS,MAAA,EAAQ,QAAQ,uBAAA;AAAwB;AACtE,OACF;AAAA,IACF;AAEA,IAAA,MAAM,eAAA,GAAkB,MAAA,CAAO,WAAA,CAAY,QAAA,CAAS,OAAO,CAAA;AAC3D,IAAA,MAAM,WAAA,GAAc,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA,IAAK,EAAA;AAC5D,IAAA,IAAI,UAAA;AACJ,IAAA,IAAI;AACF,MAAA,UAAA,GAAa,MAAM,SAAA,CAAU,QAAA,EAAU,WAAW,CAAA;AAAA,IACpD,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,QAAA,GAAW,gBAAgB,KAAK,CAAA;AACtC,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,eAAA;AAAA,QACA,WACI,oDAAA,GACA,oCAAA;AAAA,QACJ;AAAA,UACE,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,OAAA,CAAQ,UAAA;AAAA,UACpB,OAAA,EAAS,QAAA,GACL,EAAE,MAAA,EAAQ,oBAAA,EAAsB,UAAU,uBAAA,EAAwB,GAClE,EAAE,MAAA,EAAQ,YAAA,EAAa;AAAA,UAC3B,KAAA,EAAO;AAAA;AACT,OACF;AAAA,IACF;AAEA,IAAA,IAAI,QAAA,CAAS,MAAA,GAAS,GAAA,IAAO,QAAA,CAAS,UAAU,GAAA,EAAK;AAInD,MAAA,IAAA,CAAK,MAAA,CAAO,KAAA;AAAA,QACV;AAAA,UACE,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,OAAA,CAAQ,UAAA;AAAA,UACpB,QAAQ,QAAA,CAAS,MAAA;AAAA,UACjB,WAAA,EAAa,gBAAgB,UAAU;AAAA,SACzC;AAAA,QACA;AAAA,OACF;AACA,MAAA,MAAM,IAAI,aAAA,CAAc,eAAA,EAAiB,CAAA,8BAAA,EAAiC,QAAA,CAAS,MAAM,CAAA,CAAA,EAAI;AAAA,QAC3F,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,OAAA,CAAQ,UAAA;AAAA,QACpB,OAAA,EAAS,EAAE,MAAA,EAAQ,QAAA,CAAS,MAAA,EAAO;AAAA,QACnC,OAAO,IAAI,oBAAA,CAAqB,QAAA,CAAS,MAAA,EAAQ,YAAY,eAAe;AAAA,OAC7E,CAAA;AAAA,IACH;AAEA,IAAA,OAAO;AAAA,MACL,QAAQ,QAAA,CAAS,MAAA;AAAA,MACjB,OAAA,EAAS,eAAA;AAAA,MACT,IAAA,EAAM,UAAA;AAAA,MACN;AAAA,KACF;AAAA,EACF;AACF;AAKA,IAAM,eAAA,uBAAsB,OAAA,EAAuC;AAEnE,SAAS,sBAAsB,OAAA,EAA6C;AAC1E,EAAA,IAAI,MAAA,GAAS,eAAA,CAAgB,GAAA,CAAI,OAAO,CAAA;AACxC,EAAA,IAAI,WAAW,MAAA,EAAW;AACxB,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,OAAA,CAAQ,GAAG,CAAA,CAAE,QAAA;AAAA,IAC7D,CAAA,CAAA,MAAQ;AACN,MAAA,MAAA,GAAS,IAAA;AAAA,IACX;AACA,IAAA,eAAA,CAAgB,GAAA,CAAI,SAAS,MAAM,CAAA;AAAA,EACrC;AACA,EAAA,OAAO,MAAA,IAAU,MAAA;AACnB;AAEA,eAAe,cAAA,CAAe,UAAoB,QAAA,EAAmC;AACnF,EAAA,IAAI,CAAC,QAAA,CAAS,IAAA,EAAM,OAAO,EAAA;AAC3B,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,IAAA,CAAK,SAAA,EAAU;AACvC,EAAA,MAAM,SAAuB,EAAC;AAC9B,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,IAAI;AACF,IAAA,WAAS;AACP,MAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAM,OAAO,IAAA,EAAK;AAC1C,MAAA,IAAI,IAAA,EAAM;AACV,MAAA,KAAA,IAAS,KAAA,CAAM,UAAA;AACf,MAAA,IAAI,QAAQ,QAAA,EAAU;AACpB,QAAA,MAAM,OAAO,MAAA,EAAO;AAGpB,QAAA,MAAM,IAAI,aAAA,CAAc,eAAA,EAAiB,CAAA,uBAAA,EAA0B,QAAQ,CAAA,MAAA,CAAQ,CAAA;AAAA,MACrF;AACA,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,IACnB;AAAA,EACF,CAAA,SAAE;AACA,IAAA,MAAA,CAAO,WAAA,EAAY;AAAA,EACrB;AACA,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,MAAM,CAAA,CAAE,SAAS,MAAM,CAAA;AAC9C;AAEA,eAAe,SAAA,CAAU,UAAoB,WAAA,EAAuC;AAClF,EAAA,MAAM,IAAA,GAAO,MAAM,cAAA,CAAe,QAAA,EAAU,uBAAuB,CAAA;AACnE,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAC9B,EAAA,IAAI,WAAA,CAAY,QAAA,CAAS,MAAM,CAAA,EAAG;AAChC,IAAA,IAAI;AACF,MAAA,OAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,IACxB,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,gBAAgB,IAAA,EAAuB;AAC9C,EAAA,MAAM,OAAO,OAAO,IAAA,KAAS,QAAA,GAAW,IAAA,GAAO,cAAc,IAAI,CAAA;AACjE,EAAA,OAAO,IAAA,CAAK,SAAS,uBAAA,GACjB,CAAA,EAAG,KAAK,KAAA,CAAM,CAAA,EAAG,uBAAuB,CAAC,CAAA,MAAA,CAAA,GACzC,IAAA;AACN;AAEA,SAAS,cAAc,KAAA,EAAwB;AAC7C,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA,IAAK,OAAO,KAAK,CAAA;AAAA,EAC9C,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,OAAO,KAAK,CAAA;AAAA,EACrB;AACF;AAEA,SAAS,aAAa,KAAA,EAAyB;AAC7C,EAAA,OAAO,iBAAiB,KAAA,KAAU,KAAA,CAAM,IAAA,KAAS,cAAA,IAAkB,MAAM,IAAA,KAAS,YAAA,CAAA;AACpF;AC7PA,IAAM,eAAA,uBAAsB,GAAA,CAAI;AAAA,EAC9B,QAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAC,CAAA;AAGM,SAAS,kBAAkB,MAAA,EAA2C;AAC3E,EAAA,OAAO,CAAC,KAAA,KAAqC;AAC3C,IAAA,IAAI,WAAW,MAAA,EAAW,OAAO,EAAE,KAAA,EAAO,IAAA,EAAM,OAAO,KAAA,EAAM;AAC7D,IAAA,MAAM,MAAA,GAAS,YAAA,CAAa,MAAA,EAAQ,KAAA,EAAO,GAAG,CAAA;AAC9C,IAAA,OAAO,MAAA,CAAO,MAAA,KAAW,CAAA,GAAI,EAAE,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,KAAA,EAAM,GAAI,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAO;AAAA,EACtF,CAAA;AACF;AAEA,SAAS,WAAA,CAAY,MAAc,KAAA,EAAyB;AAC1D,EAAA,QAAQ,IAAA;AAAM,IACZ,KAAK,QAAA;AACH,MAAA,OAAO,SAAS,KAAK,CAAA;AAAA,IACvB,KAAK,OAAA;AACH,MAAA,OAAO,KAAA,CAAM,QAAQ,KAAK,CAAA;AAAA,IAC5B,KAAK,QAAA;AACH,MAAA,OAAO,OAAO,KAAA,KAAU,QAAA;AAAA,IAC1B,KAAK,SAAA;AACH,MAAA,OAAO,OAAO,KAAA,KAAU,SAAA;AAAA,IAC1B,KAAK,QAAA;AACH,MAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,MAAA,CAAO,SAAS,KAAK,CAAA;AAAA,IAC3D,KAAK,SAAA;AACH,MAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,MAAA,CAAO,UAAU,KAAK,CAAA;AAAA,IAC5D,KAAK,MAAA;AACH,MAAA,OAAO,KAAA,KAAU,IAAA;AAAA,IACnB;AACE,MAAA,OAAO,IAAA;AAAA;AAEb;AAEA,SAAS,aAAa,KAAA,EAAwB;AAC5C,EAAA,IAAI,KAAA,KAAU,MAAM,OAAO,MAAA;AAC3B,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG,OAAO,OAAA;AACjC,EAAA,OAAO,OAAO,KAAA;AAChB;AAGA,SAAS,SAAA,CAAU,GAAY,CAAA,EAAqB;AAClD,EAAA,OAAO,CAAA,KAAM,CAAA,IAAK,iBAAA,CAAkB,CAAA,EAAG,CAAC,CAAA;AAC1C;AAEA,SAAS,GAAA,CAAI,KAA8B,GAAA,EAAsB;AAC/D,EAAA,OAAO,OAAO,MAAA,CAAO,GAAA,EAAK,GAAG,CAAA,GAAI,GAAA,CAAI,GAAG,CAAA,GAAI,MAAA;AAC9C;AAIA,SAAS,SAAS,GAAA,EAAoC;AACpD,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,EAAU,OAAO,CAAC,GAAG,CAAA;AACxC,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,IAAK,GAAA,CAAI,KAAA,CAAM,CAAC,KAAA,KAA2B,OAAO,KAAA,KAAU,QAAQ,CAAA,EAAG;AAC1F,IAAA,OAAO,GAAA;AAAA,EACT;AACA,EAAA,OAAO,MAAA;AACT;AAWO,SAAS,mBAAmB,MAAA,EAA0C;AAC3E,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,MAAA,CAAO,MAAM,CAAC,CAAA;AACrC,EAAA,IAAI,KAAA,KAAU,MAAA,EAAW,OAAO,KAAA,CAAM,SAAS,QAAQ,CAAA;AACvD,EAAA,OAAO,MAAA,CAAO,OAAO,MAAA,EAAQ,YAAY,KAAK,MAAA,CAAO,MAAA,CAAO,QAAQ,UAAU,CAAA;AAChF;AAEA,SAAS,YAAA,CAAa,MAAA,EAAoB,KAAA,EAAgB,IAAA,EAA4B;AACpF,EAAA,MAAM,SAAuB,EAAC;AAC9B,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,GAAA,CAAI,MAAA,EAAQ,MAAM,CAAC,CAAA;AAC1C,EAAA,MAAM,eAAA,GAAkB,OAAO,MAAA,CAAO,CAAC,UAAU,eAAA,CAAgB,GAAA,CAAI,KAAK,CAAC,CAAA;AAE3E,EAAA,IACE,KAAA,KAAU,MAAA,IACV,eAAA,KAAoB,MAAA,IACpB,eAAA,CAAgB,WAAW,KAAA,CAAM,MAAA,IACjC,KAAA,CAAM,MAAA,GAAS,CAAA,EACf;AACA,IAAA,IAAI,CAAC,MAAM,IAAA,CAAK,CAAC,UAAU,WAAA,CAAY,KAAA,EAAO,KAAK,CAAC,CAAA,EAAG;AACrD,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA;AAAA,QACA,OAAA,EAAS,kBAAkB,KAAA,CAAM,IAAA,CAAK,KAAK,CAAC,CAAA,UAAA,EAAa,YAAA,CAAa,KAAK,CAAC,CAAA;AAAA,OAC7E,CAAA;AACD,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,GAAU,GAAA,CAAI,MAAA,EAAQ,MAAM,CAAA;AAClC,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,EAAG;AAC1B,IAAA,MAAM,OAAA,GAAU,OAAA;AAChB,IAAA,IAAI,CAAC,QAAQ,IAAA,CAAK,CAAC,cAAc,SAAA,CAAU,SAAA,EAAW,KAAK,CAAC,CAAA,EAAG;AAC7D,MAAA,MAAA,CAAO,IAAA,CAAK,EAAE,IAAA,EAAM,OAAA,EAAS,CAAA,eAAA,EAAkB,KAAK,SAAA,CAAU,OAAO,CAAC,CAAA,CAAA,EAAI,CAAA;AAAA,IAC5E;AAAA,EACF;AAEA,EAAA,IAAI,kBAAA,CAAmB,MAAM,CAAA,IAAK,QAAA,CAAS,KAAK,CAAA,EAAG;AACjD,IAAA,MAAA,CAAO,KAAK,GAAG,cAAA,CAAe,MAAA,EAAQ,KAAA,EAAO,IAAI,CAAC,CAAA;AAAA,EACpD,CAAA,MAAA,IAAA,CAAY,OAAO,QAAA,CAAS,OAAO,KAAK,KAAA,KAAU,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACtE,IAAA,MAAA,CAAO,KAAK,GAAG,aAAA,CAAc,MAAA,EAAQ,KAAA,EAAO,IAAI,CAAC,CAAA;AAAA,EACnD;AAEA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,cAAA,CACP,MAAA,EACA,KAAA,EACA,IAAA,EACc;AACd,EAAA,MAAM,SAAuB,EAAC;AAC9B,EAAA,MAAM,QAAA,GAAW,GAAA,CAAI,MAAA,EAAQ,YAAY,CAAA;AACzC,EAAA,MAAM,UAAA,GAAa,QAAA,CAAS,QAAQ,CAAA,GAAI,WAAW,EAAC;AACpD,EAAA,MAAM,WAAA,GAAc,GAAA,CAAI,MAAA,EAAQ,UAAU,CAAA;AAC1C,EAAA,MAAM,QAAA,GAAW,KAAA,CAAM,OAAA,CAAQ,WAAW,CAAA,GACtC,WAAA,CAAY,MAAA,CAAO,CAAC,KAAA,KAA2B,OAAO,KAAA,KAAU,QAAQ,IACxE,EAAC;AAEL,EAAA,KAAA,MAAW,OAAO,QAAA,EAAU;AAG1B,IAAA,IAAI,CAAC,MAAA,CAAO,MAAA,CAAO,KAAA,EAAO,GAAG,CAAA,EAAG;AAC9B,MAAA,MAAA,CAAO,IAAA,CAAK,EAAE,IAAA,EAAM,CAAA,EAAG,IAAI,IAAI,GAAG,CAAA,CAAA,EAAI,OAAA,EAAS,aAAA,EAAe,CAAA;AAAA,IAChE;AAAA,EACF;AAEA,EAAA,MAAM,UAAA,GAAa,GAAA,CAAI,MAAA,EAAQ,sBAAsB,CAAA;AAErD,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,EAAG;AAGpC,IAAA,MAAM,aAAA,GAAgB,GAAA,CAAI,UAAA,EAAY,GAAG,CAAA;AACzC,IAAA,IAAI,kBAAkB,MAAA,EAAW;AAC/B,MAAA,IAAI,QAAA,CAAS,aAAa,CAAA,EAAG;AAC3B,QAAA,MAAA,CAAO,IAAA,CAAK,GAAG,YAAA,CAAa,aAAA,EAAe,KAAA,CAAM,GAAG,CAAA,EAAG,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,GAAG,CAAA,CAAE,CAAC,CAAA;AAAA,MAC1E;AACA,MAAA;AAAA,IACF;AACA,IAAA,IAAI,eAAe,KAAA,EAAO;AACxB,MAAA,MAAA,CAAO,IAAA,CAAK,EAAE,IAAA,EAAM,CAAA,EAAG,IAAI,IAAI,GAAG,CAAA,CAAA,EAAI,OAAA,EAAS,iCAAA,EAAmC,CAAA;AAAA,IACpF,CAAA,MAAA,IAAW,QAAA,CAAS,UAAU,CAAA,EAAG;AAC/B,MAAA,MAAA,CAAO,IAAA,CAAK,GAAG,YAAA,CAAa,UAAA,EAAY,KAAA,CAAM,GAAG,CAAA,EAAG,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,GAAG,CAAA,CAAE,CAAC,CAAA;AAAA,IACvE;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,aAAA,CAAc,MAAA,EAAoB,KAAA,EAAkB,IAAA,EAA4B;AACvF,EAAA,MAAM,SAAuB,EAAC;AAC9B,EAAA,MAAM,QAAA,GAAW,GAAA,CAAI,MAAA,EAAQ,OAAO,CAAA;AACpC,EAAA,IAAI,QAAA,CAAS,QAAQ,CAAA,EAAG;AACtB,IAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,EAAM,KAAA,KAAU;AAC7B,MAAA,MAAA,CAAO,IAAA,CAAK,GAAG,YAAA,CAAa,QAAA,EAAU,IAAA,EAAM,GAAG,IAAI,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,CAAG,CAAC,CAAA;AAAA,IAClE,CAAC,CAAA;AAAA,EACH;AACA,EAAA,OAAO,MAAA;AACT;;;AChMO,SAAS,6BAAA,CACd,SAAA,EACA,QAAA,EACA,SAAA,EACkC;AAClC,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,aAAA,EAAe,QAAA,IAAY,EAAC;AACtD,EAAA,OAAO,QAAA,CAAS,GAAA,CAAI,CAAC,MAAA,KAAoC;AACvD,IAAA,MAAM,QAAQ,SAAA,CAAU,IAAA,CAAK,CAAC,QAAA,KAAa,QAAA,CAAS,SAAS,MAAM,CAAA;AACnE,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,gBAAA;AAAA,QACA,CAAA,UAAA,EAAa,QAAA,CAAS,EAAE,CAAA,iCAAA,EAAoC,MAAM,CAAA,uBAAA,CAAA;AAAA,QAClE,EAAE,SAAA,EAAW,UAAA,EAAY,QAAA,CAAS,EAAA;AAAG,OACvC;AAAA,IACF;AACA,IAAA,OAAO,KAAA;AAAA,EACT,CAAC,CAAA;AACH;AAUO,SAAS,0BAA0B,GAAA,EAA2C;AACnF,EAAA,MAAM,EAAE,OAAA,EAAS,QAAA,EAAU,UAAA,EAAW,GAAI,GAAA;AAK1C,EAAA,eAAe,mBAAA,CACb,OAAA,EACA,QAAA,EACA,SAAA,EACA,aACA,KAAA,EACwC;AACxC,IAAA,IAAI,SAAA,CAAU,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AAEnC,IAAA,MAAM,aAAa,OAAA,CAAQ,aAAA;AAC3B,IAAA,MAAM,QAAA,GAAW,UAAU,IAAA,CAAK,CAAC,cAAc,SAAA,CAAU,IAAA,KAAS,YAAY,MAAM,CAAA;AAGpF,IAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,MAAA,CAAO,CAAC,SAAA,KAAc,SAAA,KAAc,QAAQ,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAA;AAEvF,IAAA,IAAI,eAAe,MAAA,IAAa,QAAA,KAAa,MAAA,IAAa,KAAA,CAAM,SAAS,CAAA,EAAG;AAC1E,MAAA,MAAM,QAAA;AAAA,QACJ,UAAA,CAAW;AAAA,UACT,IAAA,EAAM,wBAAA;AAAA,UACN,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,SAAS,OAAA,CAAQ,QAAA;AAAA,UACjB,MAAA,EAAQ,OAAA;AAAA,UACR,IAAA,EAAM,EAAE,MAAA,EAAQ,wBAAA,EAA0B,SAAS,KAAA;AAAM,SAC1D;AAAA,OACH;AACA,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,wBAAA;AAAA,QACA,aAAa,QAAA,CAAS,EAAE,6BAA6B,KAAA,CAAM,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA;AAAA,QACrE;AAAA,UACE,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,OAAA,EAAS,EAAE,QAAA,EAAU,SAAA,CAAU,GAAA,CAAI,CAAC,SAAA,KAAc,SAAA,CAAU,IAAI,CAAA,EAAG,OAAA,EAAS,KAAA;AAAM;AACpF,OACF;AAAA,IACF;AAEA,IAAA,IAAI,YAAA;AACJ,IAAA,IAAI;AACF,MAAA,YAAA,GAAe,MAAM,SAAS,gBAAA,CAAiB;AAAA,QAC7C,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,QAAA,CAAS,EAAA;AAAA,QACrB,KAAA;AAAA,QACA,UAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AAGd,MAAA,MAAM,MAAA,GAAS,eAAA,CAAgB,KAAK,CAAA,GAChC,QACA,IAAI,aAAA;AAAA,QACF,oCAAA;AAAA,QACA,uCAAA;AAAA,QACA;AAAA,UACE,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,KAAA,EAAO;AAAA;AACT,OACF;AACJ,MAAA,MAAM,QAAA;AAAA,QACJ,UAAA,CAAW;AAAA,UACT,IAAA,EAAM,wBAAA;AAAA,UACN,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,SAAS,OAAA,CAAQ,QAAA;AAAA,UACjB,MAAA,EAAQ,OAAA;AAAA,UACR,MAAM,EAAE,MAAA,EAAQ,OAAO,IAAA,EAAM,MAAA,EAAQ,SAAS,IAAA;AAAK,SACpD;AAAA,OACH;AACA,MAAA,MAAM,MAAA;AAAA,IACR;AAEA,IAAA,MAAM,QAAA;AAAA,MACJ,UAAA,CAAW;AAAA,QACT,IAAA,EAAM,wBAAA;AAAA,QACN,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,QAAA,CAAS,EAAA;AAAA,QACrB,SAAS,OAAA,CAAQ,QAAA;AAAA,QACjB,MAAA,EAAQ,IAAA;AAAA,QACR,MAAM,EAAE,MAAA,EAAQ,aAAa,MAAA,EAAQ,SAAA,EAAW,aAAa,SAAA;AAAU,OACxE;AAAA,KACH;AAEA,IAAA,MAAM,UAAU,EAAE,SAAA,EAAW,QAAQ,SAAA,EAAW,UAAA,EAAY,SAAS,EAAA,EAAG;AACxE,IAAA,OAAO;AAAA,MACL,MAAA,EAAQ;AAAA,QACN,QAAQ,YAAA,CAAa,MAAA;AAAA,QACrB,WAAW,YAAA,CAAa,SAAA;AAAA,QACxB,GAAI,aAAa,QAAA,KAAa,MAAA,GAAY,EAAE,QAAA,EAAU,YAAA,CAAa,QAAA,EAAS,GAAI;AAAC,OACnF;AAAA,MACA,MAAM,SAAS,MAAA,EAAQ;AACrB,QAAA,IAAI;AACF,UAAA,MAAM,QAAA,CAAS,MAAM,CAAA,CAAE,YAAA,CAAa,eAAe,OAAO,CAAA;AAAA,QAC5D,SAAS,KAAA,EAAO;AAGd,UAAA,OAAA,CAAQ,MAAA,CAAO,KAAA;AAAA,YACb,EAAE,KAAK,aAAA,CAAc,KAAK,GAAG,SAAA,EAAW,OAAA,CAAQ,WAAW,MAAA,EAAO;AAAA,YAClE;AAAA,WACF;AAAA,QACF;AAAA,MACF;AAAA,KACF;AAAA,EACF;AAEA,EAAA,OAAO,mBAAA;AACT;;;AClJO,SAAS,cAAA,CACd,aACA,MAAA,EACuC;AACvC,EAAA,MAAM,QAAA,GAAW,YAAY,SAAA,CAAU,QAAA;AACvC,EAAA,IAAI,QAAA,KAAa,MAAA,IAAa,MAAA,KAAW,MAAA,SAAkB,EAAC;AAC5D,EAAA,OAAO;AAAA,IACL,OAAA,EAAS;AAAA,MACP,GAAI,QAAA,KAAa,MAAA,GAAY,EAAE,SAAA,EAAW,QAAA,KAAa,EAAC;AAAA,MACxD,GAAI,MAAA,KAAW,MAAA,GAAY,EAAE,MAAA,KAAW;AAAC;AAC3C,GACF;AACF;AAKA,IAAM,4CAAiD,IAAI,GAAA,CAAI,CAAC,SAAA,EAAW,UAAU,CAAC,CAAA;AAK/E,SAAS,WAAA,CAAY,OAAsB,WAAA,EAAgD;AAChG,EAAA,IAAI,KAAA,CAAM,IAAA,KAAS,kBAAA,EAAoB,OAAO,KAAA;AAC9C,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,OAAA,GAAU,eAAe,CAAA;AAC9C,EAAA,MAAM,WAAW,OAAO,MAAA,KAAW,QAAA,IAAY,yBAAA,CAA0B,IAAI,MAAM,CAAA;AACnF,EAAA,MAAM,UAAU,WAAA,CAAY,OAAA;AAC5B,EAAA,IAAI,CAAC,QAAA,IAAY,OAAA,KAAY,MAAA,EAAW,OAAO,KAAA;AAC/C,EAAA,OAAO,IAAI,aAAA,CAAc,kBAAA,EAAoB,KAAA,CAAM,OAAA,EAAS;AAAA,IAC1D,GAAI,MAAM,SAAA,KAAc,MAAA,GAAY,EAAE,SAAA,EAAW,KAAA,CAAM,SAAA,EAAU,GAAI,EAAC;AAAA,IACtE,GAAI,MAAM,UAAA,KAAe,MAAA,GAAY,EAAE,UAAA,EAAY,KAAA,CAAM,UAAA,EAAW,GAAI,EAAC;AAAA,IACzE,GAAI,QAAA,GAAW,EAAE,UAAA,EAAY,GAAA,KAAQ,EAAC;AAAA,IACtC,OAAA,EAAS;AAAA,MACP,GAAG,KAAA,CAAM,OAAA;AAAA,MACT,GAAI,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,KAAY,EAAC;AAAA,MAC3C,GAAI,QAAA,GAAW,cAAA,CAAe,WAAW,CAAA,CAAE,UAAU;AAAC;AACxD,GACD,CAAA;AACH;;;ACdO,SAAS,sBAAA,CACd,KACA,mBAAA,EACc;AACd,EAAA,MAAM,EAAE,OAAA,EAAS,QAAA,EAAU,UAAA,EAAW,GAAI,GAAA;AAE1C,EAAA,OAAO,eAAe,YAAA,CAAa,OAAA,EAAS,QAAA,EAAU,SAAS,UAAA,EAAY;AACzE,IAAA,MAAM,QAAA,GAAW,YAAA,CAAa,OAAA,CAAQ,gBAAA,EAAkB,SAAS,cAAc,CAAA;AAC/E,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,8BAAA;AAAA,QACA,CAAA,0CAAA,EAA6C,SAAS,EAAE,CAAA,CAAA,CAAA;AAAA,QACxD;AAAA,UACE,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,OAAA,EAAS,EAAE,cAAA,EAAgB,QAAA,CAAS,cAAA;AAAe;AACrD,OACF;AAAA,IACF;AAIA,IAAA,MAAM,aAAA,GAAgB,6BAAA;AAAA,MACpB,OAAA,CAAQ,0BAA0B,EAAC;AAAA,MACnC,QAAA;AAAA,MACA,OAAA,CAAQ;AAAA,KACV;AAEA,IAAA,IAAI,WAAA;AACJ,IAAA,IAAI;AACF,MAAA,WAAA,GAAc,MAAM,SAAS,iBAAA,CAAkB;AAAA,QAC7C,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,QAAA;AAAA,QACA,QAAQ,OAAA,CAAQ,MAAA;AAAA,QAChB,UAAU,OAAA,CAAQ,QAAA;AAAA,QAClB,WAAA,EAAa,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAO;AAAA;AAAA,QAElC,GAAI,QAAQ,QAAA,KAAa,KAAA,CAAA,GAAY,EAAE,QAAA,EAAU,OAAA,CAAQ,QAAA,EAAS,GAAI;AAAC,OACxE,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,gBAAgB,KAAK,CAAA,GACvB,QACA,IAAI,aAAA,CAAc,gCAAgC,iCAAA,EAAmC;AAAA,QACnF,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,QAAA,CAAS,EAAA;AAAA,QACrB,KAAA,EAAO;AAAA,OACR,CAAA;AAAA,IACP;AAEA,IAAA,IAAI,CAAC,QAAQ,OAAA,EAAS;AACpB,MAAA,MAAM,QAAA;AAAA,QACJ,UAAA,CAAW;AAAA,UACT,IAAA,EAAM,kBAAA;AAAA,UACN,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,SAAS,OAAA,CAAQ,QAAA;AAAA,UACjB,iBAAiB,QAAA,CAAS;AAAA,SAC3B;AAAA,OACH;AACA,MAAA,OAAO;AAAA,QACL,IAAA,EAAM,kBAAA;AAAA,QACN,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,QAAA,CAAS,EAAA;AAAA,QACrB,WAAA;AAAA,QACA,GAAI,aAAA,CAAc,MAAA,GAAS,CAAA,GACvB,EAAE,aAAA,EAAe,aAAA,CAAc,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,CAAA,KACvD;AAAC,OACP;AAAA,IACF;AAEA,IAAA,MAAM,UAAU,OAAA,CAAQ,OAAA;AAExB,IAAA,IAAI,YAAA;AACJ,IAAA,IAAI;AAGF,MAAA,IAAI,SAAS,iBAAA,EAAmB;AAC9B,QAAA,WAAA,GAAc,MAAM,SAAS,iBAAA,CAAkB;AAAA,UAC7C,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,QAAA;AAAA,UACA,WAAA;AAAA,UACA,UAAA,EAAY;AAAA,SACb,CAAA;AAAA,MACH;AACA,MAAA,YAAA,GAAe,MAAM,SAAS,MAAA,CAAO;AAAA,QACnC,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,QAAA;AAAA,QACA,WAAA;AAAA,QACA,UAAA,EAAY;AAAA,OACb,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AAId,MAAA,MAAM,MAAA,GAAS,gBAAgB,KAAK,CAAA,GAChC,QACA,IAAI,aAAA,CAAc,mBAAmB,6BAAA,EAA+B;AAAA,QAClE,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,QAAA,CAAS,EAAA;AAAA,QACrB,KAAA,EAAO,KAAA;AAAA,QACP,GAAG,eAAe,WAAW;AAAA,OAC9B,CAAA;AACL,MAAA,MAAM,QAAA;AAAA,QACJ,UAAA,CAAW;AAAA,UACT,IAAA,EAAM,kBAAA;AAAA,UACN,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,SAAS,OAAA,CAAQ,QAAA;AAAA,UACjB,iBAAiB,QAAA,CAAS,IAAA;AAAA,UAC1B,MAAA,EAAQ,OAAA;AAAA,UACR,IAAA,EAAM,EAAE,MAAA,EAAQ,MAAA,CAAO,IAAA;AAAK,SAC7B;AAAA,OACH;AACA,MAAA,MAAM,MAAA;AAAA,IACR;AAEA,IAAA,IAAI,YAAA,CAAa,WAAW,UAAA,EAAY;AACtC,MAAA,MAAM,QAAA;AAAA,QACJ,UAAA,CAAW;AAAA,UACT,IAAA,EAAM,kBAAA;AAAA,UACN,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,SAAS,OAAA,CAAQ,QAAA;AAAA,UACjB,iBAAiB,QAAA,CAAS,IAAA;AAAA,UAC1B,MAAA,EAAQ,OAAA;AAAA,UACR,IAAA,EAAM,aAAa,eAAA,GAAkB,EAAE,QAAQ,YAAA,CAAa,eAAA,KAAoB;AAAC,SAClF;AAAA,OACH;AACA,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,iBAAA;AAAA,QACA,aAAa,eAAA,IAAmB,sBAAA;AAAA,QAChC;AAAA,UACE,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,GAAG,cAAA,CAAe,WAAA,EAAa,YAAA,CAAa,eAAe;AAAA;AAC7D,OACF;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,aAAa,SAAA,EAAW;AAC3B,MAAA,MAAM,QAAA;AAAA,QACJ,UAAA,CAAW;AAAA,UACT,IAAA,EAAM,kBAAA;AAAA,UACN,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,SAAS,OAAA,CAAQ,QAAA;AAAA,UACjB,iBAAiB,QAAA,CAAS,IAAA;AAAA,UAC1B,MAAA,EAAQ,OAAA;AAAA,UACR,IAAA,EAAM,EAAE,MAAA,EAAQ,oBAAA;AAAqB,SACtC;AAAA,OACH;AACA,MAAA,MAAM,IAAI,aAAA,CAAc,iBAAA,EAAmB,8CAAA,EAAgD;AAAA,QACzF,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,QAAA,CAAS;AAAA,OACtB,CAAA;AAAA,IACH;AACA,IAAA,MAAM,YAAY,YAAA,CAAa,SAAA;AAE/B,IAAA,MAAM,OAAO,MAAM,mBAAA;AAAA,MACjB,OAAA;AAAA,MACA,QAAA;AAAA,MACA,aAAA;AAAA,MACA,WAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,CAAQ,MAAM,qBAAA,CAAsB;AAAA,QACxC,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,QAAA,CAAS,EAAA;AAAA,QACrB,UAAU,QAAA,CAAS,IAAA;AAAA,QACnB,SAAA;AAAA,QACA,QAAQ,YAAA,CAAa,MAAA;AAAA,QACrB,UAAU,YAAA,CAAa,QAAA;AAAA,QACvB,GAAI,aAAa,KAAA,KAAU,KAAA,CAAA,GAAY,EAAE,KAAA,EAAO,YAAA,CAAa,KAAA,EAAM,GAAI,EAAC;AAAA,QACxE,GAAI,aAAa,KAAA,KAAU,KAAA,CAAA,GAAY,EAAE,KAAA,EAAO,YAAA,CAAa,KAAA,EAAM,GAAI,EAAC;AAAA,QACxE,GAAI,WAAA,CAAY,QAAA,GAAW,yCAAyC,CAAA,KAAM,OACtE,EAAE,eAAA,EAAiB,IAAA,EAAK,GACxB;AAAC,OACN,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AAId,MAAA,MAAM,MAAA,GAAS,eAAA;AAAA,QACb,KAAA;AAAA,QACA,eAAA;AAAA,QACA;AAAA,OACF;AACA,MAAA,MAAM,IAAA,EAAM,SAAS,SAAS,CAAA;AAC9B,MAAA,MAAM,QAAA;AAAA,QACJ,UAAA,CAAW;AAAA,UACT,IAAA,EAAM,kBAAA;AAAA,UACN,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,SAAS,OAAA,CAAQ,QAAA;AAAA,UACjB,iBAAiB,QAAA,CAAS,IAAA;AAAA,UAC1B,MAAA,EAAQ,OAAA;AAAA,UACR,IAAA,EAAM,EAAE,MAAA,EAAQ,MAAA,CAAO,IAAA;AAAK,SAC7B;AAAA,OACH;AACA,MAAA,MAAM,WAAA,CAAY,QAAQ,WAAW,CAAA;AAAA,IACvC;AAEA,IAAA,MAAM,QAAA;AAAA,MACJ,UAAA,CAAW;AAAA,QACT,IAAA,EAAM,kBAAA;AAAA,QACN,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,QAAA,CAAS,EAAA;AAAA,QACrB,SAAS,OAAA,CAAQ,QAAA;AAAA,QACjB,iBAAiB,QAAA,CAAS,IAAA;AAAA,QAC1B,MAAA,EAAQ;AAAA,OACT;AAAA,KACH;AAEA,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,UAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACV,OAAA;AAAA,QACA,QAAA;AAAA,QACA,QAAA;AAAA,QACA,WAAA;AAAA,QACA,OAAA;AAAA,QACA,YAAA;AAAA,QACA,SAAA;AAAA,QACA;AAAA;AACF,KACF;AAAA,EACF,CAAA;AACF;AAEA,SAAS,YAAA,CACP,WACA,OAAA,EAC6B;AAC7B,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,MAAM,QAAQ,SAAA,CAAU,IAAA,CAAK,CAAC,QAAA,KAAa,QAAA,CAAS,SAAS,MAAM,CAAA;AACnE,IAAA,IAAI,OAAO,OAAO,KAAA;AAAA,EACpB;AACA,EAAA,OAAO,MAAA;AACT;;;AC9MO,SAAS,sBAAsB,OAAA,EAA0D;AAC9F,EAAA,eAAe,SAAS,KAAA,EAAqC;AAC3D,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,CAAQ,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA;AAAA,IACjC,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,MAAA,CAAO,KAAA;AAAA,QACb,EAAE,GAAA,EAAK,aAAA,CAAc,KAAK,CAAA,EAAG,WAAW,KAAA,CAAM,IAAA,EAAM,SAAA,EAAW,KAAA,CAAM,SAAA,EAAU;AAAA,QAC/E;AAAA,OACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,eAAe,WAAA,CACb,EAAA,EACA,KAAA,EACA,SAAA,EACe;AACf,IAAA,IAAI;AACF,MAAA,MAAM,EAAA,EAAG;AAAA,IACX,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,MAAA,CAAO,KAAA;AAAA,QACb,EAAE,GAAA,EAAK,aAAA,CAAc,KAAK,GAAG,SAAA,EAAU;AAAA,QACvC,uBAAuB,KAAK,CAAA;AAAA,OAC9B;AAAA,IACF;AAAA,EACF;AAEA,EAAA,SAAS,WAAW,OAAA,EAA0D;AAC5E,IAAA,OAAO,EAAE,EAAA,EAAI,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,KAAK,CAAA,EAAG,EAAA,EAAI,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAO,EAAG,GAAG,OAAA,EAAQ;AAAA,EAC/E;AAEA,EAAA,OAAO,EAAE,OAAA,EAAS,QAAA,EAAU,WAAA,EAAa,UAAA,EAAW;AACtD;;;ACnFO,SAAS,iBAAiB,GAAA,EAAkC;AACjE,EAAA,MAAM,EAAE,OAAA,EAAS,QAAA,EAAU,WAAA,EAAa,YAAW,GAAI,GAAA;AAIvD,EAAA,eAAe,OAAO,IAAA,EAA0C;AAC9D,IAAA,MAAM,EAAE,SAAS,QAAA,EAAU,QAAA,EAAU,aAAa,OAAA,EAAS,YAAA,EAAc,SAAA,EAAW,IAAA,EAAK,GACvF,IAAA;AACF,IAAA,IAAI,UAAA;AACJ,IAAA,IAAI;AACF,MAAA,UAAA,GAAa,MAAM,SAAS,MAAA,CAAO;AAAA,QACjC,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,QAAA;AAAA,QACA,WAAA;AAAA,QACA,UAAA,EAAY,OAAA;AAAA,QACZ;AAAA,OACD,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AAGd,MAAA,MAAM,YAAA,GAAe,mBAAmB,KAAK,CAAA;AAC7C,MAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,QAAA,MAAM,IAAA,EAAM,SAAS,SAAS,CAAA;AAC9B,QAAA,MAAM,WAAA;AAAA,UACJ,MACE,OAAA,CAAQ,KAAA,CAAM,oBAAA,CAAqB;AAAA,YACjC,SAAA;AAAA,YACA,MAAA,EAAQ,UAAA;AAAA,YACR,eAAA,EAAiB;AAAA,WAClB,CAAA;AAAA,UACH,qCAAA;AAAA,UACA,OAAA,CAAQ;AAAA,SACV;AACA,QAAA,MAAM,QAAA;AAAA,UACJ,UAAA,CAAW;AAAA,YACT,IAAA,EAAM,kBAAA;AAAA,YACN,WAAW,OAAA,CAAQ,SAAA;AAAA,YACnB,YAAY,QAAA,CAAS,EAAA;AAAA,YACrB,SAAS,OAAA,CAAQ,QAAA;AAAA,YACjB,iBAAiB,QAAA,CAAS,IAAA;AAAA,YAC1B,MAAA,EAAQ,OAAA;AAAA,YACR,IAAA,EAAM,EAAE,MAAA,EAAQ,0BAAA,EAA4B,gBAAgB,YAAA;AAAa,WAC1E;AAAA,SACH;AACA,QAAA,MAAM,IAAI,aAAA;AAAA,UACR,8BAAA;AAAA,UACA,wEAAA;AAAA,UACA,EAAE,WAAW,OAAA,CAAQ,SAAA,EAAW,YAAY,QAAA,CAAS,EAAA,EAAI,OAAO,KAAA;AAAM,SACxE;AAAA,MACF;AAIA,MAAA,MAAM,MAAA,GAAS,iBAAiB,KAAK,CAAA;AACrC,MAAA,MAAM,IAAA,EAAM,SAAS,eAAe,CAAA;AACpC,MAAA,MAAM,WAAA;AAAA,QACJ,MACE,OAAA,CAAQ,KAAA,CAAM,oBAAA,CAAqB;AAAA,UACjC,SAAA;AAAA,UACA,MAAA,EAAQ,sBAAA;AAAA,UACR,GAAI,MAAA,KAAW,MAAA,GAAY,EAAE,iBAAA,EAAmB,MAAA,KAAW,EAAC;AAAA,UAC5D,GAAI,iBAAiB,KAAA,GAAQ,EAAE,iBAAiB,KAAA,CAAM,OAAA,KAAY;AAAC,SACpE,CAAA;AAAA,QACH,4CAAA;AAAA,QACA,OAAA,CAAQ;AAAA,OACV;AACA,MAAA,MAAM,QAAA;AAAA,QACJ,UAAA,CAAW;AAAA,UACT,IAAA,EAAM,kBAAA;AAAA,UACN,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,SAAS,OAAA,CAAQ,QAAA;AAAA,UACjB,iBAAiB,QAAA,CAAS,IAAA;AAAA,UAC1B,MAAA,EAAQ,OAAA;AAAA,UACR,IAAA,EAAM;AAAA,YACJ,MAAA,EAAQ,sBAAA;AAAA,YACR,GAAI,MAAA,KAAW,MAAA,GAAY,EAAE,eAAA,EAAiB,MAAA,KAAW;AAAC;AAC5D,SACD;AAAA,OACH;AAGA,MAAA,MAAM,IAAI,aAAA,CAAc,2BAAA,EAA6B,mCAAA,EAAqC;AAAA,QACxF,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,QAAA,CAAS,EAAA;AAAA,QACrB,KAAA,EAAO,KAAA;AAAA,QACP,OAAA,EAAS;AAAA,UACP,mBAAA,EAAqB,IAAA;AAAA,UACrB,GAAI,MAAA,KAAW,MAAA,GAAY,EAAE,eAAA,EAAiB,MAAA,KAAW,EAAC;AAAA,UAC1D,GAAG,iBAAA,CAAkB,WAAA,EAAa,YAAY;AAAA;AAChD,OACD,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,UAAA,CAAW,WAAW,SAAA,EAAW;AACnC,MAAA,MAAM,IAAA,EAAM,SAAS,SAAS,CAAA;AAC9B,MAAA,MAAM,WAAA;AAAA,QACJ,MACE,OAAA,CAAQ,KAAA,CAAM,oBAAA,CAAqB;AAAA,UACjC,SAAA;AAAA,UACA,MAAA,EAAQ,UAAA;AAAA,UACR,GAAI,WAAW,eAAA,KAAoB,MAAA,GAC/B,EAAE,eAAA,EAAiB,UAAA,CAAW,eAAA,EAAgB,GAC9C,EAAC;AAAA,UACL,GAAI,WAAW,iBAAA,KAAsB,MAAA,GACjC,EAAE,iBAAA,EAAmB,UAAA,CAAW,iBAAA,EAAkB,GAClD;AAAC,SACN,CAAA;AAAA,QACH,gCAAA;AAAA,QACA,OAAA,CAAQ;AAAA,OACV;AACA,MAAA,MAAM,QAAA;AAAA,QACJ,UAAA,CAAW;AAAA,UACT,IAAA,EAAM,kBAAA;AAAA,UACN,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,SAAS,OAAA,CAAQ,QAAA;AAAA,UACjB,iBAAiB,QAAA,CAAS,IAAA;AAAA,UAC1B,MAAA,EAAQ,OAAA;AAAA,UACR,IAAA,EAAM,WAAW,eAAA,GAAkB,EAAE,QAAQ,UAAA,CAAW,eAAA,KAAoB;AAAC,SAC9E;AAAA,OACH;AAEA,MAAA,MAAM,gBAAA,GAAmB,cAAA,CAAe,WAAA,EAAa,UAAA,CAAW,eAAe,CAAA,CAAE,OAAA;AACjF,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,2BAAA;AAAA,QACA,WAAW,eAAA,IAAmB,yBAAA;AAAA,QAC9B;AAAA,UACE,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,UAAA,EAAY,GAAA;AAAA,UACZ,OAAA,EAAS;AAAA,YACP,GAAG,gBAAA;AAAA,YACH,GAAG,iBAAA,CAAkB,WAAA,EAAa,UAAA,EAAY,YAAY;AAAA;AAC5D;AACF,OACF;AAAA,IACF;AAEA,IAAA,MAAM,IAAA,EAAM,SAAS,SAAS,CAAA;AAC9B,IAAA,MAAM,WAAA;AAAA,MACJ,MACE,OAAA,CAAQ,KAAA,CAAM,oBAAA,CAAqB;AAAA,QACjC,SAAA;AAAA,QACA,MAAA,EAAQ,SAAA;AAAA,QACR,GAAI,WAAW,iBAAA,KAAsB,MAAA,GACjC,EAAE,iBAAA,EAAmB,UAAA,CAAW,iBAAA,EAAkB,GAClD;AAAC,OACN,CAAA;AAAA,MACH,+BAAA;AAAA,MACA,OAAA,CAAQ;AAAA,KACV;AACA,IAAA,MAAM,QAAA;AAAA,MACJ,UAAA,CAAW;AAAA,QACT,IAAA,EAAM,iBAAA;AAAA,QACN,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,QAAA,CAAS,EAAA;AAAA,QACrB,SAAS,OAAA,CAAQ,QAAA;AAAA,QACjB,iBAAiB,QAAA,CAAS,IAAA;AAAA,QAC1B,MAAA,EAAQ;AAAA,OACT;AAAA,KACH;AAEA,IAAA,OAAO,UAAA;AAAA,EACT;AAKA,EAAA,eAAe,iBAAA,CAAkB,MAAkB,gBAAA,EAAyC;AAC1F,IAAA,MAAM,EAAE,OAAA,EAAS,QAAA,EAAU,QAAA,EAAU,SAAA,EAAW,MAAK,GAAI,IAAA;AACzD,IAAA,MAAM,IAAA,EAAM,SAAS,SAAS,CAAA;AAC9B,IAAA,MAAM,WAAA;AAAA,MACJ,MACE,OAAA,CAAQ,KAAA,CAAM,oBAAA,CAAqB;AAAA,QACjC,SAAA;AAAA,QACA,MAAA,EAAQ,UAAA;AAAA,QACR,eAAA,EAAiB;AAAA,OAClB,CAAA;AAAA,MACH,sCAAA;AAAA,MACA,OAAA,CAAQ;AAAA,KACV;AACA,IAAA,MAAM,QAAA;AAAA,MACJ,UAAA,CAAW;AAAA,QACT,IAAA,EAAM,kBAAA;AAAA,QACN,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,QAAA,CAAS,EAAA;AAAA,QACrB,SAAS,OAAA,CAAQ,QAAA;AAAA,QACjB,iBAAiB,QAAA,CAAS,IAAA;AAAA,QAC1B,MAAA,EAAQ,OAAA;AAAA,QACR,IAAA,EAAM,EAAE,MAAA,EAAQ,gBAAA,EAAkB,gBAAA;AAAiB,OACpD;AAAA,KACH;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,QAAQ,iBAAA,EAAkB;AACrC;AAGA,SAAS,mBAAmB,KAAA,EAAoC;AAC9D,EAAA,IAAI,CAAC,gBAAgB,KAAK,CAAA,IAAK,MAAM,OAAA,GAAU,wBAAwB,MAAM,IAAA,EAAM;AACjF,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,OAAA,CAAQ,QAAQ,CAAA;AACrC,EAAA,OAAO,OAAO,MAAA,KAAW,QAAA,GAAW,MAAA,GAAS,0BAAA;AAC/C;AAIA,SAAS,iBAAiB,KAAA,EAAoC;AAC5D,EAAA,MAAM,OAAO,eAAA,CAAgB,KAAK,IAAI,KAAA,CAAM,OAAA,GAAU,iBAAiB,CAAA,GAAI,MAAA;AAC3E,EAAA,OAAO,OAAO,IAAA,KAAS,QAAA,GAAW,IAAA,GAAO,MAAA;AAC3C;AAIA,SAAS,iBAAA,CACP,gBACG,OAAA,EACmC;AACtC,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,EAAE,OAAA,KAAY,MAAS,CAAA,EAAG,OAAA,IAAW,WAAA,CAAY,OAAA;AACrF,EAAA,MAAM,KAAA,GAAQ,QAAQ,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,KAAA,KAAU,MAAS,CAAA,EAAG,KAAA;AAC1D,EAAA,OAAO;AAAA,IACL,GAAI,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,KAAY,EAAC;AAAA,IAC3C,GAAI,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,KAAU;AAAC,GACzC;AACF;;;ACtMO,SAAS,wBACd,OAAA,EACmB;AACnB,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAuB;AAE9C,EAAA,SAAS,aAAa,QAAA,EAAuC;AAC3D,IAAA,MAAM,MAAA,GAAS,UAAA,CAAW,GAAA,CAAI,QAAA,CAAS,EAAE,CAAA;AACzC,IAAA,IAAI,QAAQ,OAAO,MAAA;AACnB,IAAA,MAAM,QAAA,GAAW,iBAAA,CAAkB,QAAA,CAAS,WAAW,CAAA;AACvD,IAAA,UAAA,CAAW,GAAA,CAAI,QAAA,CAAS,EAAA,EAAI,QAAQ,CAAA;AACpC,IAAA,OAAO,QAAA;AAAA,EACT;AAEA,EAAA,MAAM,GAAA,GAAM,sBAAsB,OAAO,CAAA;AACzC,EAAA,MAAM,EAAE,QAAA,EAAU,WAAA,EAAa,UAAA,EAAW,GAAI,GAAA;AAC9C,EAAA,MAAM,EAAE,MAAA,EAAQ,iBAAA,EAAkB,GAAI,iBAAiB,GAAG,CAAA;AAC1D,EAAA,MAAM,YAAA,GAAe,sBAAA,CAAuB,GAAA,EAAK,yBAAA,CAA0B,GAAG,CAAC,CAAA;AAE/E,EAAA,eAAe,QAAQ,OAAA,EAAsD;AAC3E,IAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,KAAA,CAAM,WAAA,EAAY;AAGhD,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,SAAA,CAAU,GAAA,CAAI,QAAQ,UAAU,CAAA;AAGzD,IAAA,IAAI,CAAC,QAAA,EAAU,UAAA,CAAW,QAAA,CAAS,OAAA,CAAQ,QAAQ,CAAA,EAAG;AACpD,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,oBAAA;AAAA,QACA,CAAA,UAAA,EAAa,QAAQ,UAAU,CAAA,eAAA,CAAA;AAAA,QAC/B;AAAA,UACE,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,OAAA,CAAQ;AAAA;AACtB,OACF;AAAA,IACF;AAEA,IAAA,MAAM,QAAA;AAAA,MACJ,UAAA,CAAW;AAAA,QACT,IAAA,EAAM,oBAAA;AAAA,QACN,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,QAAA,CAAS,EAAA;AAAA,QACrB,SAAS,OAAA,CAAQ;AAAA,OAClB;AAAA,KACH;AAGA,IAAA,MAAM,aAAA,GAAgB,mBAAA,CAAoB,OAAA,CAAQ,KAAK,CAAA;AACvD,IAAA,MAAM,UAAA,GAAa,YAAA,CAAa,QAAQ,CAAA,CAAE,aAAa,CAAA;AACvD,IAAA,IAAI,CAAC,WAAW,KAAA,EAAO;AACrB,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,eAAA;AAAA,QACA,CAAA,oBAAA,EAAuB,SAAS,EAAE,CAAA,mBAAA,CAAA;AAAA,QAClC;AAAA,UACE,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,OAAA,EAAS,EAAE,MAAA,EAAQ,UAAA,CAAW,MAAA;AAAO;AACvC,OACF;AAAA,IACF;AACA,IAAA,MAAM,aAAa,UAAA,CAAW,KAAA;AAI9B,IAAA,2BAAA;AAAA,MACE,QAAA,CAAS,OAAA;AAAA,MACT,UAAA;AAAA,MACA,EAAE,SAAA,EAAW,OAAA,CAAQ,SAAA,EAAW,UAAA,EAAY,SAAS,EAAA,EAAG;AAAA,MACxD,OAAA,CAAQ;AAAA,KACV;AAGA,IAAA,IAAI,QAAA,CAAS,OAAA,CAAQ,IAAA,KAAS,SAAA,EAAW;AAEvC,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,gBAAA;AAAA,QACA,CAAA,UAAA,EAAa,SAAS,EAAE,CAAA,kCAAA,CAAA;AAAA,QACxB;AAAA,UACE,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS;AAAA;AACvB,OACF;AAAA,IACF;AAIA,IAAA,IAAI,QAAA,CAAS,QAAQ,IAAA,KAAS,OAAA,IAAA,CAAY,SAAS,aAAA,EAAe,QAAA,CAAS,MAAA,IAAU,CAAA,IAAK,CAAA,EAAG;AAC3F,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,gBAAA;AAAA,QACA,CAAA,UAAA,EAAa,SAAS,EAAE,CAAA,mDAAA,CAAA;AAAA,QACxB;AAAA,UACE,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS;AAAA;AACvB,OACF;AAAA,IACF;AAEA,IAAA,IAAI,aAAA;AACJ,IAAA,IAAI,aAAA;AACJ,IAAA,IAAI,kBAAA;AAEJ,IAAA,IAAI,QAAA,CAAS,OAAA,CAAQ,IAAA,KAAS,OAAA,EAAS;AACrC,MAAA,MAAM,YAAY,MAAM,YAAA,CAAa,SAAS,QAAA,EAAU,QAAA,CAAS,SAAS,UAAU,CAAA;AACpF,MAAA,IAAI,SAAA,CAAU,IAAA,KAAS,kBAAA,EAAoB,OAAO,SAAA;AAClD,MAAA,MAAM,EAAE,YAAW,GAAI,SAAA;AACvB,MAAA,aAAA,GAAgB,WAAW,IAAA,EAAM,MAAA;AACjC,MAAA,IAAI,UAAA,CAAW,WAAA,CAAY,QAAA,GAAW,iCAAiC,MAAM,IAAA,EAAM;AACjF,QAAA,kBAAA,GAAqB,UAAA;AAAA,MACvB,CAAA,MAAO;AACL,QAAA,aAAA,GAAgB,MAAM,OAAO,UAAU,CAAA;AAAA,MACzC;AAAA,IACF;AAGA,IAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,KAAA,CAAM,WAAA,EAAY;AAC/C,IAAA,IAAI,eAAA;AACJ,IAAA,IAAI;AACF,MAAA,eAAA,GAAkB,MAAM,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAA,EAAS;AAAA,QAC7D,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,QAAA,CAAS,EAAA;AAAA,QACrB,KAAA,EAAO,UAAA;AAAA,QACP,GAAI,QAAQ,cAAA,KAAmB,KAAA,CAAA,GAAY,EAAE,cAAA,EAAgB,OAAA,CAAQ,cAAA,EAAe,GAAI,EAAC;AAAA,QACzF,GAAI,QAAQ,cAAA,KAAmB,KAAA,CAAA,GAAY,EAAE,cAAA,EAAgB,OAAA,CAAQ,cAAA,EAAe,GAAI;AAAC,OAC1F,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,aAAA,GAAgB,eAAA,CAAgB,KAAA,EAAO,eAAA,EAAiB,qBAAqB,CAAA;AACnF,MAAA,MAAM,QAAA;AAAA,QACJ,UAAA,CAAW;AAAA,UACT,IAAA,EAAM,gBAAA;AAAA,UACN,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,SAAS,OAAA,CAAQ,QAAA;AAAA,UACjB,MAAA,EAAQ,OAAA;AAAA,UACR,YAAY,IAAA,CAAK,KAAA,CAAM,QAAQ,KAAA,CAAM,WAAA,KAAgB,YAAY,CAAA;AAAA,UACjE,IAAA,EAAM,EAAE,IAAA,EAAM,aAAA,CAAc,IAAA;AAAK,SAClC;AAAA,OACH;AAEA,MAAA,IAAI,uBAAuB,MAAA,EAAW;AACpC,QAAA,MAAM,iBAAA,CAAkB,kBAAA,EAAoB,aAAA,CAAc,IAAI,CAAA;AAC9D,QAAA,MAAM,aAAA;AAAA,MACR;AAEA,MAAA,IAAI,kBAAkB,MAAA,EAAW;AAI/B,QAAA,MAAM,aAAA,GAAiC;AAAA,UACrC,EAAA,EAAI,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,SAAS,CAAA;AAAA,UAC9B,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,YAAY,QAAA,CAAS,EAAA;AAAA,UACrB,WAAA,EAAa,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAO;AAAA,UAClC,aAAA,EAAe,mBAAmB,aAAa,CAAA;AAAA,UAC/C,UAAU,OAAA,CAAQ,QAAA;AAAA,UAClB,OAAA,EAAS,aAAA;AAAA,UACT,GAAI,aAAA,KAAkB,MAAA,GAAY,EAAE,aAAA,KAAkB,EAAC;AAAA,UACvD,UAAU,EAAE,SAAA,EAAW,KAAA,EAAO,gBAAA,EAAkB,cAAc,IAAA;AAAK,SACrE;AACA,QAAA,MAAM,WAAA;AAAA,UACJ,MAAM,OAAA,CAAQ,KAAA,CAAM,WAAA,CAAY,aAAa,CAAA;AAAA,UAC7C,8CAAA;AAAA,UACA,OAAA,CAAQ;AAAA,SACV;AAEA,QAAA,MAAM,IAAI,aAAA;AAAA,UACR,eAAA;AAAA,UACA,yFAAA;AAAA,UACA;AAAA,YACE,WAAW,OAAA,CAAQ,SAAA;AAAA,YACnB,YAAY,QAAA,CAAS,EAAA;AAAA,YACrB,KAAA,EAAO,aAAA;AAAA,YACP,OAAA,EAAS;AAAA,cACP,OAAA,EAAS;AAAA,gBACP,QAAQ,aAAA,CAAc,MAAA;AAAA,gBACtB,UAAU,aAAA,CAAc,QAAA;AAAA,gBACxB,QAAQ,aAAA,CAAc,MAAA;AAAA,gBACtB,UAAU,aAAA,CAAc,QAAA;AAAA,gBACxB,GAAI,cAAc,OAAA,KAAY,MAAA,GAAY,EAAE,OAAA,EAAS,aAAA,CAAc,OAAA,EAAQ,GAAI,EAAC;AAAA,gBAChF,GAAI,cAAc,iBAAA,KAAsB,MAAA,GACpC,EAAE,iBAAA,EAAmB,aAAA,CAAc,iBAAA,EAAkB,GACrD,EAAC;AAAA,gBACL,GAAI,cAAc,KAAA,KAAU,MAAA,GAAY,EAAE,KAAA,EAAO,aAAA,CAAc,KAAA,EAAM,GAAI,EAAC;AAAA,gBAC1E,GAAI,OAAO,aAAA,CAAc,QAAA,GAAW,iBAAiB,CAAA,KAAM,QAAA,GACvD,EAAE,eAAA,EAAiB,aAAA,CAAc,QAAA,CAAS,iBAAiB,CAAA,KAC3D,EAAC;AAAA,gBACL,GAAI,OAAO,aAAA,CAAc,QAAA,GAAW,SAAS,CAAA,KAAM,QAAA,GAC/C,EAAE,OAAA,EAAS,aAAA,CAAc,QAAA,CAAS,SAAS,CAAA,KAC3C;AAAC;AACP;AACF;AACF,SACF;AAAA,MACF;AAEA,MAAA,MAAM,aAAA;AAAA,IACR;AAEA,IAAA,MAAM,QAAA;AAAA,MACJ,UAAA,CAAW;AAAA,QACT,IAAA,EAAM,gBAAA;AAAA,QACN,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,QAAA,CAAS,EAAA;AAAA,QACrB,SAAS,OAAA,CAAQ,QAAA;AAAA,QACjB,MAAA,EAAQ,IAAA;AAAA,QACR,YAAY,eAAA,CAAgB,UAAA;AAAA,QAC5B,IAAA,EAAM,EAAE,MAAA,EAAQ,eAAA,CAAgB,MAAA;AAAO,OACxC;AAAA,KACH;AAIA,IAAA,IAAI,uBAAuB,MAAA,EAAW;AACpC,MAAA,aAAA,GAAgB,MAAM,OAAO,kBAAkB,CAAA;AAAA,IACjD;AAGA,IAAA,MAAM,OAAA,GAA2B;AAAA,MAC/B,EAAA,EAAI,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,SAAS,CAAA;AAAA,MAC9B,WAAW,OAAA,CAAQ,SAAA;AAAA,MACnB,YAAY,QAAA,CAAS,EAAA;AAAA,MACrB,WAAA,EAAa,OAAA,CAAQ,KAAA,CAAM,MAAA,EAAO;AAAA,MAClC,eAAe,eAAA,CAAgB,MAAA;AAAA,MAC/B,YAAY,eAAA,CAAgB,UAAA;AAAA,MAC5B,UAAU,OAAA,CAAQ,QAAA;AAAA,MAClB,GAAI,aAAA,KAAkB,MAAA,GAAY,EAAE,OAAA,EAAS,aAAA,KAAkB,EAAC;AAAA,MAChE,GAAI,aAAA,KAAkB,MAAA,GAAY,EAAE,aAAA,KAAkB;AAAC,KACzD;AAEA,IAAA,MAAM,WAAA,CAAY,MAAM,OAAA,CAAQ,KAAA,CAAM,YAAY,OAAO,CAAA,EAAG,aAAA,EAAe,OAAA,CAAQ,SAAS,CAAA;AAE5F,IAAA,MAAM,kBAAkB,IAAA,CAAK,KAAA,CAAM,QAAQ,KAAA,CAAM,WAAA,KAAgB,aAAa,CAAA;AAE9E,IAAA,MAAM,QAAA;AAAA,MACJ,UAAA,CAAW;AAAA,QACT,IAAA,EAAM,oBAAA;AAAA,QACN,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,YAAY,QAAA,CAAS,EAAA;AAAA,QACrB,SAAS,OAAA,CAAQ,QAAA;AAAA,QACjB,MAAA,EAAQ,IAAA;AAAA,QACR,UAAA,EAAY;AAAA,OACb;AAAA,KACH;AAEA,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,WAAA;AAAA,MACN,WAAW,OAAA,CAAQ,SAAA;AAAA,MACnB,YAAY,QAAA,CAAS,EAAA;AAAA,MACrB,eAAe,eAAA,CAAgB,MAAA;AAAA,MAC/B,MAAM,eAAA,CAAgB,IAAA;AAAA,MACtB,SAAS,eAAA,CAAgB,OAAA;AAAA,MACzB,GAAI,aAAA,KAAkB,MAAA,GAAY,EAAE,OAAA,EAAS,aAAA,KAAkB,EAAC;AAAA,MAChE,OAAA;AAAA,MACA,UAAA,EAAY;AAAA,KACd;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,OAAA,EAAQ;AACnB;AAMA,SAAS,mBAAmB,KAAA,EAA8B;AACxD,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,OAAA,GAAU,QAAQ,CAAA;AACvC,EAAA,OAAO,OAAO,MAAA,KAAW,QAAA,GAAW,MAAA,GAAS,CAAA;AAC/C;AAEA,IAAM,mBAAA,GAAyC,CAAC,GAAG,qBAAA,EAAuB,WAAW,CAAA;AAErF,SAAS,oBAAoB,KAAA,EAAyB;AACpD,EAAA,IAAI,CAAC,QAAA,CAAS,KAAK,CAAA,EAAG,OAAO,KAAA;AAE7B,EAAA,IAAI,CAAC,mBAAA,CAAoB,IAAA,CAAK,CAAC,GAAA,KAAQ,MAAA,CAAO,MAAA,CAAO,KAAA,EAAO,GAAG,CAAC,CAAA,EAAG,OAAO,KAAA;AAC1E,EAAA,MAAM,OAAgC,EAAC;AACvC,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,EAAG;AAIpC,IAAA,IAAI,CAAC,oBAAoB,QAAA,CAAS,GAAG,GAAG,IAAA,CAAK,GAAG,CAAA,GAAI,KAAA,CAAM,GAAG,CAAA;AAAA,EAC/D;AACA,EAAA,OAAO,IAAA;AACT;;;AC7TA,IAAM,uBAAN,MAAuD;AAAA,EACpC,IAAA,uBAAW,GAAA,EAA8B;AAAA,EACzC,OAAA;AAAA,EAEjB,YAAY,SAAA,EAAwC;AAClD,IAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AAChC,MAAA,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,QAAA,CAAS,EAAE,CAAA,EAAG;AAC9B,QAAA,MAAM,IAAI,aAAA,CAAc,gBAAA,EAAkB,CAAA,uBAAA,EAA0B,QAAA,CAAS,EAAE,CAAA,CAAA,CAAA,EAAK;AAAA,UAClF,OAAA,EAAS,EAAE,UAAA,EAAY,QAAA,CAAS,EAAA;AAAG,SACpC,CAAA;AAAA,MACH;AACA,MAAA,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,QAAA,CAAS,EAAA,EAAI,QAAQ,CAAA;AAAA,IACrC;AACA,IAAA,IAAA,CAAK,OAAA,GAAU,CAAC,GAAG,SAAS,CAAA;AAAA,EAC9B;AAAA,EAEA,IAAI,EAAA,EAA0C;AAC5C,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,EAAE,CAAA;AAAA,EACzB;AAAA,EAEA,IAAA,GAAoC;AAClC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA,EAEA,eAAe,QAAA,EAAqD;AAClE,IAAA,OAAO,IAAA,CAAK,QAAQ,MAAA,CAAO,CAAC,aAAa,QAAA,CAAS,UAAA,CAAW,QAAA,CAAS,QAAQ,CAAC,CAAA;AAAA,EACjF;AAAA,EAEA,IAAI,EAAA,EAAqB;AACvB,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,EAAE,CAAA;AAAA,EACzB;AACF,CAAA;AAGO,SAAS,uBAAuB,SAAA,EAA0D;AAC/F,EAAA,OAAO,IAAI,qBAAqB,SAAS,CAAA;AAC3C;;;AC3BO,SAAS,qBAAqB,OAAA,EAAiD;AACpF,EAAA,OAAO;AAAA,IACL,MAAM,KAAK,KAAA,EAAqC;AAC9C,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,CAAQ,KAAA,CAAM,WAAA,CAAY,KAAK,CAAA;AAAA,MACvC,SAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,MAAA,CAAO,KAAA;AAAA,UACb,EAAE,GAAA,EAAK,aAAA,CAAc,KAAK,CAAA,EAAG,WAAW,KAAA,CAAM,IAAA,EAAM,SAAA,EAAW,KAAA,CAAM,SAAA,EAAU;AAAA,UAC/E;AAAA,SACF;AAAA,MACF;AAAA,IACF;AAAA,GACF;AACF;;;ACXO,IAAM,gBAAA,GAAmB;AACzB,IAAM,eAAA,GAAkB;AAGxB,IAAM,mBAAA,GAAsB;AAO5B,IAAM,uBAAA,GAA0B;AAAA,EACrC,uBAAA;AAAA,EACA,uBAAA;AAAA,EACA,oBAAA;AAAA,EACA,yBAAA;AAAA,EACA;AACF;AASO,IAAM,wBAAA,GAET;AAAA,EACF,qBAAA,EAAuB,CAAC,MAAM,CAAA;AAAA,EAC9B,qBAAA,EAAuB,CAAC,MAAA,EAAQ,MAAM,CAAA;AAAA,EACtC,kBAAA,EAAoB,CAAC,MAAM,CAAA;AAAA,EAC3B,uBAAA,EAAyB,CAAC,MAAA,EAAQ,MAAM,CAAA;AAAA,EACxC,qBAAA,EAAuB,CAAC,MAAM;AAChC;AAOO,IAAM,iCAAA,GAET;AAAA,EACF,qBAAA,EAAuB,CAAC,MAAM;AAChC;AAGO,IAAM,wBAAA,GAA2B;AAGjC,IAAM,mBAAA,GAAsB;AAS5B,IAAM,sBAAA,GAAyB;AAC/B,IAAM,qBAAA,GAAwB;AAC9B,IAAM,0BAAA,GAA6B;AACnC,IAAM,8BAAA,GAAiC;AAMvC,IAAM,iCAAA,GAAoC;AAM1C,IAAM,yBAAA,GAA4B;AAGlC,IAAM,qBAAA,GAAwB;AAAA,EACnC,iBAAA;AAAA,EACA,YAAA;AAAA,EACA,qBAAA;AAAA,EACA,sBAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF;AAGO,IAAM,+BAAA,GAAkC;AAGxC,IAAM,wCAAA,GAA2C;AACjD,IAAM,oCAAA,GAAuC","file":"chunk-2LN5PO5I.js","sourcesContent":["/**\n * The default configuration filename, shared by the loader, `init`'s default\n * output path and the `--config` help text.\n *\n * Its own module with no imports: `src/cli` loads the rest of `src/config`\n * only through a dynamic import (`src/cli/lib/config-client.ts`), so a broken\n * config module cannot take down commands that never read configuration. A\n * leaf with no module graph can be imported statically without undoing that.\n */\nexport const DEFAULT_CONFIG_FILENAME = 'config.yaml';\n","/**\n * Shapes a backend request from validated input: the path template, query,\n * body and forwarded headers. The pipeline checks the shape before pricing, so\n * a request the backend cannot receive fails before any payment.\n */\nimport type { BackendHandler, BackendMethod } from '../domain/resource';\nimport { CommerceError } from '../errors';\nimport { isRecord } from '../is-record';\n\n// Never forward credentials, transport headers or fields set by the executor\nconst NEVER_FORWARDED_HEADER =\n /^(authorization|cookie|set-cookie|host|content-length|content-type|connection|keep-alive|te|trailer|transfer-encoding|upgrade|idempotency-key|proxy-.*)$/;\n\n// The one `{param}` grammar, shared by substitution, config, `doctor` and the\n// OpenAPI importer. It admits `-` and `.` because\n// `/report/{report-id}` is ordinary REST. Config refuses any other brace\n// (findUnparsedBraceToken).\nconst PATH_PARAM_PATTERN = /\\{([a-zA-Z0-9_.-]+)\\}/g;\n\n/**\n * `{param}` names in a `backend.url` template, in declaration order. Config,\n * `doctor` and the OpenAPI importer use it so they read the same grammar as\n * substitution.\n */\nexport function extractPathParameterNames(url: string): string[] {\n return [...url.matchAll(PATH_PARAM_PATTERN)].map((match) => match[1] as string);\n}\n\n/**\n * A brace left over after every legal `{param}` is removed, or `undefined`.\n *\n * `{report id}`, `{a/b}`, `{}` and an unbalanced `{` match no parameter and\n * would reach the backend as literals, which on a paid resource means payment\n * without delivery. Config refuses any such residue, and the OpenAPI importer\n * skips the operation.\n */\nexport function findUnparsedBraceToken(url: string): string | undefined {\n const residue = url.replace(PATH_PARAM_PATTERN, '');\n const index = residue.search(/[{}]/);\n if (index === -1) return undefined;\n // Report the offending run, not just the character, so the error is fixable\n const token = /\\{[^{}]*\\}?|\\}/.exec(residue.slice(index));\n return token?.[0] ?? residue[index];\n}\n\n/**\n * Check path values, query collisions and headers before pricing. `call()`\n * repeats these checks. Invalid input or forwarded headers raise\n * `INPUT_INVALID`; invalid configured headers raise `BACKEND_ERROR`.\n * An unparseable URL remains a call-time error. Does no I/O.\n */\nexport function validateBackendRequestShape(\n handler: BackendHandler,\n input: unknown,\n context: ShapeContext,\n backendHeaders?: Readonly<Record<string, string>>,\n): void {\n const inputRecord = isRecord(input) ? input : {};\n\n // Every shape error (missing or invalid path parameter, a bound group that is\n // not an object) throws INPUT_INVALID here\n const parts = buildBackendRequestParts(handler, inputRecord, context);\n // Config refuses a bad header at load; this covers a hand-built resource\n buildHeaders(handler, context, backendHeaders);\n\n let target: URL;\n try {\n target = new URL(parts.url);\n } catch {\n return; // call() raises BACKEND_ERROR for an unparseable URL\n }\n checkQueryCollision(target, parts.query, context);\n}\n\ntype ShapeContext = { readonly requestId: string; readonly resourceId: string };\n\n// The path-templated URL plus the query and body values a request carries\ninterface BackendRequestParts {\n readonly url: string;\n readonly query: Record<string, unknown>;\n // Present when a JSON body should be sent; `value` is what gets encoded\n readonly body?: { readonly value: unknown };\n}\n\nfunction acceptsBody(method: BackendMethod): boolean {\n return method !== 'GET' && method !== 'DELETE';\n}\n\n/**\n * Split validated input into URL, query and body according to\n * `handler.inputBindings`. `call()` and `validateBackendRequestShape()` both\n * use it, so they cannot disagree about the request an input describes. Throws\n * only `CommerceError('INPUT_INVALID')`.\n */\nexport function buildBackendRequestParts(\n handler: BackendHandler,\n input: Record<string, unknown>,\n context: ShapeContext,\n): BackendRequestParts {\n const bindings = handler.inputBindings;\n if (bindings === undefined) {\n const { url, remaining } = applyPathTemplate(handler.url, input, context);\n return acceptsBody(handler.method)\n ? { url, query: {}, body: { value: remaining } }\n : { url, query: remaining };\n }\n\n const pathValues =\n bindings.path === undefined ? {} : resolveBoundGroup(input, bindings.path, 'path', context);\n const { url } = applyPathTemplate(handler.url, pathValues, context);\n const query =\n bindings.query === undefined ? {} : resolveBoundGroup(input, bindings.query, 'query', context);\n\n // An absent body value sends no body rather than `null`. A required body is\n // enforced earlier, by `required` in the resource's input schema.\n const bodyValue = bindings.body === undefined ? undefined : input[bindings.body];\n if (bodyValue === undefined || !acceptsBody(handler.method)) return { url, query };\n return { url, query, body: { value: bodyValue } };\n}\n\nfunction resolveBoundGroup(\n input: Record<string, unknown>,\n key: string,\n kind: 'path' | 'query',\n context: ShapeContext,\n): Record<string, unknown> {\n const value = input[key];\n if (value === undefined) return {};\n if (!isRecord(value)) {\n throw new CommerceError(\n 'INPUT_INVALID',\n `Input \"${key}\" must be an object of ${kind} parameters`,\n { ...context, details: { field: key } },\n );\n }\n return value;\n}\n\nexport function checkQueryCollision(\n target: URL,\n remaining: Record<string, unknown>,\n context: { readonly requestId: string; readonly resourceId: string },\n): void {\n const templateKeys = new Set(target.searchParams.keys());\n for (const key of Object.keys(remaining)) {\n if (templateKeys.has(key)) {\n throw new CommerceError(\n 'INPUT_INVALID',\n `Input key \"${key}\" collides with a query parameter already set on backend.url`,\n { requestId: context.requestId, resourceId: context.resourceId, details: { field: key } },\n );\n }\n }\n}\n\n// encodeURIComponent leaves \".\" alone, and new URL() then resolves a \".\" or\n// \"..\" segment, stepping outside the template's directory. Slashes are\n// escaped, so only these exact values (and \"\", an empty segment) need refusing.\nconst TRAVERSAL_PATH_VALUES = new Set(['', '.', '..']);\n\nfunction applyPathTemplate(\n template: string,\n input: Record<string, unknown>,\n context: ShapeContext,\n): { url: string; remaining: Record<string, unknown> } {\n const remaining: Record<string, unknown> = { ...input };\n let missing: string | undefined;\n let invalid: string | undefined;\n const url = template.replace(PATH_PARAM_PATTERN, (_match, key: string) => {\n // Object.hasOwn, not `in`: a parameter named \"constructor\" or \"toString\"\n // would otherwise resolve to the inherited Object.prototype member\n if (!Object.hasOwn(remaining, key)) {\n missing = key;\n return '';\n }\n const value = remaining[key];\n delete remaining[key];\n const raw = stringifyPrimitive(value);\n if (TRAVERSAL_PATH_VALUES.has(raw)) {\n invalid = key;\n return '';\n }\n return encodeURIComponent(raw);\n });\n if (missing !== undefined) {\n // Config refuses a template parameter the input schema cannot supply.\n // This covers a hand-built `CommerceResource` that skipped config: through\n // validateBackendRequestShape it fails before payment, instead of calling\n // the backend with an empty path segment.\n throw new CommerceError('INPUT_INVALID', `Path parameter \"${missing}\" was not supplied`, {\n ...context,\n details: { field: missing },\n });\n }\n if (invalid !== undefined) {\n throw new CommerceError('INPUT_INVALID', `Path parameter \"${invalid}\" is not a valid value`, {\n ...context,\n details: { field: invalid },\n });\n }\n return { url, remaining };\n}\n\nexport function stringifyPrimitive(value: unknown): string {\n if (value === undefined || value === null) return '';\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\n// `Headers` throws a TypeError on an illegal name or value. The error is\n// rethrown typed and without `cause`: the TypeError quotes the value, which may\n// be a credential.\nexport function buildHeaders(\n handler: BackendHandler,\n context: ShapeContext,\n forwarded: Readonly<Record<string, string>> = {},\n): Headers {\n let headers: Headers;\n try {\n headers = new Headers(handler.headers);\n } catch {\n throw invalidHeaderError(context);\n }\n // Caller headers cannot replace operator-configured backend credentials\n for (const [name, value] of Object.entries(forwarded)) {\n if (NEVER_FORWARDED_HEADER.test(name.toLowerCase())) continue;\n try {\n if (!headers.has(name)) headers.set(name, value);\n } catch {\n throw new CommerceError('INPUT_INVALID', 'A forwarded request header is invalid', {\n ...context,\n details: { reason: 'invalid-forwarded-header' },\n });\n }\n }\n return headers;\n}\n\nexport function setHeader(\n headers: Headers,\n name: string,\n value: string,\n context: ShapeContext,\n): void {\n try {\n headers.set(name, value);\n } catch {\n throw invalidHeaderError(context);\n }\n}\n\nfunction invalidHeaderError(context: ShapeContext): CommerceError {\n return new CommerceError('BACKEND_ERROR', 'Backend request headers are invalid', {\n ...context,\n details: { reason: 'invalid-header' },\n });\n}\n","/**\n * The built-in outbound HTTP path to a merchant backend.\n *\n * - Global `fetch`, always bounded by `AbortSignal.timeout`.\n * - `redirect: 'manual'`: a 3xx response is a `BACKEND_ERROR`, never followed\n * (SSRF hardening).\n * - `{param}` segments in `handler.url` are filled from validated input and\n * URL-encoded; the rest is mapped as `BackendHandler.inputBindings`\n * describes (see `backend-request.ts`).\n */\nimport { type BackendHandler, DEFAULT_BACKEND_TIMEOUT_MS } from '../domain/resource';\nimport { CommerceError, isCommerceError } from '../errors';\nimport type { BackendExecutor, BackendRequest, BackendResponse } from '../interfaces/backend';\nimport { type Logger, NOOP_LOGGER } from '../interfaces/logger';\nimport { isRecord } from '../is-record';\nimport {\n buildBackendRequestParts,\n buildHeaders,\n checkQueryCollision,\n setHeader,\n stringifyPrimitive,\n} from './backend-request';\n\nconst MAX_BODY_SNIPPET_LENGTH = 512;\n\n// How a merchant recognizes a repeat of an operation. The de facto standard\n// name, and the one ACP requires inbound.\nconst IDEMPOTENCY_KEY_HEADER = 'idempotency-key';\n\n// The timeout bounds a response by time, not bytes; this stops a hostile or\n// broken backend from filling memory\nconst MAX_RESPONSE_BODY_BYTES = 1024 * 1024;\n\nexport interface HttpBackendExecutorOptions {\n /** Override for `fetch`, used in tests. Defaults to the global implementation */\n readonly fetchImpl?: typeof fetch;\n /** Receives a non-2xx backend body at debug level; it never reaches the client */\n readonly logger?: Logger;\n}\n\n/**\n * Merchant non-2xx response attached as the `BACKEND_ERROR` cause. Adapters\n * can inspect its body and headers; client errors omit the cause.\n */\nexport class BackendErrorResponse {\n constructor(\n readonly status: number,\n readonly body: unknown,\n /** Lowercase names, as `Headers` yields them */\n readonly headers: Readonly<Record<string, string>> = {},\n ) {}\n}\n\nexport class HttpBackendExecutor implements BackendExecutor {\n private readonly fetchImpl: typeof fetch;\n private readonly logger: Logger;\n\n constructor(options: HttpBackendExecutorOptions = {}) {\n this.fetchImpl = options.fetchImpl ?? fetch;\n this.logger = options.logger ?? NOOP_LOGGER;\n }\n\n async call(handler: BackendHandler, request: BackendRequest): Promise<BackendResponse> {\n const timeoutMs = handler.timeoutMs ?? DEFAULT_BACKEND_TIMEOUT_MS;\n const inputRecord = isRecord(request.input) ? request.input : {};\n\n const context = { requestId: request.requestId, resourceId: request.resourceId };\n // Throws INPUT_INVALID for every shape problem. The pipeline already ran it\n // before payment through validateBackendRequestShape(); this copy covers a\n // caller that bypasses the pipeline.\n const parts = buildBackendRequestParts(handler, inputRecord, context);\n\n let target: URL;\n try {\n target = new URL(parts.url);\n } catch (error) {\n throw new CommerceError('BACKEND_ERROR', 'Backend URL could not be constructed from input', {\n ...context,\n details: { reason: 'invalid-url' },\n cause: error,\n });\n }\n\n // Beyond the per-parameter check: the resolved path must stay under the\n // template's literal prefix (everything before the first `{`)\n const prefixPathname = literalPrefixPathname(handler);\n if (prefixPathname !== undefined && !target.pathname.startsWith(prefixPathname)) {\n throw new CommerceError(\n 'INPUT_INVALID',\n 'Path parameters resolved outside the configured backend path',\n context,\n );\n }\n\n const headers = buildHeaders(handler, context, request.backendHeaders);\n // Replaces a configured header of the same name, unlike content-type below:\n // a static key would make every request look like a retry of the first\n if (request.idempotencyKey !== undefined) {\n setHeader(headers, IDEMPOTENCY_KEY_HEADER, request.idempotencyKey, context);\n }\n let body: string | undefined;\n\n // searchParams.set() replaces an existing param, so a caller key named\n // like an operator's query param (`?apikey=SECRET` in handler.url) would\n // overwrite it. validateBackendRequestShape() runs the same check before\n // payment.\n checkQueryCollision(target, parts.query, context);\n for (const [key, value] of Object.entries(parts.query)) {\n target.searchParams.set(key, stringifyPrimitive(value));\n }\n if (parts.body !== undefined) {\n body = JSON.stringify(parts.body.value);\n // A configured Content-Type, such as `application/vnd.x+json`, wins\n if (!headers.has('content-type')) headers.set('content-type', 'application/json');\n }\n\n const started = performance.now();\n let response: Response;\n try {\n response = await this.fetchImpl(target, {\n method: handler.method,\n headers,\n ...(body !== undefined ? { body } : {}),\n redirect: 'manual',\n signal: AbortSignal.timeout(timeoutMs),\n });\n } catch (error) {\n const durationMs = Math.round(performance.now() - started);\n if (isAbortError(error)) {\n throw new CommerceError(\n 'BACKEND_TIMEOUT',\n `Backend request timed out after ${timeoutMs}ms`,\n {\n requestId: request.requestId,\n resourceId: request.resourceId,\n details: { timeoutMs, durationMs },\n cause: error,\n },\n );\n }\n throw new CommerceError('BACKEND_ERROR', 'Backend request failed (transport error)', {\n requestId: request.requestId,\n resourceId: request.resourceId,\n details: { durationMs },\n cause: error,\n });\n }\n const durationMs = Math.round(performance.now() - started);\n\n const isRedirect =\n response.type === 'opaqueredirect' || (response.status >= 300 && response.status < 400);\n if (isRedirect) {\n throw new CommerceError(\n 'BACKEND_ERROR',\n 'Backend responded with a redirect, which is not followed',\n {\n requestId: request.requestId,\n resourceId: request.resourceId,\n details: { status: response.status, reason: 'redirect-not-followed' },\n },\n );\n }\n\n const responseHeaders = Object.fromEntries(response.headers);\n const contentType = response.headers.get('content-type') ?? '';\n let parsedBody: unknown;\n try {\n parsedBody = await parseBody(response, contentType);\n } catch (error) {\n const tooLarge = isCommerceError(error);\n throw new CommerceError(\n 'BACKEND_ERROR',\n tooLarge\n ? 'Backend response exceeded the maximum allowed size'\n : 'Backend response could not be read',\n {\n requestId: request.requestId,\n resourceId: request.resourceId,\n details: tooLarge\n ? { reason: 'response-too-large', maxBytes: MAX_RESPONSE_BODY_BYTES }\n : { reason: 'read-error' },\n cause: error,\n },\n );\n }\n\n if (response.status < 200 || response.status >= 300) {\n // The status may reach the client, but the body is logged at debug level\n // only: a backend in verbose error mode emits stack traces, hostnames or\n // SQL fragments, and the caller may be anonymous\n this.logger.debug(\n {\n requestId: request.requestId,\n resourceId: request.resourceId,\n status: response.status,\n bodySnippet: truncateSnippet(parsedBody),\n },\n 'Backend responded with a non-2xx status',\n );\n throw new CommerceError('BACKEND_ERROR', `Backend responded with status ${response.status}`, {\n requestId: request.requestId,\n resourceId: request.resourceId,\n details: { status: response.status },\n cause: new BackendErrorResponse(response.status, parsedBody, responseHeaders),\n });\n }\n\n return {\n status: response.status,\n headers: responseHeaders,\n body: parsedBody,\n durationMs,\n };\n }\n}\n\n// `handler.url` never changes, so its literal prefix is parsed once per handler.\n// `null` records a prefix that is not a URL, as when a parameter sits in the\n// host (which config refuses); the containment check is then skipped.\nconst prefixPathnames = new WeakMap<BackendHandler, string | null>();\n\nfunction literalPrefixPathname(handler: BackendHandler): string | undefined {\n let cached = prefixPathnames.get(handler);\n if (cached === undefined) {\n try {\n cached = new URL(handler.url.split('{')[0] ?? handler.url).pathname;\n } catch {\n cached = null;\n }\n prefixPathnames.set(handler, cached);\n }\n return cached ?? undefined;\n}\n\nasync function readBodyCapped(response: Response, maxBytes: number): Promise<string> {\n if (!response.body) return '';\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let total = 0;\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n total += value.byteLength;\n if (total > maxBytes) {\n await reader.cancel();\n // The only CommerceError parseBody can throw, which is how its caller\n // tells an oversized body from a read failure\n throw new CommerceError('BACKEND_ERROR', `response body exceeded ${maxBytes} bytes`);\n }\n chunks.push(value);\n }\n } finally {\n reader.releaseLock();\n }\n return Buffer.concat(chunks).toString('utf8');\n}\n\nasync function parseBody(response: Response, contentType: string): Promise<unknown> {\n const text = await readBodyCapped(response, MAX_RESPONSE_BODY_BYTES);\n if (text.length === 0) return text;\n if (contentType.includes('json')) {\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n }\n return text;\n}\n\nfunction truncateSnippet(body: unknown): string {\n const text = typeof body === 'string' ? body : safeStringify(body);\n return text.length > MAX_BODY_SNIPPET_LENGTH\n ? `${text.slice(0, MAX_BODY_SNIPPET_LENGTH)}…`\n : text;\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof Error && (error.name === 'TimeoutError' || error.name === 'AbortError');\n}\n","/**\n * A small JSON Schema validator for resource input.\n *\n * Supported subset (draft 2020-12 vocabulary, structural only):\n * - `type`: \"object\" | \"string\" | \"number\" | \"integer\" | \"boolean\" | \"array\" |\n * \"null\", or an array of those (e.g. `[\"object\", \"null\"]`)\n * - `properties` (validated recursively)\n * - `required` (string[])\n * - `additionalProperties` (boolean, or a schema applied to extra properties)\n * - `enum` (allowed values; objects and arrays compared structurally, in any key\n * order)\n * - `items` (one schema applied to every array element, no tuple form)\n *\n * Not enforced: `minLength`, `maxLength`, `pattern`, `format`, `minimum`,\n * `maximum`, `exclusiveMinimum/Maximum`, `multipleOf`, `oneOf`, `anyOf`,\n * `allOf`, `not`, `$ref`, `const`, `patternProperties`, `minItems`,\n * `maxItems`, `uniqueItems`, tuple-form `items`, and a `type` naming anything\n * outside the list above. Config warns at load when a schema uses one of these\n * keywords or a tuple `items`.\n */\nimport { isDeepStrictEqual } from 'node:util';\nimport type { JsonSchema } from '../domain/common';\nimport { isRecord } from '../is-record';\n\nexport interface FieldError {\n readonly path: string;\n readonly message: string;\n}\n\nexport type ValidationResult =\n | { readonly valid: true; readonly value: unknown }\n | { readonly valid: false; readonly errors: readonly FieldError[] };\n\nexport type Validator = (input: unknown) => ValidationResult;\n\nconst SUPPORTED_TYPES = new Set([\n 'object',\n 'string',\n 'number',\n 'integer',\n 'boolean',\n 'array',\n 'null',\n]);\n\n/** Wrap a resource `inputSchema` in a reusable validator function */\nexport function compileJsonSchema(schema: JsonSchema | undefined): Validator {\n return (input: unknown): ValidationResult => {\n if (schema === undefined) return { valid: true, value: input };\n const errors = validateNode(schema, input, '$');\n return errors.length === 0 ? { valid: true, value: input } : { valid: false, errors };\n };\n}\n\nfunction matchesType(type: string, value: unknown): boolean {\n switch (type) {\n case 'object':\n return isRecord(value);\n case 'array':\n return Array.isArray(value);\n case 'string':\n return typeof value === 'string';\n case 'boolean':\n return typeof value === 'boolean';\n case 'number':\n return typeof value === 'number' && Number.isFinite(value);\n case 'integer':\n return typeof value === 'number' && Number.isInteger(value);\n case 'null':\n return value === null;\n default:\n return true;\n }\n}\n\nfunction describeType(value: unknown): string {\n if (value === null) return 'null';\n if (Array.isArray(value)) return 'array';\n return typeof value;\n}\n\n// `===` first keeps a top-level -0 equal to 0; isDeepStrictEqual alone would not\nfunction deepEqual(a: unknown, b: unknown): boolean {\n return a === b || isDeepStrictEqual(a, b);\n}\n\nfunction own(obj: Record<string, unknown>, key: string): unknown {\n return Object.hasOwn(obj, key) ? obj[key] : undefined;\n}\n\n// `type` may be a string or an array of strings, e.g. `[\"object\", \"null\"]`. An\n// array with a non-string entry is ignored rather than guessed at.\nfunction typeList(raw: unknown): string[] | undefined {\n if (typeof raw === 'string') return [raw];\n if (Array.isArray(raw) && raw.every((entry): entry is string => typeof entry === 'string')) {\n return raw;\n }\n return undefined;\n}\n\n/**\n * Whether a schema node is an object schema: its `type` includes \"object\"\n * (`[\"object\", \"null\"]` counts), or it has no `type` and declares `properties`\n * or `required`.\n *\n * Config's `defaultClosedObjectSchema` uses it to close schemas and this\n * validator uses it to enforce them. With two definitions, a node could stay\n * open while config believes it closed.\n */\nexport function isObjectSchemaNode(schema: Record<string, unknown>): boolean {\n const types = typeList(schema['type']);\n if (types !== undefined) return types.includes('object');\n return Object.hasOwn(schema, 'properties') || Object.hasOwn(schema, 'required');\n}\n\nfunction validateNode(schema: JsonSchema, value: unknown, path: string): FieldError[] {\n const errors: FieldError[] = [];\n const types = typeList(own(schema, 'type'));\n const recognizedTypes = types?.filter((entry) => SUPPORTED_TYPES.has(entry));\n\n if (\n types !== undefined &&\n recognizedTypes !== undefined &&\n recognizedTypes.length === types.length &&\n types.length > 0\n ) {\n if (!types.some((entry) => matchesType(entry, value))) {\n errors.push({\n path,\n message: `expected type \"${types.join(' | ')}\" but got ${describeType(value)}`,\n });\n return errors;\n }\n }\n\n const enumRaw = own(schema, 'enum');\n if (Array.isArray(enumRaw)) {\n const allowed = enumRaw as unknown[];\n if (!allowed.some((candidate) => deepEqual(candidate, value))) {\n errors.push({ path, message: `must be one of ${JSON.stringify(allowed)}` });\n }\n }\n\n if (isObjectSchemaNode(schema) && isRecord(value)) {\n errors.push(...validateObject(schema, value, path));\n } else if ((types?.includes('array') ?? false) && Array.isArray(value)) {\n errors.push(...validateArray(schema, value, path));\n }\n\n return errors;\n}\n\nfunction validateObject(\n schema: JsonSchema,\n value: Record<string, unknown>,\n path: string,\n): FieldError[] {\n const errors: FieldError[] = [];\n const propsRaw = own(schema, 'properties');\n const properties = isRecord(propsRaw) ? propsRaw : {};\n const requiredRaw = own(schema, 'required');\n const required = Array.isArray(requiredRaw)\n ? requiredRaw.filter((entry): entry is string => typeof entry === 'string')\n : [];\n\n for (const key of required) {\n // Object.hasOwn, not `in`: `in` walks the prototype chain, so a required\n // \"toString\" or \"__proto__\" would always look present\n if (!Object.hasOwn(value, key)) {\n errors.push({ path: `${path}.${key}`, message: 'is required' });\n }\n }\n\n const additional = own(schema, 'additionalProperties');\n\n for (const key of Object.keys(value)) {\n // Own-property lookup: `properties[\"toString\"]` would find the inherited\n // member and skip the additionalProperties check below\n const propSchemaRaw = own(properties, key);\n if (propSchemaRaw !== undefined) {\n if (isRecord(propSchemaRaw)) {\n errors.push(...validateNode(propSchemaRaw, value[key], `${path}.${key}`));\n }\n continue;\n }\n if (additional === false) {\n errors.push({ path: `${path}.${key}`, message: 'additional property not allowed' });\n } else if (isRecord(additional)) {\n errors.push(...validateNode(additional, value[key], `${path}.${key}`));\n }\n }\n\n return errors;\n}\n\nfunction validateArray(schema: JsonSchema, value: unknown[], path: string): FieldError[] {\n const errors: FieldError[] = [];\n const itemsRaw = own(schema, 'items');\n if (isRecord(itemsRaw)) {\n value.forEach((item, index) => {\n errors.push(...validateNode(itemsRaw, item, `${path}[${index}]`));\n });\n }\n return errors;\n}\n","// Verifies and reserves the authorization a resource requires, before its payment is reserved\nimport type { AuthorizationProvider, AuthorizationVerification } from '../../domain/authorization';\nimport type { AuthorizationMethodName } from '../../domain/common';\nimport type { PaymentRequirement } from '../../domain/payment';\nimport type { CanonicalRequest } from '../../domain/request';\nimport type { CommerceResource } from '../../domain/resource';\nimport { CommerceError, describeError, isCommerceError } from '../../errors';\nimport type { AuthorizationHold, PipelineContext } from './context';\n\n// The provider for each method a resource requires, in the resource's order.\n// Config refuses a method that is not enabled at load; it is checked again\n// because missing it here would serve the resource with no authorization.\nexport function resolveAuthorizationProviders(\n providers: readonly AuthorizationProvider[],\n resource: CommerceResource,\n requestId: string,\n): readonly AuthorizationProvider[] {\n const required = resource.authorization?.required ?? [];\n return required.map((method: AuthorizationMethodName) => {\n const found = providers.find((provider) => provider.name === method);\n if (!found) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n `Resource \"${resource.id}\" requires authorization method \"${method}\", which is not enabled`,\n { requestId, resourceId: resource.id },\n );\n }\n return found;\n });\n}\n\nexport type AuthorizeAndReserve = (\n request: CanonicalRequest,\n resource: CommerceResource,\n providers: readonly AuthorizationProvider[],\n requirement: PaymentRequirement,\n input: unknown,\n) => Promise<AuthorizationHold | undefined>;\n\nexport function createAuthorizeAndReserve(ctx: PipelineContext): AuthorizeAndReserve {\n const { options, safeEmit, buildEvent } = ctx;\n\n // Verify and reserve what the resource requires, or undefined if it requires\n // none. Runs after payment verification, which has no side effect, so a bad\n // payment proof cannot burn a reservation.\n async function authorizeAndReserve(\n request: CanonicalRequest,\n resource: CommerceResource,\n providers: readonly AuthorizationProvider[],\n requirement: PaymentRequirement,\n input: unknown,\n ): Promise<AuthorizationHold | undefined> {\n if (providers.length === 0) return undefined;\n\n const submission = request.authorization;\n const provider = providers.find((candidate) => candidate.name === submission?.method);\n // A request carries one proof, so a resource requiring two methods is\n // refused here rather than half-checked\n const unmet = providers.filter((candidate) => candidate !== provider).map((c) => c.name);\n\n if (submission === undefined || provider === undefined || unmet.length > 0) {\n await safeEmit(\n buildEvent({\n type: 'authorization.rejected',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n status: 'error',\n data: { reason: 'AUTHORIZATION_REQUIRED', methods: unmet },\n }),\n );\n throw new CommerceError(\n 'AUTHORIZATION_REQUIRED',\n `Resource \"${resource.id}\" requires authorization: ${unmet.join(', ')}`,\n {\n requestId: request.requestId,\n resourceId: resource.id,\n details: { required: providers.map((candidate) => candidate.name), missing: unmet },\n },\n );\n }\n\n let verification: AuthorizationVerification;\n try {\n verification = await provider.verifyAndReserve({\n requestId: request.requestId,\n resourceId: resource.id,\n input,\n submission,\n requirement,\n });\n } catch (error) {\n // An untyped throw says nothing about whose fault it was. Unavailable is\n // honest and retryable; invalid would blame the buyer for our outage.\n const mapped = isCommerceError(error)\n ? error\n : new CommerceError(\n 'AUTHORIZATION_PROVIDER_UNAVAILABLE',\n 'Authorization provider is unavailable',\n {\n requestId: request.requestId,\n resourceId: resource.id,\n cause: error,\n },\n );\n await safeEmit(\n buildEvent({\n type: 'authorization.rejected',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n status: 'error',\n data: { reason: mapped.code, method: provider.name },\n }),\n );\n throw mapped;\n }\n\n await safeEmit(\n buildEvent({\n type: 'authorization.verified',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n status: 'ok',\n data: { method: verification.method, reference: verification.reference },\n }),\n );\n\n const context = { requestId: request.requestId, resourceId: resource.id };\n return {\n record: {\n method: verification.method,\n reference: verification.reference,\n ...(verification.metadata !== undefined ? { metadata: verification.metadata } : {}),\n },\n async finalize(action) {\n try {\n await provider[action](verification.reservationId, context);\n } catch (error) {\n // A failure leaves the reservation reserved, which is still\n // unspendable, so the caller's outcome stands\n options.logger.error(\n { err: describeError(error), requestId: request.requestId, action },\n 'Authorization finalization failed; the reservation stays reserved',\n );\n }\n },\n };\n }\n\n return authorizeAndReserve;\n}\n","// What a refused or replayed payment answers with: the unused challenge, when one may be retried\nimport type { PaymentRequirement } from '../../domain/payment';\nimport { CommerceError } from '../../errors';\n\n// A refusal leaves this request's challenge unused. Return it with the\n// provider's reason so the client can retry without fetching another challenge\nexport function retryChallenge(\n requirement: PaymentRequirement,\n reason?: string,\n): { details?: Record<string, unknown> } {\n const envelope = requirement.challenge.envelope;\n if (envelope === undefined && reason === undefined) return {};\n return {\n details: {\n ...(envelope !== undefined ? { challenge: envelope } : {}),\n ...(reason !== undefined ? { reason } : {}),\n },\n };\n}\n\n// Attempt statuses the pipeline treats as finished when handling a replay. The\n// legacy `failed` is not one: it recorded any throw from settle(), so it may\n// hide a transfer, like `settlement-uncertain`.\nconst FINISHED_ATTEMPT_STATUSES: ReadonlySet<string> = new Set(['settled', 'rejected']);\n\n// Include the paid offer's network for the rail's replay code. Finished\n// attempts get 402 with a fresh challenge; unfinished or unreadable attempts\n// keep 409 to avoid prompting a second payment.\nexport function replayError(error: CommerceError, requirement: PaymentRequirement): CommerceError {\n if (error.code !== 'PAYMENT_REPLAYED') return error;\n const status = error.details?.['attemptStatus'];\n const finished = typeof status === 'string' && FINISHED_ATTEMPT_STATUSES.has(status);\n const network = requirement.network;\n if (!finished && network === undefined) return error;\n return new CommerceError('PAYMENT_REPLAYED', error.message, {\n ...(error.requestId !== undefined ? { requestId: error.requestId } : {}),\n ...(error.resourceId !== undefined ? { resourceId: error.resourceId } : {}),\n ...(finished ? { httpStatus: 402 } : {}),\n details: {\n ...error.details,\n ...(network !== undefined ? { network } : {}),\n ...(finished ? retryChallenge(requirement).details : {}),\n },\n });\n}\n","// The payment phase: challenge, offer selection, verification, and the authorization and replay reservations\n\nimport type { PaymentMethodName } from '../../domain/common';\nimport type { PaymentProvider, PaymentRequirement, PaymentResult } from '../../domain/payment';\nimport type { CanonicalRequest, PaymentRequiredOutcome } from '../../domain/request';\nimport type { CommerceResource, Pricing } from '../../domain/resource';\nimport { CommerceError, isCommerceError, toCommerceError } from '../../errors';\nimport { REUSE_REJECTED_AUTHORIZATION_METADATA_KEY } from '../settlement-order';\nimport { type AuthorizeAndReserve, resolveAuthorizationProviders } from './authorization';\nimport { replayError, retryChallenge } from './challenge';\nimport type { PipelineContext, SettleArgs } from './context';\n\n/** A verified payment whose authorization and replay identity are reserved */\nexport interface AdmittedPayment {\n readonly kind: 'admitted';\n readonly settleArgs: SettleArgs;\n}\n\nexport type AdmitPayment = (\n request: CanonicalRequest,\n resource: CommerceResource,\n pricing: Extract<Pricing, { type: 'fixed' }>,\n validInput: unknown,\n) => Promise<PaymentRequiredOutcome | AdmittedPayment>;\n\n/**\n * Builds the payment phase. It returns the challenge when the request carries\n * no proof, and otherwise verifies the proof and reserves the authorization\n * and replay identity, or throws.\n */\nexport function createPaymentAdmission(\n ctx: PipelineContext,\n authorizeAndReserve: AuthorizeAndReserve,\n): AdmitPayment {\n const { options, safeEmit, buildEvent } = ctx;\n\n return async function admitPayment(request, resource, pricing, validInput) {\n const provider = pickProvider(options.paymentProviders, resource.paymentMethods);\n if (!provider) {\n throw new CommerceError(\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n `No enabled payment provider for resource \"${resource.id}\"`,\n {\n requestId: request.requestId,\n resourceId: resource.id,\n details: { paymentMethods: resource.paymentMethods },\n },\n );\n }\n\n // Resolved before the challenge so the 402 can name what the retry must\n // also carry, and so an uncheckable method fails before payment starts\n const authProviders = resolveAuthorizationProviders(\n options.authorizationProviders ?? [],\n resource,\n request.requestId,\n );\n\n let requirement: PaymentRequirement;\n try {\n requirement = await provider.createRequirement({\n requestId: request.requestId,\n resource,\n amount: pricing.amount,\n currency: pricing.currency,\n requestedAt: options.clock.nowIso(),\n // Transport facts a rail may bind into its challenge, such as a body digest\n ...(request.metadata !== undefined ? { metadata: request.metadata } : {}),\n });\n } catch (error) {\n throw isCommerceError(error)\n ? error\n : new CommerceError('PAYMENT_PROVIDER_UNAVAILABLE', 'Payment provider is unavailable', {\n requestId: request.requestId,\n resourceId: resource.id,\n cause: error,\n });\n }\n\n if (!request.payment) {\n await safeEmit(\n buildEvent({\n type: 'payment.required',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n paymentProvider: provider.name,\n }),\n );\n return {\n kind: 'payment-required',\n requestId: request.requestId,\n resourceId: resource.id,\n requirement,\n ...(authProviders.length > 0\n ? { authorization: authProviders.map((p) => p.requirement) }\n : {}),\n };\n }\n\n const payment = request.payment;\n\n let verification: PaymentResult;\n try {\n // Later steps, including authorization and settlement order, use the\n // selected requirement with its full retry challenge\n if (provider.selectRequirement) {\n requirement = await provider.selectRequirement({\n requestId: request.requestId,\n resource,\n requirement,\n submission: payment,\n });\n }\n verification = await provider.verify({\n requestId: request.requestId,\n resource,\n requirement,\n submission: payment,\n });\n } catch (error) {\n // A typed CommerceError is rethrown as is, keeping its code and its\n // possibly retryable status. Only an untyped throw is mapped, with a\n // fixed client-facing message.\n const mapped = isCommerceError(error)\n ? error\n : new CommerceError('PAYMENT_INVALID', 'Payment verification failed', {\n requestId: request.requestId,\n resourceId: resource.id,\n cause: error,\n ...retryChallenge(requirement),\n });\n await safeEmit(\n buildEvent({\n type: 'payment.rejected',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n paymentProvider: provider.name,\n status: 'error',\n data: { reason: mapped.code },\n }),\n );\n throw mapped;\n }\n\n if (verification.status !== 'verified') {\n await safeEmit(\n buildEvent({\n type: 'payment.rejected',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n paymentProvider: provider.name,\n status: 'error',\n data: verification.rejectionReason ? { reason: verification.rejectionReason } : {},\n }),\n );\n throw new CommerceError(\n 'PAYMENT_INVALID',\n verification.rejectionReason ?? 'Payment was rejected',\n {\n requestId: request.requestId,\n resourceId: resource.id,\n ...retryChallenge(requirement, verification.rejectionReason),\n },\n );\n }\n\n if (!verification.replayKey) {\n await safeEmit(\n buildEvent({\n type: 'payment.rejected',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n paymentProvider: provider.name,\n status: 'error',\n data: { reason: 'missing-replay-key' },\n }),\n );\n throw new CommerceError('PAYMENT_INVALID', 'Payment provider did not return a replay key', {\n requestId: request.requestId,\n resourceId: resource.id,\n });\n }\n const replayKey = verification.replayKey;\n\n const hold = await authorizeAndReserve(\n request,\n resource,\n authProviders,\n requirement,\n validInput,\n );\n\n try {\n await options.store.reservePaymentAttempt({\n requestId: request.requestId,\n resourceId: resource.id,\n provider: provider.name,\n replayKey,\n amount: verification.amount,\n currency: verification.currency,\n ...(verification.payer !== undefined ? { payer: verification.payer } : {}),\n ...(verification.payee !== undefined ? { payee: verification.payee } : {}),\n ...(requirement.metadata?.[REUSE_REJECTED_AUTHORIZATION_METADATA_KEY] === true\n ? { reclaimRejected: true }\n : {}),\n });\n } catch (error) {\n // A duplicate replayKey arrives as PAYMENT_REPLAYED and is kept. Any\n // other failure (a full disk, a dropped connection) is STORAGE_ERROR,\n // never a replay.\n const mapped = toCommerceError(\n error,\n 'STORAGE_ERROR',\n 'Payment attempt could not be recorded',\n );\n await hold?.finalize('release');\n await safeEmit(\n buildEvent({\n type: 'payment.rejected',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n paymentProvider: provider.name,\n status: 'error',\n data: { reason: mapped.code },\n }),\n );\n throw replayError(mapped, requirement);\n }\n\n await safeEmit(\n buildEvent({\n type: 'payment.verified',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n paymentProvider: provider.name,\n status: 'ok',\n }),\n );\n\n return {\n kind: 'admitted',\n settleArgs: {\n request,\n resource,\n provider,\n requirement,\n payment,\n verification,\n replayKey,\n hold,\n },\n };\n };\n}\n\nfunction pickProvider(\n providers: readonly PaymentProvider[],\n methods: readonly PaymentMethodName[],\n): PaymentProvider | undefined {\n for (const method of methods) {\n const found = providers.find((provider) => provider.name === method);\n if (found) return found;\n }\n return undefined;\n}\n","// What the pipeline's stages share: its options, and event and persistence writes that never fail a flow\nimport type { AuthorizationProvider, AuthorizationRecord } from '../../domain/authorization';\nimport type { CommerceEvent, EventSink } from '../../domain/event';\nimport type {\n PaymentProvider,\n PaymentRequirement,\n PaymentResult,\n PaymentSubmission,\n} from '../../domain/payment';\nimport type { CanonicalRequest } from '../../domain/request';\nimport type { CommerceResource, ResourceRegistry } from '../../domain/resource';\nimport { describeError } from '../../errors';\nimport type { BackendExecutor } from '../../interfaces/backend';\nimport type { Logger } from '../../interfaces/logger';\nimport type { Clock, IdGenerator } from '../../interfaces/runtime';\nimport type { ReceiptStore } from '../../interfaces/store';\n\nexport interface CreateExecutionPipelineOptions {\n readonly resources: ResourceRegistry;\n readonly paymentProviders: readonly PaymentProvider[];\n /** Defaults to none */\n readonly authorizationProviders?: readonly AuthorizationProvider[];\n readonly store: ReceiptStore;\n readonly backend: BackendExecutor;\n readonly events: EventSink;\n readonly logger: Logger;\n readonly clock: Clock;\n readonly ids: IdGenerator;\n}\n\n/**\n * A reservation held across settlement, plus the summary the receipt keeps.\n * `finalize` ends it.\n */\nexport interface AuthorizationHold {\n readonly record: AuthorizationRecord;\n finalize(action: 'consume' | 'release' | 'markUncertain'): Promise<void>;\n}\n\n/** A verified, reserved payment and everything its settlement needs */\nexport interface SettleArgs {\n readonly request: CanonicalRequest;\n readonly resource: CommerceResource;\n readonly provider: PaymentProvider;\n readonly requirement: PaymentRequirement;\n readonly payment: PaymentSubmission;\n readonly verification: PaymentResult;\n readonly replayKey: string;\n readonly hold: AuthorizationHold | undefined;\n}\n\nexport interface PipelineContext {\n readonly options: CreateExecutionPipelineOptions;\n /** Emits an event; a failing sink is logged, never thrown */\n readonly safeEmit: (event: CommerceEvent) => Promise<void>;\n /** Runs a store write; a failure is logged, never thrown */\n readonly safePersist: (\n op: () => Promise<void>,\n label: string,\n requestId: string,\n ) => Promise<void>;\n readonly buildEvent: (partial: Omit<CommerceEvent, 'id' | 'at'>) => CommerceEvent;\n}\n\nexport function createPipelineContext(options: CreateExecutionPipelineOptions): PipelineContext {\n async function safeEmit(event: CommerceEvent): Promise<void> {\n try {\n await options.events.emit(event);\n } catch (error) {\n options.logger.error(\n { err: describeError(error), eventType: event.type, requestId: event.requestId },\n 'Event sink failed; commerce flow continues',\n );\n }\n }\n\n async function safePersist(\n op: () => Promise<void>,\n label: string,\n requestId: string,\n ): Promise<void> {\n try {\n await op();\n } catch (error) {\n options.logger.error(\n { err: describeError(error), requestId },\n `Persistence failed: ${label}`,\n );\n }\n }\n\n function buildEvent(partial: Omit<CommerceEvent, 'id' | 'at'>): CommerceEvent {\n return { id: options.ids.next('evt'), at: options.clock.nowIso(), ...partial };\n }\n\n return { options, safeEmit, safePersist, buildEvent };\n}\n","// Settles a verified, reserved payment, or records that the backend failed before it could\nimport type { PaymentRequirement, PaymentResult } from '../../domain/payment';\nimport { CommerceError, isCommerceError } from '../../errors';\nimport { retryChallenge } from './challenge';\nimport type { PipelineContext, SettleArgs } from './context';\n\nexport interface Settlement {\n /** Settles and finalizes the authorization; a refusal or unknown outcome throws */\n readonly settle: (args: SettleArgs) => Promise<PaymentResult>;\n /** Records a backend failure before settlement and releases the authorization */\n readonly abandonSettlement: (args: SettleArgs, backendErrorCode: string) => Promise<void>;\n}\n\nexport function createSettlement(ctx: PipelineContext): Settlement {\n const { options, safeEmit, safePersist, buildEvent } = ctx;\n\n // Settle a verified, reserved payment and finalize its authorization.\n // Rejected or uncertain settlement throws before any response is delivered.\n async function settle(args: SettleArgs): Promise<PaymentResult> {\n const { request, resource, provider, requirement, payment, verification, replayKey, hold } =\n args;\n let settlement: PaymentResult;\n try {\n settlement = await provider.settle({\n requestId: request.requestId,\n resource,\n requirement,\n submission: payment,\n verification,\n });\n } catch (error) {\n // Confirmed non-submission leaves the authorization spendable. Release\n // it for retry and report the provider failure.\n const notSubmitted = notSubmittedReason(error);\n if (notSubmitted !== undefined) {\n await hold?.finalize('release');\n await safePersist(\n () =>\n options.store.updatePaymentAttempt({\n replayKey,\n status: 'rejected',\n rejectionReason: notSubmitted,\n }),\n 'updatePaymentAttempt(not-submitted)',\n request.requestId,\n );\n await safeEmit(\n buildEvent({\n type: 'payment.rejected',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n paymentProvider: provider.name,\n status: 'error',\n data: { reason: 'settlement-not-submitted', providerReason: notSubmitted },\n }),\n );\n throw new CommerceError(\n 'PAYMENT_PROVIDER_UNAVAILABLE',\n 'The payment provider could not settle the payment; nothing was charged',\n { requestId: request.requestId, resourceId: resource.id, cause: error },\n );\n }\n // A throw gives no settlement verdict. The facilitator may have\n // broadcast before losing its response, even without a transaction\n // hash. Keep the authorization uncertain so it cannot be spent again.\n const txHash = settlementTxHash(error);\n await hold?.finalize('markUncertain');\n await safePersist(\n () =>\n options.store.updatePaymentAttempt({\n replayKey,\n status: 'settlement-uncertain',\n ...(txHash !== undefined ? { externalReference: txHash } : {}),\n ...(error instanceof Error ? { rejectionReason: error.message } : {}),\n }),\n 'updatePaymentAttempt(settlement-uncertain)',\n request.requestId,\n );\n await safeEmit(\n buildEvent({\n type: 'payment.rejected',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n paymentProvider: provider.name,\n status: 'error',\n data: {\n reason: 'settlement-uncertain',\n ...(txHash !== undefined ? { transactionHash: txHash } : {}),\n },\n }),\n );\n // The replay key remains reserved, so report an uncertain, non-retryable\n // outcome. Expose only the transaction hash from the underlying error.\n throw new CommerceError('PAYMENT_SETTLEMENT_FAILED', 'Settlement could not be confirmed', {\n requestId: request.requestId,\n resourceId: resource.id,\n cause: error,\n details: {\n settlementUncertain: true,\n ...(txHash !== undefined ? { transactionHash: txHash } : {}),\n ...settlementParties(requirement, verification),\n },\n });\n }\n\n if (settlement.status !== 'settled') {\n await hold?.finalize('release');\n await safePersist(\n () =>\n options.store.updatePaymentAttempt({\n replayKey,\n status: 'rejected',\n ...(settlement.rejectionReason !== undefined\n ? { rejectionReason: settlement.rejectionReason }\n : {}),\n ...(settlement.externalReference !== undefined\n ? { externalReference: settlement.externalReference }\n : {}),\n }),\n 'updatePaymentAttempt(rejected)',\n request.requestId,\n );\n await safeEmit(\n buildEvent({\n type: 'payment.rejected',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n paymentProvider: provider.name,\n status: 'error',\n data: settlement.rejectionReason ? { reason: settlement.rejectionReason } : {},\n }),\n );\n // A returned rejection confirms no settlement. Both rails return 402.\n const rejectionDetails = retryChallenge(requirement, settlement.rejectionReason).details;\n throw new CommerceError(\n 'PAYMENT_SETTLEMENT_FAILED',\n settlement.rejectionReason ?? 'Settlement was rejected',\n {\n requestId: request.requestId,\n resourceId: resource.id,\n httpStatus: 402,\n details: {\n ...rejectionDetails,\n ...settlementParties(requirement, settlement, verification),\n },\n },\n );\n }\n\n await hold?.finalize('consume');\n await safePersist(\n () =>\n options.store.updatePaymentAttempt({\n replayKey,\n status: 'settled',\n ...(settlement.externalReference !== undefined\n ? { externalReference: settlement.externalReference }\n : {}),\n }),\n 'updatePaymentAttempt(settled)',\n request.requestId,\n );\n await safeEmit(\n buildEvent({\n type: 'payment.settled',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n paymentProvider: provider.name,\n status: 'ok',\n }),\n );\n\n return settlement;\n }\n\n // Record the pre-settlement backend failure and release the authorization\n // hold. Rails with reuse metadata can reserve the unspent replay key again,\n // as after any rejection.\n async function abandonSettlement(args: SettleArgs, backendErrorCode: string): Promise<void> {\n const { request, resource, provider, replayKey, hold } = args;\n await hold?.finalize('release');\n await safePersist(\n () =>\n options.store.updatePaymentAttempt({\n replayKey,\n status: 'rejected',\n rejectionReason: 'backend_failed',\n }),\n 'updatePaymentAttempt(backend-failed)',\n request.requestId,\n );\n await safeEmit(\n buildEvent({\n type: 'payment.rejected',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n paymentProvider: provider.name,\n status: 'error',\n data: { reason: 'backend-failed', backendErrorCode },\n }),\n );\n }\n\n return { settle, abandonSettlement };\n}\n\n// The reason a provider gave when it threw before submitting anything\nfunction notSubmittedReason(error: unknown): string | undefined {\n if (!isCommerceError(error) || error.details?.['settlementNotSubmitted'] !== true) {\n return undefined;\n }\n const reason = error.details['reason'];\n return typeof reason === 'string' ? reason : 'settlement_not_submitted';\n}\n\n// The broadcast transaction hash a provider attached to a settlement throw,\n// when it knows one\nfunction settlementTxHash(error: unknown): string | undefined {\n const hash = isCommerceError(error) ? error.details?.['transactionHash'] : undefined;\n return typeof hash === 'string' ? hash : undefined;\n}\n\n// Prefer the network and payer reported by settlement or verification, then\n// fall back to the requirement's network\nfunction settlementParties(\n requirement: PaymentRequirement,\n ...results: readonly PaymentResult[]\n): { network?: string; payer?: string } {\n const network = results.find((r) => r.network !== undefined)?.network ?? requirement.network;\n const payer = results.find((r) => r.payer !== undefined)?.payer;\n return {\n ...(network !== undefined ? { network } : {}),\n ...(payer !== undefined ? { payer } : {}),\n };\n}\n","/**\n * The single execution path every protocol adapter converges on. The order is a\n * security boundary; do not reorder:\n *\n * 1. resolve resource (RESOURCE_NOT_FOUND)\n * 2. strip reserved input fields, validate input and the backend request shape\n * (INPUT_INVALID, or BACKEND_ERROR for an illegal configured header)\n * 3. resolve price\n * 4. free: straight to the backend\n * 5. paid: pick provider and createRequirement, then return a challenge, or\n * select the offer the proof pays, verify it, and reserve authorization and\n * replay identities\n * 6. settle before calling the backend, or call the backend first and settle\n * only if it succeeds. Finalize authorization according to the outcome\n * (BACKEND_TIMEOUT / BACKEND_ERROR)\n * 7. persist receipt, emit events, return outcome\n */\n\nimport type { AuthorizationRecord } from '../../domain/authorization';\nimport type { PaymentResult } from '../../domain/payment';\nimport type { CommerceReceipt } from '../../domain/receipt';\nimport type { CanonicalRequest, ExecutionOutcome, ExecutionPipeline } from '../../domain/request';\nimport type { CommerceResource } from '../../domain/resource';\nimport { RESERVED_INPUT_FIELDS } from '../../domain/wire';\nimport { CommerceError, toCommerceError } from '../../errors';\nimport type { BackendResponse } from '../../interfaces/backend';\nimport { isRecord } from '../../is-record';\nimport { validateBackendRequestShape } from '../backend-request';\nimport { SETTLE_AFTER_BACKEND_METADATA_KEY } from '../settlement-order';\nimport { compileJsonSchema, type Validator } from '../validation';\nimport { createPaymentAdmission } from './admission';\nimport { createAuthorizeAndReserve } from './authorization';\nimport {\n type CreateExecutionPipelineOptions,\n createPipelineContext,\n type SettleArgs,\n} from './context';\nimport { createSettlement } from './settlement';\n\nexport type { CreateExecutionPipelineOptions } from './context';\n\nexport function createExecutionPipeline(\n options: CreateExecutionPipelineOptions,\n): ExecutionPipeline {\n const validators = new Map<string, Validator>();\n\n function getValidator(resource: CommerceResource): Validator {\n const cached = validators.get(resource.id);\n if (cached) return cached;\n const compiled = compileJsonSchema(resource.inputSchema);\n validators.set(resource.id, compiled);\n return compiled;\n }\n\n const ctx = createPipelineContext(options);\n const { safeEmit, safePersist, buildEvent } = ctx;\n const { settle, abandonSettlement } = createSettlement(ctx);\n const admitPayment = createPaymentAdmission(ctx, createAuthorizeAndReserve(ctx));\n\n async function execute(request: CanonicalRequest): Promise<ExecutionOutcome> {\n const pipelineStart = options.clock.monotonicMs();\n\n // 1. resolve resource\n const resource = options.resources.get(request.resourceId);\n // Same code and message as an unknown id: a caller on a protocol the\n // resource is not exposed via must not learn that it exists\n if (!resource?.exposedVia.includes(request.protocol)) {\n throw new CommerceError(\n 'RESOURCE_NOT_FOUND',\n `Resource \"${request.resourceId}\" was not found`,\n {\n requestId: request.requestId,\n resourceId: request.resourceId,\n },\n );\n }\n\n await safeEmit(\n buildEvent({\n type: 'resource.requested',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n }),\n );\n\n // 2. strip reserved gateway fields, then validate input\n const strippedInput = stripReservedFields(request.input);\n const validation = getValidator(resource)(strippedInput);\n if (!validation.valid) {\n throw new CommerceError(\n 'INPUT_INVALID',\n `Input for resource \"${resource.id}\" failed validation`,\n {\n requestId: request.requestId,\n resourceId: resource.id,\n details: { errors: validation.errors },\n },\n );\n }\n const validInput = validation.value;\n\n // Before pricing, so a request the backend cannot receive fails before\n // payment (see validateBackendRequestShape)\n validateBackendRequestShape(\n resource.handler,\n validInput,\n { requestId: request.requestId, resourceId: resource.id },\n request.backendHeaders,\n );\n\n // 3. resolve price\n if (resource.pricing.type === 'dynamic') {\n // Config validation rejects this at load; this is defense in depth\n throw new CommerceError(\n 'CONFIG_INVALID',\n `Resource \"${resource.id}\" uses unsupported dynamic pricing`,\n {\n requestId: request.requestId,\n resourceId: resource.id,\n },\n );\n }\n\n // Authorization gates settlement, so on a free resource nothing would read\n // the proof. Config refuses this at load; this is defense in depth.\n if (resource.pricing.type !== 'fixed' && (resource.authorization?.required.length ?? 0) > 0) {\n throw new CommerceError(\n 'CONFIG_INVALID',\n `Resource \"${resource.id}\" requires authorization but is not a paid resource`,\n {\n requestId: request.requestId,\n resourceId: resource.id,\n },\n );\n }\n\n let paymentResult: PaymentResult | undefined;\n let authorization: AuthorizationRecord | undefined;\n let deferredSettlement: SettleArgs | undefined;\n\n if (resource.pricing.type === 'fixed') {\n const admission = await admitPayment(request, resource, resource.pricing, validInput);\n if (admission.kind === 'payment-required') return admission;\n const { settleArgs } = admission;\n authorization = settleArgs.hold?.record;\n if (settleArgs.requirement.metadata?.[SETTLE_AFTER_BACKEND_METADATA_KEY] === true) {\n deferredSettlement = settleArgs;\n } else {\n paymentResult = await settle(settleArgs);\n }\n }\n\n // 6. call backend\n const backendStart = options.clock.monotonicMs();\n let backendResponse: BackendResponse;\n try {\n backendResponse = await options.backend.call(resource.handler, {\n requestId: request.requestId,\n resourceId: resource.id,\n input: validInput,\n ...(request.idempotencyKey !== undefined ? { idempotencyKey: request.idempotencyKey } : {}),\n ...(request.backendHeaders !== undefined ? { backendHeaders: request.backendHeaders } : {}),\n });\n } catch (error) {\n const commerceError = toCommerceError(error, 'BACKEND_ERROR', 'Backend call failed');\n await safeEmit(\n buildEvent({\n type: 'backend.failed',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n status: 'error',\n durationMs: Math.round(options.clock.monotonicMs() - backendStart),\n data: { code: commerceError.code },\n }),\n );\n\n if (deferredSettlement !== undefined) {\n await abandonSettlement(deferredSettlement, commerceError.code);\n throw commerceError;\n }\n\n if (paymentResult !== undefined) {\n // The payment settled and the backend then failed. Record an\n // undelivered receipt for the merchant and tell the buyer what they\n // paid, including the settlement reference.\n const failedReceipt: CommerceReceipt = {\n id: options.ids.next('receipt'),\n requestId: request.requestId,\n resourceId: resource.id,\n deliveredAt: options.clock.nowIso(),\n backendStatus: backendErrorStatus(commerceError),\n protocol: request.protocol,\n payment: paymentResult,\n ...(authorization !== undefined ? { authorization } : {}),\n metadata: { delivered: false, backendErrorCode: commerceError.code },\n };\n await safePersist(\n () => options.store.saveReceipt(failedReceipt),\n 'saveReceipt(backend-failed-after-settlement)',\n request.requestId,\n );\n\n throw new CommerceError(\n 'BACKEND_ERROR',\n 'Payment settled but the backend call failed; the payment was not refunded automatically',\n {\n requestId: request.requestId,\n resourceId: resource.id,\n cause: commerceError,\n details: {\n payment: {\n status: paymentResult.status,\n provider: paymentResult.provider,\n amount: paymentResult.amount,\n currency: paymentResult.currency,\n ...(paymentResult.network !== undefined ? { network: paymentResult.network } : {}),\n ...(paymentResult.externalReference !== undefined\n ? { externalReference: paymentResult.externalReference }\n : {}),\n ...(paymentResult.payer !== undefined ? { payer: paymentResult.payer } : {}),\n ...(typeof paymentResult.metadata?.['amountBaseUnits'] === 'string'\n ? { amountBaseUnits: paymentResult.metadata['amountBaseUnits'] }\n : {}),\n ...(typeof paymentResult.metadata?.['receipt'] === 'string'\n ? { receipt: paymentResult.metadata['receipt'] }\n : {}),\n },\n },\n },\n );\n }\n\n throw commerceError;\n }\n\n await safeEmit(\n buildEvent({\n type: 'backend.called',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n status: 'ok',\n durationMs: backendResponse.durationMs,\n data: { status: backendResponse.status },\n }),\n );\n\n // Hold the backend response until settlement succeeds. A refusal or\n // uncertain outcome throws before delivery.\n if (deferredSettlement !== undefined) {\n paymentResult = await settle(deferredSettlement);\n }\n\n // 7. persist receipt, emit final event, return outcome\n const receipt: CommerceReceipt = {\n id: options.ids.next('receipt'),\n requestId: request.requestId,\n resourceId: resource.id,\n deliveredAt: options.clock.nowIso(),\n backendStatus: backendResponse.status,\n durationMs: backendResponse.durationMs,\n protocol: request.protocol,\n ...(paymentResult !== undefined ? { payment: paymentResult } : {}),\n ...(authorization !== undefined ? { authorization } : {}),\n };\n\n await safePersist(() => options.store.saveReceipt(receipt), 'saveReceipt', request.requestId);\n\n const totalDurationMs = Math.round(options.clock.monotonicMs() - pipelineStart);\n\n await safeEmit(\n buildEvent({\n type: 'resource.delivered',\n requestId: request.requestId,\n resourceId: resource.id,\n adapter: request.protocol,\n status: 'ok',\n durationMs: totalDurationMs,\n }),\n );\n\n return {\n kind: 'delivered',\n requestId: request.requestId,\n resourceId: resource.id,\n backendStatus: backendResponse.status,\n body: backendResponse.body,\n headers: backendResponse.headers,\n ...(paymentResult !== undefined ? { payment: paymentResult } : {}),\n receipt,\n durationMs: totalDurationMs,\n };\n }\n\n return { execute };\n}\n\n// The status the backend returned, which backend-http.ts puts on\n// `details.status` for a non-2xx or redirect response. 0 means no status is\n// known, as after a timeout, a transport failure or an unreadable or oversized\n// body.\nfunction backendErrorStatus(error: CommerceError): number {\n const status = error.details?.['status'];\n return typeof status === 'number' ? status : 0;\n}\n\nconst RESERVED_INPUT_KEYS: readonly string[] = [...RESERVED_INPUT_FIELDS, '__proto__'];\n\nfunction stripReservedFields(input: unknown): unknown {\n if (!isRecord(input)) return input;\n // Object.hasOwn, not `in`, which also matches inherited names\n if (!RESERVED_INPUT_KEYS.some((key) => Object.hasOwn(input, key))) return input;\n const rest: Record<string, unknown> = {};\n for (const key of Object.keys(input)) {\n // \"__proto__\" is dropped too: assigning it would call the inherited setter\n // and replace `rest`'s prototype instead of creating a data property.\n // validation.ts's own-property lookups are the primary control.\n if (!RESERVED_INPUT_KEYS.includes(key)) rest[key] = input[key];\n }\n return rest;\n}\n","// In-memory implementation of the frozen `ResourceRegistry` interface\nimport type { ProtocolName } from '../domain/common';\nimport type { CommerceResource, ResourceRegistry } from '../domain/resource';\nimport { CommerceError } from '../errors';\n\nclass ResourceRegistryImpl implements ResourceRegistry {\n private readonly byId = new Map<string, CommerceResource>();\n private readonly ordered: readonly CommerceResource[];\n\n constructor(resources: readonly CommerceResource[]) {\n for (const resource of resources) {\n if (this.byId.has(resource.id)) {\n throw new CommerceError('CONFIG_INVALID', `Duplicate resource id \"${resource.id}\"`, {\n details: { resourceId: resource.id },\n });\n }\n this.byId.set(resource.id, resource);\n }\n this.ordered = [...resources];\n }\n\n get(id: string): CommerceResource | undefined {\n return this.byId.get(id);\n }\n\n list(): readonly CommerceResource[] {\n return this.ordered;\n }\n\n listExposedVia(protocol: ProtocolName): readonly CommerceResource[] {\n return this.ordered.filter((resource) => resource.exposedVia.includes(protocol));\n }\n\n has(id: string): boolean {\n return this.byId.has(id);\n }\n}\n\n/** Build a `ResourceRegistry` from a validated list of canonical resources */\nexport function createResourceRegistry(resources: readonly CommerceResource[]): ResourceRegistry {\n return new ResourceRegistryImpl(resources);\n}\n","/**\n * `EventSink` that persists every event to the receipt store. A store failure\n * is logged, never thrown to the caller.\n */\nimport type { CommerceEvent, EventSink } from '../domain/event';\nimport { describeError } from '../errors';\nimport type { Logger } from '../interfaces/logger';\nimport type { ReceiptStore } from '../interfaces/store';\n\nexport interface CreateStoreEventSinkOptions {\n readonly store: ReceiptStore;\n readonly logger: Logger;\n}\n\nexport function createStoreEventSink(options: CreateStoreEventSinkOptions): EventSink {\n return {\n async emit(event: CommerceEvent): Promise<void> {\n try {\n await options.store.appendEvent(event);\n } catch (error) {\n options.logger.error(\n { err: describeError(error), eventType: event.type, requestId: event.requestId },\n 'Failed to persist commerce event',\n );\n }\n },\n };\n}\n","/**\n * ACP protocol constants shared by the config layer and the adapter.\n *\n * Kept dependency-free: `src/config` reads the operation set at load time, so\n * anything imported here would become a config-load dependency too.\n */\n\n/**\n * The ACP stable snapshot this adapter implements, and the only value accepted\n * in the `API-Version` request header. Both name the same released snapshot;\n * they are separate constants because ACP versions the wire contract and the\n * header independently, and a future snapshot may accept more than one.\n *\n * Changing either means vendoring a new schema directory beside\n * `spec/2026-04-17/` - never editing the vendored one in place.\n */\nexport const ACP_SPEC_VERSION = '2026-04-17';\nexport const ACP_API_VERSION = '2026-04-17';\n\n/** Discovery path fixed by the ACP specification, never a configurable mount */\nexport const ACP_WELL_KNOWN_PATH = '/.well-known/acp.json';\n\n/**\n * The stable checkout operations, by ACP operation id. All five are required\n * when ACP is enabled: a partially configured checkout lifecycle would be\n * advertised as a whole service the seller cannot actually serve.\n */\nexport const ACP_CHECKOUT_OPERATIONS = [\n 'createCheckoutSession',\n 'updateCheckoutSession',\n 'getCheckoutSession',\n 'completeCheckoutSession',\n 'cancelCheckoutSession',\n] as const;\n\nexport type AcpCheckoutOperation = (typeof ACP_CHECKOUT_OPERATIONS)[number];\n\n/**\n * Top-level canonical-input properties each operation always supplies.\n *\n * `path` carries `{ checkout_session_id }`, `body` the ACP request document.\n */\nexport const ACP_OPERATION_INPUT_KEYS: Readonly<\n Record<AcpCheckoutOperation, readonly ('path' | 'body')[]>\n> = {\n createCheckoutSession: ['body'],\n updateCheckoutSession: ['path', 'body'],\n getCheckoutSession: ['path'],\n completeCheckoutSession: ['path', 'body'],\n cancelCheckoutSession: ['path'],\n};\n\n/**\n * Canonical-input properties an operation supplies only when the caller sends\n * them. The pinned schema lets a cancel omit its body, so a bare cancel has no\n * `body`, but one carrying `intent_trace` passes it on.\n */\nexport const ACP_OPERATION_OPTIONAL_INPUT_KEYS: Readonly<\n Partial<Record<AcpCheckoutOperation, readonly 'body'[]>>\n> = {\n cancelCheckoutSession: ['body'],\n};\n\n/** The key inside `path` that carries the checkout session id from the route */\nexport const ACP_SESSION_ID_INPUT_KEY = 'checkout_session_id';\n\n/** Media type for every ACP request and response body */\nexport const ACP_JSON_MEDIA_TYPE = 'application/json';\n\n/**\n * Protocol headers, lowercased as Node delivers them.\n *\n * `API-Version` is mandatory on checkout requests and is never defaulted:\n * answering an unversioned request as if it named the pinned snapshot would be\n * guessing on the caller's behalf about a contract that changes.\n */\nexport const ACP_API_VERSION_HEADER = 'api-version';\nexport const ACP_REQUEST_ID_HEADER = 'request-id';\nexport const ACP_IDEMPOTENCY_KEY_HEADER = 'idempotency-key';\nexport const ACP_IDEMPOTENT_REPLAYED_HEADER = 'idempotent-replayed';\n\n/**\n * Seconds a client is told to wait before retrying a key whose first request is\n * still running. Short: the original is a live HTTP call, not a queue.\n */\nexport const ACP_IN_FLIGHT_RETRY_AFTER_SECONDS = 1;\n\n/**\n * Longest `Request-Id` echoed back. The value is the caller's, so it is\n * bounded and filtered before it is ever written into a response header.\n */\nexport const ACP_MAX_REQUEST_ID_LENGTH = 128;\n\n/** Caller headers forwarded to the merchant; the bearer token stays at the gateway */\nexport const ACP_FORWARDED_HEADERS = [\n 'accept-language',\n 'user-agent',\n ACP_REQUEST_ID_HEADER,\n ACP_API_VERSION_HEADER,\n 'signature',\n 'timestamp',\n] as const;\n\n/** Maximum forwarded header value length; longer values are dropped */\nexport const ACP_MAX_FORWARDED_HEADER_LENGTH = 2048;\n\n/** Fallback and maximum `Retry-After` seconds for merchant 429 or 503 */\nexport const ACP_MERCHANT_RETRY_AFTER_DEFAULT_SECONDS = 5;\nexport const ACP_MERCHANT_RETRY_AFTER_MAX_SECONDS = 300;\n"]}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { AP2_CHECKOUT_MANDATE_VCT, AP2_SIGNING_ALGORITHM, AP2_DIGEST_ALGORITHM, AP2_CHECKOUT_PROFILE, AP2_SPEC_VERSION } from './chunk-FHCFR2GS.js';
|
|
2
|
+
|
|
3
|
+
// src/authorization/ap2/descriptor.ts
|
|
4
|
+
var AP2_CAPABILITIES = [
|
|
5
|
+
"direct-mode",
|
|
6
|
+
"trusted-agent-provider",
|
|
7
|
+
AP2_CHECKOUT_MANDATE_VCT,
|
|
8
|
+
"sd-jwt-presentation",
|
|
9
|
+
AP2_SIGNING_ALGORITHM,
|
|
10
|
+
AP2_DIGEST_ALGORITHM,
|
|
11
|
+
"static-inline-trust",
|
|
12
|
+
"merchant-checkout-jwt-binding",
|
|
13
|
+
AP2_CHECKOUT_PROFILE,
|
|
14
|
+
"purchase-binding",
|
|
15
|
+
"replay-defence"
|
|
16
|
+
];
|
|
17
|
+
var AP2_UNSUPPORTED = [
|
|
18
|
+
// Mandate kinds. Open mandates are refused: see AP2_CHECKOUT_MANDATE_VCT
|
|
19
|
+
"autonomous mode",
|
|
20
|
+
"open checkout mandates (mandate.checkout.open.1)",
|
|
21
|
+
"payment mandates (mandate.payment.1)",
|
|
22
|
+
"spending constraint evaluation",
|
|
23
|
+
"cnf-bound agent keys",
|
|
24
|
+
// Delegation models other than a trusted agent provider
|
|
25
|
+
"user credential delegation (OpenID4VP)",
|
|
26
|
+
"delegation chains and key-binding JWTs",
|
|
27
|
+
// Key handling. Every key is written into config by an operator
|
|
28
|
+
"JWKS and any key discovery by URL (jku, x5u)",
|
|
29
|
+
"issuer metadata fetching",
|
|
30
|
+
"key rotation without a config change",
|
|
31
|
+
// Algorithms
|
|
32
|
+
"signature algorithms other than ES256",
|
|
33
|
+
"digest algorithms other than sha-256",
|
|
34
|
+
// Roles this gateway does not play
|
|
35
|
+
"mandate issuance",
|
|
36
|
+
"checkout receipts",
|
|
37
|
+
"AP2 over the ACP checkout adapter"
|
|
38
|
+
];
|
|
39
|
+
function buildAp2Descriptor(implementationVersion) {
|
|
40
|
+
return {
|
|
41
|
+
name: "ap2",
|
|
42
|
+
kind: "authorization",
|
|
43
|
+
implementationVersion,
|
|
44
|
+
supportedSpec: `ap2/v${AP2_SPEC_VERSION} mode=direct`,
|
|
45
|
+
capabilities: AP2_CAPABILITIES,
|
|
46
|
+
status: "experimental",
|
|
47
|
+
unsupported: AP2_UNSUPPORTED
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export { AP2_CAPABILITIES, AP2_UNSUPPORTED, buildAp2Descriptor };
|
|
52
|
+
//# sourceMappingURL=chunk-3EQBCFZY.js.map
|
|
53
|
+
//# sourceMappingURL=chunk-3EQBCFZY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/authorization/ap2/descriptor.ts"],"names":[],"mappings":";;;AAgBO,IAAM,gBAAA,GAAsC;AAAA,EACjD,aAAA;AAAA,EACA,wBAAA;AAAA,EACA,wBAAA;AAAA,EACA,qBAAA;AAAA,EACA,qBAAA;AAAA,EACA,oBAAA;AAAA,EACA,qBAAA;AAAA,EACA,+BAAA;AAAA,EACA,oBAAA;AAAA,EACA,kBAAA;AAAA,EACA;AACF;AAOO,IAAM,eAAA,GAAqC;AAAA;AAAA,EAEhD,iBAAA;AAAA,EACA,kDAAA;AAAA,EACA,sCAAA;AAAA,EACA,gCAAA;AAAA,EACA,sBAAA;AAAA;AAAA,EAEA,wCAAA;AAAA,EACA,wCAAA;AAAA;AAAA,EAEA,8CAAA;AAAA,EACA,0BAAA;AAAA,EACA,sCAAA;AAAA;AAAA,EAEA,uCAAA;AAAA,EACA,sCAAA;AAAA;AAAA,EAEA,kBAAA;AAAA,EACA,mBAAA;AAAA,EACA;AACF;AAEO,SAAS,mBAAmB,qBAAA,EAAkD;AACnF,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,KAAA;AAAA,IACN,IAAA,EAAM,eAAA;AAAA,IACN,qBAAA;AAAA,IACA,aAAA,EAAe,QAAQ,gBAAgB,CAAA,YAAA,CAAA;AAAA,IACvC,YAAA,EAAc,gBAAA;AAAA,IACd,MAAA,EAAQ,cAAA;AAAA,IACR,WAAA,EAAa;AAAA,GACf;AACF","file":"chunk-3EQBCFZY.js","sourcesContent":["/**\n * Adapter self-description.\n *\n * Imports nothing but core types and the pins, so `doctor` can report AP2\n * without pulling `jose` or `@sd-jwt/core` into the CLI bundle.\n */\nimport type { AdapterDescriptor } from '../../core';\nimport {\n AP2_CHECKOUT_MANDATE_VCT,\n AP2_CHECKOUT_PROFILE,\n AP2_DIGEST_ALGORITHM,\n AP2_SIGNING_ALGORITHM,\n AP2_SPEC_VERSION,\n} from './constants';\n\n/** What this provider actually verifies */\nexport const AP2_CAPABILITIES: readonly string[] = [\n 'direct-mode',\n 'trusted-agent-provider',\n AP2_CHECKOUT_MANDATE_VCT,\n 'sd-jwt-presentation',\n AP2_SIGNING_ALGORITHM,\n AP2_DIGEST_ALGORITHM,\n 'static-inline-trust',\n 'merchant-checkout-jwt-binding',\n AP2_CHECKOUT_PROFILE,\n 'purchase-binding',\n 'replay-defence',\n];\n\n/**\n * Major AP2 features this provider does not support, published in its\n * descriptor and printed by `doctor`, so no client assumes full protocol\n * support\n */\nexport const AP2_UNSUPPORTED: readonly string[] = [\n // Mandate kinds. Open mandates are refused: see AP2_CHECKOUT_MANDATE_VCT\n 'autonomous mode',\n 'open checkout mandates (mandate.checkout.open.1)',\n 'payment mandates (mandate.payment.1)',\n 'spending constraint evaluation',\n 'cnf-bound agent keys',\n // Delegation models other than a trusted agent provider\n 'user credential delegation (OpenID4VP)',\n 'delegation chains and key-binding JWTs',\n // Key handling. Every key is written into config by an operator\n 'JWKS and any key discovery by URL (jku, x5u)',\n 'issuer metadata fetching',\n 'key rotation without a config change',\n // Algorithms\n 'signature algorithms other than ES256',\n 'digest algorithms other than sha-256',\n // Roles this gateway does not play\n 'mandate issuance',\n 'checkout receipts',\n 'AP2 over the ACP checkout adapter',\n];\n\nexport function buildAp2Descriptor(implementationVersion: string): AdapterDescriptor {\n return {\n name: 'ap2',\n kind: 'authorization',\n implementationVersion,\n supportedSpec: `ap2/v${AP2_SPEC_VERSION} mode=direct`,\n capabilities: AP2_CAPABILITIES,\n status: 'experimental',\n unsupported: AP2_UNSUPPORTED,\n };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/core/is-record.ts"],"names":[],"mappings":";AACO,SAAS,SAAS,KAAA,EAAkD;AACzE,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5E","file":"chunk-3M6U7ILB.js","sourcesContent":["/** A non-null, non-array object. The prototype is not checked */\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n"]}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { CommerceError } from './chunk-QQ3WY5L3.js';
|
|
2
|
+
import { existsSync, accessSync, constants, closeSync, openSync, mkdirSync, chmodSync } from 'fs';
|
|
3
|
+
import { dirname } from 'path';
|
|
4
|
+
import Database from 'better-sqlite3';
|
|
5
|
+
|
|
6
|
+
function openSqliteDatabase(options) {
|
|
7
|
+
const { path, label, logger } = options;
|
|
8
|
+
const isFileBacked = path !== ":memory:";
|
|
9
|
+
if (isFileBacked) {
|
|
10
|
+
try {
|
|
11
|
+
createDirectory(dirname(path));
|
|
12
|
+
} catch (cause) {
|
|
13
|
+
throw new CommerceError(
|
|
14
|
+
"STORAGE_ERROR",
|
|
15
|
+
`${label} directory "${dirname(path)}" cannot be created: ${cause instanceof Error ? cause.message : String(cause)}`,
|
|
16
|
+
{ details: { path }, cause }
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (isFileBacked && existsSync(path)) {
|
|
21
|
+
try {
|
|
22
|
+
accessSync(path, constants.W_OK);
|
|
23
|
+
} catch {
|
|
24
|
+
throw new CommerceError(
|
|
25
|
+
"STORAGE_ERROR",
|
|
26
|
+
`${label} "${path}" exists but is not writable by this process (uid ${typeof process.getuid === "function" ? process.getuid() : "unknown"}). If this is a container that recently changed user, an existing volume may still be owned by the previous one - recreate it (docker compose down -v) or fix its ownership.`,
|
|
27
|
+
{ details: { path } }
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (isFileBacked) {
|
|
32
|
+
try {
|
|
33
|
+
closeSync(openSync(path, "a", 384));
|
|
34
|
+
} catch {
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const db = new Database(path);
|
|
38
|
+
db.pragma("journal_mode = WAL");
|
|
39
|
+
db.pragma("foreign_keys = ON");
|
|
40
|
+
if (isFileBacked) restrictDatabasePermissions(path, label, logger);
|
|
41
|
+
return db;
|
|
42
|
+
}
|
|
43
|
+
function createDirectory(dir) {
|
|
44
|
+
if (existsSync(dir)) return;
|
|
45
|
+
const parent = dirname(dir);
|
|
46
|
+
if (parent !== dir) createDirectory(parent);
|
|
47
|
+
try {
|
|
48
|
+
mkdirSync(dir, { mode: 448 });
|
|
49
|
+
} catch (error) {
|
|
50
|
+
if (error.code !== "EEXIST") throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function restrictDatabasePermissions(path, label, logger) {
|
|
54
|
+
for (const file of [path, `${path}-wal`, `${path}-shm`]) {
|
|
55
|
+
try {
|
|
56
|
+
chmodSync(file, 384);
|
|
57
|
+
} catch (error) {
|
|
58
|
+
const code = error.code;
|
|
59
|
+
if (code === "ENOENT") continue;
|
|
60
|
+
logger.warn(
|
|
61
|
+
{ file, label, error: code ?? "unknown" },
|
|
62
|
+
"could not restrict database permissions to owner-only"
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export { openSqliteDatabase };
|
|
69
|
+
//# sourceMappingURL=chunk-3MGAJ5FX.js.map
|
|
70
|
+
//# sourceMappingURL=chunk-3MGAJ5FX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/storage/sqlite.ts"],"names":["fsConstants"],"mappings":"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","file":"chunk-3MGAJ5FX.js","sourcesContent":["/**\n * Opens a SQLite file with owner-only permissions. Every store that keeps a\n * SQLite file opens it here, so the hardening below exists once: the file is\n * pre-created at 0600, the WAL sidecars are narrowed once WAL creates them, and\n * an existing but unwritable file fails at startup.\n *\n * Callers own their schema; this function migrates nothing.\n */\nimport {\n accessSync,\n chmodSync,\n closeSync,\n existsSync,\n constants as fsConstants,\n mkdirSync,\n openSync,\n} from 'node:fs';\nimport { dirname } from 'node:path';\nimport Database from 'better-sqlite3';\nimport { CommerceError, type Logger } from '../core';\n\nexport interface OpenSqliteOptions {\n /** File path, or ':memory:' for tests. Parent directory is created if missing */\n readonly path: string;\n /** Names the database in operator-facing errors, e.g. \"Receipt database\" */\n readonly label: string;\n readonly logger: Logger;\n}\n\nexport function openSqliteDatabase(options: OpenSqliteOptions): Database.Database {\n const { path, label, logger } = options;\n const isFileBacked = path !== ':memory:';\n\n if (isFileBacked) {\n try {\n createDirectory(dirname(path));\n } catch (cause) {\n throw new CommerceError(\n 'STORAGE_ERROR',\n `${label} directory \"${dirname(path)}\" cannot be created: ${cause instanceof Error ? cause.message : String(cause)}`,\n { details: { path }, cause },\n );\n }\n }\n\n // Check write access at startup. SQLite can open a read-only database and\n // report the problem only when the first write is attempted.\n if (isFileBacked && existsSync(path)) {\n try {\n accessSync(path, fsConstants.W_OK);\n } catch {\n throw new CommerceError(\n 'STORAGE_ERROR',\n `${label} \"${path}\" exists but is not writable by this process (uid ${typeof process.getuid === 'function' ? process.getuid() : 'unknown'}). If this is a container that recently changed user, an existing volume may still be owned by the previous one - recreate it (docker compose down -v) or fix its ownership.`,\n { details: { path } },\n );\n }\n }\n\n // Create the file at 0600 before SQLite creates it at 0644 (less the umask).\n // A chmod afterwards is too late: a local user who opens the file in between\n // keeps a readable descriptor across the chmod. SQLite copies the main file's\n // mode onto the -wal/-shm sidecars, so this covers all three. `mode` applies\n // on creation only; an existing file is left to the chmod below.\n if (isFileBacked) {\n try {\n closeSync(openSync(path, 'a', 0o600));\n } catch {\n // Silent on purpose: `new Database` reports the same cause with a better\n // message, or the failure is harmless and the chmod below covers it\n }\n }\n\n const db = new Database(path);\n db.pragma('journal_mode = WAL');\n db.pragma('foreign_keys = ON');\n if (isFileBacked) restrictDatabasePermissions(path, label, logger);\n return db;\n}\n\n// Create missing directory levels at 0700, preserving existing modes. Explicit\n// recursion avoids the recursive mkdir hang observed on Node 24.8.0 when /proc\n// returns ENOENT for a directory it cannot create.\nfunction createDirectory(dir: string): void {\n if (existsSync(dir)) return;\n const parent = dirname(dir);\n if (parent !== dir) createDirectory(parent);\n try {\n mkdirSync(dir, { mode: 0o700 });\n } catch (error) {\n // Created by someone else in the meantime\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;\n }\n}\n\n/**\n * Narrows the database and its WAL sidecars to owner-only. The receipt ledger\n * holds no key material, but it does hold payer and payee addresses, amounts,\n * settlement hashes, replay keys and the commerce event log.\n *\n * Runs after `journal_mode = WAL`, which creates the sidecars, and also\n * tightens a database that already existed with a looser mode. A failure only\n * warns: a filesystem without POSIX modes must not stop the gateway starting.\n */\nfunction restrictDatabasePermissions(path: string, label: string, logger: Logger): void {\n for (const file of [path, `${path}-wal`, `${path}-shm`]) {\n try {\n chmodSync(file, 0o600);\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === 'ENOENT') continue;\n logger.warn(\n { file, label, error: code ?? 'unknown' },\n 'could not restrict database permissions to owner-only',\n );\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { isRecord } from './chunk-3M6U7ILB.js';
|
|
2
|
+
import { createHash } from 'crypto';
|
|
3
|
+
|
|
4
|
+
// src/payments/mpp/problems.ts
|
|
5
|
+
var MPP_PROBLEM_BASE_URI = "https://paymentauth.org/problems/";
|
|
6
|
+
var TITLES = {
|
|
7
|
+
"payment-required": "Payment Required",
|
|
8
|
+
"malformed-credential": "Malformed Credential",
|
|
9
|
+
"invalid-challenge": "Invalid Challenge",
|
|
10
|
+
"payment-expired": "Payment Expired",
|
|
11
|
+
"verification-failed": "Verification Failed",
|
|
12
|
+
"internal-payment-error": "Internal Payment Error"
|
|
13
|
+
};
|
|
14
|
+
var REASON_TYPES = /* @__PURE__ */ new Map([
|
|
15
|
+
["malformed_credential", "malformed-credential"],
|
|
16
|
+
["invalid_payload", "malformed-credential"],
|
|
17
|
+
["invalid_challenge", "invalid-challenge"],
|
|
18
|
+
["challenge_not_issued", "invalid-challenge"],
|
|
19
|
+
["wrong_realm", "invalid-challenge"],
|
|
20
|
+
["wrong_resource", "invalid-challenge"],
|
|
21
|
+
["challenge_already_used", "invalid-challenge"],
|
|
22
|
+
["challenge_expired", "payment-expired"],
|
|
23
|
+
["authorization_expired", "payment-expired"]
|
|
24
|
+
]);
|
|
25
|
+
function mppProblem(code, httpStatus, reason) {
|
|
26
|
+
const problem = problemType(code, httpStatus, reason);
|
|
27
|
+
return { type: `${MPP_PROBLEM_BASE_URI}${problem}`, title: TITLES[problem] };
|
|
28
|
+
}
|
|
29
|
+
var REASON_DETAILS = /* @__PURE__ */ new Map([
|
|
30
|
+
["wrong_provider", "The challenge was issued for another payment method."],
|
|
31
|
+
["missing_challenge", "No challenge is available for this request."],
|
|
32
|
+
["malformed_credential", "The credential could not be decoded."],
|
|
33
|
+
["invalid_payload", "The credential payload does not match the expected format."],
|
|
34
|
+
["invalid_challenge", "The credential does not answer a valid challenge."],
|
|
35
|
+
["challenge_not_issued", "The challenge was not issued by this server or was altered."],
|
|
36
|
+
["challenge_already_used", "The challenge has already been used for a payment."],
|
|
37
|
+
["challenge_expired", "The challenge has expired."],
|
|
38
|
+
["wrong_realm", "The challenge was issued for another realm."],
|
|
39
|
+
["wrong_resource", "The challenge was issued for another resource."],
|
|
40
|
+
[
|
|
41
|
+
"unsupported_method",
|
|
42
|
+
"The challenge names a payment method or intent this server does not accept."
|
|
43
|
+
],
|
|
44
|
+
["unsupported_credential", "The credential type is not accepted for this challenge."],
|
|
45
|
+
["body_digest_mismatch", "The request body differs from the one the challenge was issued for."],
|
|
46
|
+
["wrong_amount", "The payment amount does not match the challenge."],
|
|
47
|
+
["wrong_recipient", "The payment recipient does not match the challenge."],
|
|
48
|
+
["wrong_network", "The payment uses a different network from the challenge."],
|
|
49
|
+
["wrong_asset", "The payment uses a different asset from the challenge."],
|
|
50
|
+
["wrong_terms", "The payment terms do not match the challenge."],
|
|
51
|
+
["wrong_nonce", "The authorization nonce is not derived from the challenge."],
|
|
52
|
+
["invalid_signature", "The authorization signature does not match the payer."],
|
|
53
|
+
["source_mismatch", "The credential source is not the account that signed the authorization."],
|
|
54
|
+
["authorization_not_yet_valid", "The authorization is not valid yet."],
|
|
55
|
+
["authorization_expired", "The authorization has expired."],
|
|
56
|
+
["authorization_invalid", "The authorization failed verification."],
|
|
57
|
+
["settlement_rejected", "The payment was refused before settlement."],
|
|
58
|
+
["settlement_mismatch", "The payment could not be matched to its settlement."],
|
|
59
|
+
["invalid_exact_evm_insufficient_balance", "The payer balance is too low for this payment."],
|
|
60
|
+
[
|
|
61
|
+
"invalid_exact_evm_transaction_simulation_failed",
|
|
62
|
+
"The transfer failed in simulation, so it was not submitted."
|
|
63
|
+
]
|
|
64
|
+
]);
|
|
65
|
+
function mppProblemDetail(reason, fallback) {
|
|
66
|
+
if (reason === void 0) return fallback;
|
|
67
|
+
return REASON_DETAILS.get(reason) ?? `The payment was refused: ${reason}.`;
|
|
68
|
+
}
|
|
69
|
+
function problemType(code, httpStatus, reason) {
|
|
70
|
+
if (code === "PAYMENT_REQUIRED") return "payment-required";
|
|
71
|
+
if (httpStatus >= 500) return "internal-payment-error";
|
|
72
|
+
if (code === "PAYMENT_REPLAYED") return "invalid-challenge";
|
|
73
|
+
return (reason !== void 0 ? REASON_TYPES.get(reason) : void 0) ?? "verification-failed";
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/payments/mpp/transport.ts
|
|
77
|
+
var CONTENT_DIGEST_METADATA_KEY = "contentDigest";
|
|
78
|
+
function contentDigest(body) {
|
|
79
|
+
return `sha-256=:${createHash("sha256").update(body).digest("base64")}:`;
|
|
80
|
+
}
|
|
81
|
+
var MPP_MCP_CREDENTIAL_META_KEY = "org.paymentauth/credential";
|
|
82
|
+
var MPP_MCP_PAYMENT_REQUIRED_META_KEY = "org.paymentauth/payment-required";
|
|
83
|
+
var MPP_MCP_RECEIPT_META_KEY = "org.paymentauth/receipt";
|
|
84
|
+
function mcpPaymentRequired(envelope, refusal) {
|
|
85
|
+
const challenges = isRecord(envelope) ? envelope["challenges"] : void 0;
|
|
86
|
+
if (!Array.isArray(challenges) || challenges.length === 0) return void 0;
|
|
87
|
+
const reason = typeof refusal?.reason === "string" ? refusal.reason : void 0;
|
|
88
|
+
return {
|
|
89
|
+
httpStatus: 402,
|
|
90
|
+
challenges,
|
|
91
|
+
...refusal !== void 0 ? {
|
|
92
|
+
problem: {
|
|
93
|
+
...mppProblem(refusal.code, 402, reason),
|
|
94
|
+
status: 402,
|
|
95
|
+
detail: mppProblemDetail(reason, refusal.detail),
|
|
96
|
+
...reason !== void 0 ? { reason } : {}
|
|
97
|
+
}
|
|
98
|
+
} : {}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
function receiptObject(serialized) {
|
|
102
|
+
if (typeof serialized !== "string") return void 0;
|
|
103
|
+
try {
|
|
104
|
+
const decoded = JSON.parse(Buffer.from(serialized, "base64url").toString("utf8"));
|
|
105
|
+
return isRecord(decoded) ? decoded : void 0;
|
|
106
|
+
} catch {
|
|
107
|
+
return void 0;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export { CONTENT_DIGEST_METADATA_KEY, MPP_MCP_CREDENTIAL_META_KEY, MPP_MCP_PAYMENT_REQUIRED_META_KEY, MPP_MCP_RECEIPT_META_KEY, contentDigest, mcpPaymentRequired, mppProblem, mppProblemDetail, receiptObject };
|
|
112
|
+
//# sourceMappingURL=chunk-5K4XEAZV.js.map
|
|
113
|
+
//# sourceMappingURL=chunk-5K4XEAZV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/payments/mpp/problems.ts","../../src/payments/mpp/transport.ts"],"names":[],"mappings":"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","file":"chunk-5K4XEAZV.js","sourcesContent":["/**\n * Map MPP payment errors to the Problem Details types in\n * `draft-httpauth-payment-01`. This module has no optional peer imports, so\n * the main HTTP route can use it.\n */\n\nexport const MPP_PROBLEM_BASE_URI = 'https://paymentauth.org/problems/';\n\nexport type MppProblemType =\n | 'payment-required'\n | 'malformed-credential'\n | 'invalid-challenge'\n | 'payment-expired'\n | 'verification-failed'\n | 'internal-payment-error';\n\nconst TITLES: Readonly<Record<MppProblemType, string>> = {\n 'payment-required': 'Payment Required',\n 'malformed-credential': 'Malformed Credential',\n 'invalid-challenge': 'Invalid Challenge',\n 'payment-expired': 'Payment Expired',\n 'verification-failed': 'Verification Failed',\n 'internal-payment-error': 'Internal Payment Error',\n};\n\n// Map known MPP refusal reasons to problem types; other reasons use\n// `verification-failed`. A Map keeps facilitator text out of Object.prototype\nconst REASON_TYPES: ReadonlyMap<string, MppProblemType> = new Map([\n ['malformed_credential', 'malformed-credential'],\n ['invalid_payload', 'malformed-credential'],\n ['invalid_challenge', 'invalid-challenge'],\n ['challenge_not_issued', 'invalid-challenge'],\n ['wrong_realm', 'invalid-challenge'],\n ['wrong_resource', 'invalid-challenge'],\n ['challenge_already_used', 'invalid-challenge'],\n ['challenge_expired', 'payment-expired'],\n ['authorization_expired', 'payment-expired'],\n]);\n\n/** The Problem Details `type` URI and `title` for an MPP payment error */\nexport function mppProblem(\n code: string,\n httpStatus: number,\n reason?: string,\n): { readonly type: string; readonly title: string } {\n const problem = problemType(code, httpStatus, reason);\n return { type: `${MPP_PROBLEM_BASE_URI}${problem}`, title: TITLES[problem] };\n}\n\n// Descriptions for MPP reasons and two x402 facilitator refusals\nconst REASON_DETAILS: ReadonlyMap<string, string> = new Map([\n ['wrong_provider', 'The challenge was issued for another payment method.'],\n ['missing_challenge', 'No challenge is available for this request.'],\n ['malformed_credential', 'The credential could not be decoded.'],\n ['invalid_payload', 'The credential payload does not match the expected format.'],\n ['invalid_challenge', 'The credential does not answer a valid challenge.'],\n ['challenge_not_issued', 'The challenge was not issued by this server or was altered.'],\n ['challenge_already_used', 'The challenge has already been used for a payment.'],\n ['challenge_expired', 'The challenge has expired.'],\n ['wrong_realm', 'The challenge was issued for another realm.'],\n ['wrong_resource', 'The challenge was issued for another resource.'],\n [\n 'unsupported_method',\n 'The challenge names a payment method or intent this server does not accept.',\n ],\n ['unsupported_credential', 'The credential type is not accepted for this challenge.'],\n ['body_digest_mismatch', 'The request body differs from the one the challenge was issued for.'],\n ['wrong_amount', 'The payment amount does not match the challenge.'],\n ['wrong_recipient', 'The payment recipient does not match the challenge.'],\n ['wrong_network', 'The payment uses a different network from the challenge.'],\n ['wrong_asset', 'The payment uses a different asset from the challenge.'],\n ['wrong_terms', 'The payment terms do not match the challenge.'],\n ['wrong_nonce', 'The authorization nonce is not derived from the challenge.'],\n ['invalid_signature', 'The authorization signature does not match the payer.'],\n ['source_mismatch', 'The credential source is not the account that signed the authorization.'],\n ['authorization_not_yet_valid', 'The authorization is not valid yet.'],\n ['authorization_expired', 'The authorization has expired.'],\n ['authorization_invalid', 'The authorization failed verification.'],\n ['settlement_rejected', 'The payment was refused before settlement.'],\n ['settlement_mismatch', 'The payment could not be matched to its settlement.'],\n ['invalid_exact_evm_insufficient_balance', 'The payer balance is too low for this payment.'],\n [\n 'invalid_exact_evm_transaction_simulation_failed',\n 'The transfer failed in simulation, so it was not submitted.',\n ],\n]);\n\n/** Return a sentence for a known reason, or quote an unknown reason */\nexport function mppProblemDetail(reason: string | undefined, fallback: string): string {\n if (reason === undefined) return fallback;\n return REASON_DETAILS.get(reason) ?? `The payment was refused: ${reason}.`;\n}\n\nfunction problemType(code: string, httpStatus: number, reason?: string): MppProblemType {\n if (code === 'PAYMENT_REQUIRED') return 'payment-required';\n if (httpStatus >= 500) return 'internal-payment-error';\n // A replayed credential reuses its challenge because the replay key\n // includes the challenge-derived nonce\n if (code === 'PAYMENT_REPLAYED') return 'invalid-challenge';\n return (reason !== undefined ? REASON_TYPES.get(reason) : undefined) ?? 'verification-failed';\n}\n","/**\n * Build MPP MCP metadata accepted by the `mppx` client. This module has no\n * optional peer imports, so the `./mcp` subpath can use it.\n */\n\nimport { createHash } from 'node:crypto';\nimport { isRecord } from '../../core/is-record';\nimport { mppProblem, mppProblemDetail } from './problems';\n\n/**\n * `CanonicalRequest.metadata` key for the digest of an HTTP request body. The\n * MPP provider binds it into the challenge when present, so a credential\n * cannot pay for a different body.\n */\nexport const CONTENT_DIGEST_METADATA_KEY = 'contentDigest';\n\n/** RFC 9530 `sha-256` digest of a request body, the form of the MPP `digest` parameter */\nexport function contentDigest(body: Uint8Array): string {\n return `sha-256=:${createHash('sha256').update(body).digest('base64')}:`;\n}\n\n/** MCP `_meta` key of a tool call's credential object */\nexport const MPP_MCP_CREDENTIAL_META_KEY = 'org.paymentauth/credential';\n\n/** MCP `_meta` key of a tool result's challenges */\nexport const MPP_MCP_PAYMENT_REQUIRED_META_KEY = 'org.paymentauth/payment-required';\n\n/** MCP `_meta` key of a paid tool result's receipt object */\nexport const MPP_MCP_RECEIPT_META_KEY = 'org.paymentauth/receipt';\n\n/**\n * Build payment-required metadata from the provider's challenge objects.\n * Return undefined if the envelope has none. The draft uses JSON-RPC error\n * -32042; this gateway puts the data in a tool result's `_meta`, which\n * `mppx` also reads. A refusal adds its Problem Details, with the provider's\n * reason token in the `reason` member.\n */\nexport function mcpPaymentRequired(\n envelope: unknown,\n refusal?: { readonly code: string; readonly reason?: unknown; readonly detail: string },\n): Record<string, unknown> | undefined {\n const challenges = isRecord(envelope) ? envelope['challenges'] : undefined;\n if (!Array.isArray(challenges) || challenges.length === 0) return undefined;\n const reason = typeof refusal?.reason === 'string' ? refusal.reason : undefined;\n return {\n httpStatus: 402,\n challenges,\n ...(refusal !== undefined\n ? {\n problem: {\n ...mppProblem(refusal.code, 402, reason),\n status: 402,\n detail: mppProblemDetail(reason, refusal.detail),\n ...(reason !== undefined ? { reason } : {}),\n },\n }\n : {}),\n };\n}\n\n/** The receipt object from a serialized `Payment-Receipt` value, base64url JSON */\nexport function receiptObject(serialized: unknown): Record<string, unknown> | undefined {\n if (typeof serialized !== 'string') return undefined;\n try {\n const decoded: unknown = JSON.parse(Buffer.from(serialized, 'base64url').toString('utf8'));\n return isRecord(decoded) ? decoded : undefined;\n } catch {\n return undefined;\n }\n}\n"]}
|