vesant-sdk 1.7.2 → 1.8.0-dev.2b9e28d
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/dist/{client-D23KhWeh.d.mts → client-5q4whhGu.d.mts} +1 -1
- package/dist/{client-fy3trF2K.d.ts → client-BaUekQT8.d.ts} +32 -10
- package/dist/{client-B3DCAHlg.d.ts → client-DUHC-68_.d.ts} +1 -1
- package/dist/{client-BwXMQA2a.d.mts → client-XDEhh9VN.d.mts} +32 -10
- package/dist/compliance/index.d.mts +2 -2
- package/dist/compliance/index.d.ts +2 -2
- package/dist/compliance/index.js +40 -2
- package/dist/compliance/index.js.map +1 -1
- package/dist/compliance/index.mjs +40 -2
- package/dist/compliance/index.mjs.map +1 -1
- package/dist/decisions/index.js +1 -1
- package/dist/decisions/index.js.map +1 -1
- package/dist/decisions/index.mjs +1 -1
- package/dist/decisions/index.mjs.map +1 -1
- package/dist/geolocation/index.d.mts +2 -2
- package/dist/geolocation/index.d.ts +2 -2
- package/dist/geolocation/index.js +40 -2
- package/dist/geolocation/index.js.map +1 -1
- package/dist/geolocation/index.mjs +40 -2
- package/dist/geolocation/index.mjs.map +1 -1
- package/dist/{index-DSDgS09k.d.ts → index-BosFSGan.d.ts} +57 -2
- package/dist/{index-C3zUKydT.d.mts → index-C49a7fg2.d.mts} +57 -2
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +46 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +46 -3
- package/dist/index.mjs.map +1 -1
- package/dist/kyc/core.js +1 -1
- package/dist/kyc/core.js.map +1 -1
- package/dist/kyc/core.mjs +1 -1
- package/dist/kyc/core.mjs.map +1 -1
- package/dist/kyc/index.js +1 -1
- package/dist/kyc/index.js.map +1 -1
- package/dist/kyc/index.mjs +1 -1
- package/dist/kyc/index.mjs.map +1 -1
- package/dist/react.d.mts +9 -2
- package/dist/react.d.ts +9 -2
- package/dist/react.js +15 -10
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +15 -10
- package/dist/react.mjs.map +1 -1
- package/dist/risk-profile/index.js +1 -1
- package/dist/risk-profile/index.js.map +1 -1
- package/dist/risk-profile/index.mjs +1 -1
- package/dist/risk-profile/index.mjs.map +1 -1
- package/dist/scores/index.js +1 -1
- package/dist/scores/index.js.map +1 -1
- package/dist/scores/index.mjs +1 -1
- package/dist/scores/index.mjs.map +1 -1
- package/dist/tax/index.js +1 -1
- package/dist/tax/index.js.map +1 -1
- package/dist/tax/index.mjs +1 -1
- package/dist/tax/index.mjs.map +1 -1
- package/dist/webhooks/index.d.mts +1 -1
- package/dist/webhooks/index.d.ts +1 -1
- package/dist/webhooks/index.js +6 -0
- package/dist/webhooks/index.js.map +1 -1
- package/dist/webhooks/index.mjs +6 -1
- package/dist/webhooks/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/auth.ts","../src/core/errors.ts","../src/core/circuit-breaker.ts","../src/core/rate-limiter.ts","../src/core/logger.ts","../src/core/version.ts","../src/shared/browser-utils.ts","../src/core/client.ts","../src/core/pagination.ts","../src/core/dedup.ts","../src/core/webhook-utils.ts","../src/geolocation/integrity.ts","../src/geolocation/ciphertext.ts","../src/geolocation/client.ts","../src/risk-profile/client.ts","../src/compliance/block-reasons.ts","../src/compliance/types.ts","../src/compliance/client.ts","../src/kyc/client.ts","../src/kyc/types.ts","../src/tax/client.ts","../src/webhooks/handler.ts","../src/webhooks/middleware.ts"],"names":[],"mappings":";;;AAmCO,IAAM,uBAAN,MAAoD;AAAA,EACzD,YAA6B,MAAA,EAAgB;AAAhB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAAiB;AAAA,EAE9C,MAAM,aAAA,GAAgD;AACpD,IAAA,OAAO,IAAA,CAAK,SAAS,EAAE,MAAA,EAAQ,UAAU,KAAA,EAAO,IAAA,CAAK,QAAO,GAAI,IAAA;AAAA,EAClE;AAAA,EAEA,UAAA,GAAsB;AACpB,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAyBO,IAAM,0BAAN,MAAuD;AAAA,EAO5D,YAA6B,IAAA,EAAsC;AAAtC,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAN7B,IAAA,IAAA,CAAQ,MAAA,GAA6B,IAAA;AACrC,IAAA,IAAA,CAAQ,QAAA,GAAwC,IAAA;AAM9C,IAAA,IAAA,CAAK,MAAA,GAAS,KAAK,MAAA,IAAU,GAAA;AAC7B,IAAA,IAAA,CAAK,MAAA,GAAS,KAAK,MAAA,IAAU,QAAA;AAC7B,IAAA,IAAA,CAAK,GAAA,GAAM,IAAA,CAAK,GAAA,KAAQ,MAAM,KAAK,GAAA,EAAI,CAAA;AAAA,EACzC;AAAA,EAEA,UAAA,GAAsB;AACpB,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,cAAc,GAAA,EAA4D;AAC9E,IAAA,MAAM,YAAA,GAAe,KAAK,YAAA,IAAgB,KAAA;AAC1C,IAAA,IAAI,CAAC,gBAAgB,IAAA,CAAK,MAAA,IAAU,CAAC,IAAA,CAAK,UAAA,CAAW,IAAA,CAAK,MAAM,CAAA,EAAG;AACjE,MAAA,OAAO,EAAE,MAAA,EAAQ,IAAA,CAAK,QAAQ,KAAA,EAAO,IAAA,CAAK,OAAO,KAAA,EAAM;AAAA,IACzD;AACA,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,OAAA,EAAQ;AACjC,IAAA,OAAO,EAAE,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAQ,KAAA,EAAO,MAAM,KAAA,EAAM;AAAA,EACnD;AAAA,EAEQ,WAAW,KAAA,EAA6B;AAC9C,IAAA,IAAI,KAAA,CAAM,cAAc,MAAA,EAAW;AACjC,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,OAAO,IAAA,CAAK,GAAA,EAAI,IAAK,KAAA,CAAM,YAAY,IAAA,CAAK,MAAA;AAAA,EAC9C;AAAA,EAEQ,OAAA,GAAgC;AACtC,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA,OAAO,IAAA,CAAK,QAAA;AAAA,IACd;AACA,IAAA,IAAA,CAAK,YAAY,YAAY;AAC3B,MAAA,IAAI;AACF,QAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,IAAA,CAAK,UAAA,EAAW;AACzC,QAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AACd,QAAA,IAAA,CAAK,KAAK,QAAA,GAAW,EAAE,SAAA,EAAW,KAAA,CAAM,WAAW,CAAA;AACnD,QAAA,OAAO,KAAA;AAAA,MACT,CAAA,SAAE;AACA,QAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAAA,MAClB;AAAA,IACF,CAAA,GAAG;AACH,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd;AACF;;;AChHO,IAAM,WAAA,GAAN,MAAM,YAAA,SAAoB,KAAA,CAAM;AAAA,EAGrC,WAAA,CACE,OAAA,EACO,IAAA,EACA,UAAA,EACA,OAAA,EACP;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAJN,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AACA,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AACA,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAGP,IAAA,IAAA,CAAK,IAAA,GAAO,aAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,YAAA,CAAY,SAAS,CAAA;AAAA,EACnD;AACF;AAGO,IAAM,QAAA,GAAW;AAIjB,IAAM,YAAA,GAAN,MAAM,aAAA,SAAqB,WAAA,CAAY;AAAA,EAC5C,WAAA,CAAY,SAAwB,aAAA,EAAyB;AAC3D,IAAA,KAAA,CAAM,SAAS,eAAe,CAAA;AADI,IAAA,IAAA,CAAA,aAAA,GAAA,aAAA;AAElC,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,aAAA,CAAa,SAAS,CAAA;AAAA,EACpD;AACF;AAEO,IAAM,eAAA,GAAN,MAAM,gBAAA,SAAwB,WAAA,CAAY;AAAA,EAC/C,WAAA,CAAY,SAAiB,MAAA,EAAmB;AAC9C,IAAA,KAAA,CAAM,OAAA,EAAS,kBAAA,EAAoB,GAAA,EAAK,EAAE,QAAQ,CAAA;AAClD,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,gBAAA,CAAgB,SAAS,CAAA;AAAA,EACvD;AACF;AAEO,IAAM,uBAAA,GAAN,MAAM,wBAAA,SAAgC,WAAA,CAAY;AAAA,EACvD,WAAA,CAAY,UAAkB,qBAAA,EAAuB;AACnD,IAAA,KAAA,CAAM,OAAA,EAAS,uBAAuB,GAAG,CAAA;AACzC,IAAA,IAAA,CAAK,IAAA,GAAO,yBAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,wBAAA,CAAwB,SAAS,CAAA;AAAA,EAC/D;AACF;AAEO,IAAM,sBAAA,GAAN,MAAM,uBAAA,SAA+B,WAAA,CAAY;AAAA,EACtD,YAAY,OAAA,EAAmB;AAC7B,IAAA,KAAA,CAAM,wCAAA,EAA0C,oBAAA,EAAsB,GAAA,EAAK,EAAE,SAAS,CAAA;AACtF,IAAA,IAAA,CAAK,IAAA,GAAO,wBAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,uBAAA,CAAuB,SAAS,CAAA;AAAA,EAC9D;AACF;AAEO,IAAM,mBAAA,GAAN,MAAM,oBAAA,SAA4B,WAAA,CAAY;AAAA,EACnD,WAAA,CAAY,UAAkB,uBAAA,EAAyB;AACrD,IAAA,KAAA,CAAM,OAAA,EAAS,wBAAwB,GAAG,CAAA;AAC1C,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,oBAAA,CAAoB,SAAS,CAAA;AAAA,EAC3D;AACF;AAEO,IAAM,cAAA,GAAN,MAAM,eAAA,SAAuB,WAAA,CAAY;AAAA,EAC9C,YAAmB,UAAA,EAAqB;AACtC,IAAA,KAAA,CAAM,qBAAA,EAAuB,qBAAA,EAAuB,GAAA,EAAK,EAAE,YAAY,CAAA;AADtD,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAEjB,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,eAAA,CAAe,SAAS,CAAA;AAAA,EACtD;AACF;AAEO,IAAM,YAAA,GAAN,MAAM,aAAA,SAAqB,WAAA,CAAY;AAAA,EAC5C,YAAmB,OAAA,EAAiB;AAClC,IAAA,KAAA,CAAM,yBAAyB,OAAO,CAAA,EAAA,CAAA,EAAM,WAAW,GAAA,EAAK,EAAE,SAAS,CAAA;AADtD,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAEjB,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,aAAA,CAAa,SAAS,CAAA;AAAA,EACpD;AACF;AAEO,IAAM,eAAA,GAAN,MAAM,gBAAA,SAAwB,WAAA,CAAY;AAAA,EAC/C,WAAA,CACE,OAAA,EACO,aAAA,EACP,IAAA,GAAe,kBAAA,EACf;AACA,IAAA,KAAA,CAAM,SAAS,IAAI,CAAA;AAHZ,IAAA,IAAA,CAAA,aAAA,GAAA,aAAA;AAIP,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,gBAAA,CAAgB,SAAS,CAAA;AAAA,EACvD;AACF;AAEO,IAAM,uBAAA,GAAN,MAAM,wBAAA,SAAgC,WAAA,CAAY;AAAA,EACvD,WAAA,GAAc;AACZ,IAAA,KAAA,CAAM,iEAAA,EAA8D,wBAAwB,GAAG,CAAA;AAC/F,IAAA,IAAA,CAAK,IAAA,GAAO,yBAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,wBAAA,CAAwB,SAAS,CAAA;AAAA,EAC/D;AACF;;;AC5EO,IAAM,iBAAN,MAAqB;AAAA,EAU1B,WAAA,CAAY,MAAA,GAA+B,EAAC,EAAG;AAT/C,IAAA,IAAA,CAAQ,KAAA,GAA6B,QAAA;AACrC,IAAA,IAAA,CAAQ,QAAA,GAAW,CAAA;AACnB,IAAA,IAAA,CAAQ,SAAA,GAAY,CAAA;AACpB,IAAA,IAAA,CAAQ,eAAA,GAAiC,IAAA;AAOvC,IAAA,IAAA,CAAK,gBAAA,GAAmB,OAAO,gBAAA,IAAoB,CAAA;AACnD,IAAA,IAAA,CAAK,YAAA,GAAe,OAAO,YAAA,IAAgB,GAAA;AAC3C,IAAA,IAAA,CAAK,gBAAA,GAAmB,OAAO,gBAAA,IAAoB,CAAA;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA,GAAsB;AACpB,IAAA,IAAI,IAAA,CAAK,UAAU,QAAA,EAAU;AAC3B,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAQ;AACzB,MAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,MAAA,IAAI,KAAK,eAAA,IAAmB,GAAA,GAAM,IAAA,CAAK,eAAA,IAAmB,KAAK,YAAA,EAAc;AAC3E,QAAA,IAAA,CAAK,KAAA,GAAQ,WAAA;AACb,QAAA,IAAA,CAAK,SAAA,GAAY,CAAA;AACjB,QAAA,OAAO,IAAA;AAAA,MACT;AACA,MAAA,OAAO,KAAA;AAAA,IACT;AAGA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,GAAkB;AAChB,IAAA,IAAI,IAAA,CAAK,UAAU,WAAA,EAAa;AAC9B,MAAA,IAAA,CAAK,SAAA,EAAA;AACL,MAAA,IAAI,IAAA,CAAK,SAAA,IAAa,IAAA,CAAK,gBAAA,EAAkB;AAC3C,QAAA,IAAA,CAAK,KAAA,GAAQ,QAAA;AACb,QAAA,IAAA,CAAK,QAAA,GAAW,CAAA;AAChB,QAAA,IAAA,CAAK,SAAA,GAAY,CAAA;AACjB,QAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AAAA,MACzB;AAAA,IACF,CAAA,MAAA,IAAW,IAAA,CAAK,KAAA,KAAU,QAAA,EAAU;AAClC,MAAA,IAAA,CAAK,QAAA,GAAW,CAAA;AAAA,IAClB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,GAAkB;AAChB,IAAA,IAAA,CAAK,QAAA,EAAA;AACL,IAAA,IAAA,CAAK,eAAA,GAAkB,KAAK,GAAA,EAAI;AAEhC,IAAA,IAAI,IAAA,CAAK,UAAU,WAAA,EAAa;AAC9B,MAAA,IAAA,CAAK,KAAA,GAAQ,MAAA;AACb,MAAA,IAAA,CAAK,SAAA,GAAY,CAAA;AAAA,IACnB,WAAW,IAAA,CAAK,KAAA,KAAU,YAAY,IAAA,CAAK,QAAA,IAAY,KAAK,gBAAA,EAAkB;AAC5E,MAAA,IAAA,CAAK,KAAA,GAAQ,MAAA;AAAA,IACf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,GAAkC;AAChC,IAAA,OAAO;AAAA,MACL,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,iBAAiB,IAAA,CAAK,eAAA;AAAA,MACtB,aAAA,EACE,KAAK,KAAA,KAAU,MAAA,IAAU,KAAK,eAAA,GAC1B,IAAA,CAAK,eAAA,GAAkB,IAAA,CAAK,YAAA,GAC5B;AAAA,KACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,KAAA,GAAQ,QAAA;AACb,IAAA,IAAA,CAAK,QAAA,GAAW,CAAA;AAChB,IAAA,IAAA,CAAK,SAAA,GAAY,CAAA;AACjB,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AAAA,EACzB;AACF;;;ACtGO,IAAM,mBAAN,MAAuB;AAAA,EAAvB,WAAA,GAAA;AACL,IAAA,IAAA,CAAQ,KAAA,GAAuB,IAAA;AAC/B,IAAA,IAAA,CAAQ,SAAA,GAA2B,IAAA;AACnC,IAAA,IAAA,CAAQ,KAAA,GAAuB,IAAA;AAC/B,IAAA,IAAA,CAAQ,UAAA,GAA4B,IAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAKpC,kBAAkB,OAAA,EAAwB;AACxC,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,mBAAmB,CAAA;AAC7C,IAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,GAAA,CAAI,uBAAuB,CAAA;AACrD,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,mBAAmB,CAAA;AAC7C,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,GAAA,CAAI,aAAa,CAAA;AAE5C,IAAA,IAAI,UAAU,IAAA,EAAM,IAAA,CAAK,KAAA,GAAQ,QAAA,CAAS,OAAO,EAAE,CAAA;AACnD,IAAA,IAAI,cAAc,IAAA,EAAM,IAAA,CAAK,SAAA,GAAY,QAAA,CAAS,WAAW,EAAE,CAAA;AAC/D,IAAA,IAAI,UAAU,IAAA,EAAM,IAAA,CAAK,KAAA,GAAQ,QAAA,CAAS,OAAO,EAAE,CAAA;AACnD,IAAA,IAAI,eAAe,IAAA,EAAM,IAAA,CAAK,UAAA,GAAa,QAAA,CAAS,YAAY,EAAE,CAAA;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA,EAKA,eAAA,GAA2B;AACzB,IAAA,IAAI,IAAA,CAAK,SAAA,KAAc,IAAA,IAAQ,IAAA,CAAK,aAAa,CAAA,EAAG;AAElD,MAAA,IAAI,IAAA,CAAK,UAAU,IAAA,EAAM;AACvB,QAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,KAAQ,GAAI,CAAA;AACxC,QAAA,IAAI,GAAA,IAAO,KAAK,KAAA,EAAO;AAErB,UAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AACjB,UAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AACb,UAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAClB,UAAA,OAAO,KAAA;AAAA,QACT;AAAA,MACF;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,GAA6B;AAC3B,IAAA,OAAO;AAAA,MACL,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,YAAY,IAAA,CAAK;AAAA,KACnB;AAAA,EACF;AACF;;;ACrEO,SAAS,mBAAA,GAA8B;AAC5C,EAAA,OAAO;AAAA,IACL,KAAA,CAAM,SAAiB,IAAA,EAAgC;AACrD,MAAA,OAAA,CAAQ,IAAI,CAAA,aAAA,EAAgB,OAAO,IAAI,IAAA,KAAS,MAAA,GAAY,OAAO,EAAE,CAAA;AAAA,IACvE,CAAA;AAAA,IACA,IAAA,CAAK,SAAiB,IAAA,EAAgC;AACpD,MAAA,OAAA,CAAQ,KAAK,CAAA,aAAA,EAAgB,OAAO,IAAI,IAAA,KAAS,MAAA,GAAY,OAAO,EAAE,CAAA;AAAA,IACxE,CAAA;AAAA,IACA,IAAA,CAAK,SAAiB,IAAA,EAAgC;AACpD,MAAA,OAAA,CAAQ,KAAK,CAAA,aAAA,EAAgB,OAAO,IAAI,IAAA,KAAS,MAAA,GAAY,OAAO,EAAE,CAAA;AAAA,IACxE,CAAA;AAAA,IACA,KAAA,CAAM,SAAiB,IAAA,EAAgC;AACrD,MAAA,OAAA,CAAQ,MAAM,CAAA,aAAA,EAAgB,OAAO,IAAI,IAAA,KAAS,MAAA,GAAY,OAAO,EAAE,CAAA;AAAA,IACzE;AAAA,GACF;AACF;AAEO,IAAM,UAAA,GAAqB;AAAA,EAChC,KAAA,GAAQ;AAAA,EAAC,CAAA;AAAA,EACT,IAAA,GAAO;AAAA,EAAC,CAAA;AAAA,EACR,IAAA,GAAO;AAAA,EAAC,CAAA;AAAA,EACR,KAAA,GAAQ;AAAA,EAAC;AACX;;;ACrBO,IAAM,WAAA,GAAc;;;ACOpB,SAAS,YAAA,GAAuB;AACrC,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,MAAA,CAAO,UAAA,EAAY;AACtD,IAAA,OAAO,OAAO,UAAA,EAAW;AAAA,EAC3B;AAGA,EAAA,OAAO,sCAAA,CAAuC,OAAA,CAAQ,OAAA,EAAS,CAAC,CAAA,KAAM;AACpE,IAAA,MAAM,CAAA,GAAK,IAAA,CAAK,MAAA,EAAO,GAAI,EAAA,GAAM,CAAA;AACjC,IAAA,MAAM,CAAA,GAAI,CAAA,KAAM,GAAA,GAAM,CAAA,GAAK,IAAI,CAAA,GAAO,CAAA;AACtC,IAAA,OAAO,CAAA,CAAE,SAAS,EAAE,CAAA;AAAA,EACtB,CAAC,CAAA;AACH;AAMO,SAAS,gBAAA,GAA2B;AACzC,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,OAAO,iBAAiB,WAAA,EAAa;AACxE,IAAA,OAAO,YAAA,EAAa;AAAA,EACtB;AAEA,EAAA,MAAM,UAAA,GAAa,kBAAA;AACnB,EAAA,IAAI,QAAA,GAAW,YAAA,CAAa,OAAA,CAAQ,UAAU,CAAA;AAE9C,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,QAAA,GAAW,YAAA,EAAa;AACxB,IAAA,YAAA,CAAa,OAAA,CAAQ,YAAY,QAAQ,CAAA;AAAA,EAC3C;AAEA,EAAA,OAAO,QAAA;AACT;AAMO,SAAS,cAAA,GAKd;AACA,EAAA,IAAI,OAAO,cAAc,WAAA,EAAa;AACpC,IAAA,OAAO,EAAE,SAAS,SAAA,EAAW,eAAA,EAAiB,IAAI,EAAA,EAAI,SAAA,EAAW,YAAY,EAAA,EAAG;AAAA,EAClF;AAEA,EAAA,MAAM,KAAK,SAAA,CAAU,SAAA;AACrB,EAAA,IAAI,OAAA,GAAU,SAAA;AACd,EAAA,IAAI,cAAA,GAAiB,EAAA;AACrB,EAAA,IAAI,EAAA,GAAK,SAAA;AACT,EAAA,IAAI,SAAA,GAAY,EAAA;AAGhB,EAAA,IAAI,EAAA,CAAG,QAAA,CAAS,UAAU,CAAA,EAAG;AAC3B,IAAA,OAAA,GAAU,SAAA;AACV,IAAA,cAAA,GAAiB,EAAA,CAAG,KAAA,CAAM,mBAAmB,CAAA,GAAI,CAAC,CAAA,IAAK,EAAA;AAAA,EACzD,CAAA,MAAA,IAAW,EAAA,CAAG,QAAA,CAAS,MAAM,CAAA,EAAG;AAC9B,IAAA,OAAA,GAAU,MAAA;AACV,IAAA,cAAA,GAAiB,EAAA,CAAG,KAAA,CAAM,eAAe,CAAA,GAAI,CAAC,CAAA,IAAK,EAAA;AAAA,EACrD,CAAA,MAAA,IAAW,EAAA,CAAG,QAAA,CAAS,SAAS,CAAA,EAAG;AACjC,IAAA,OAAA,GAAU,QAAA;AACV,IAAA,cAAA,GAAiB,EAAA,CAAG,KAAA,CAAM,kBAAkB,CAAA,GAAI,CAAC,CAAA,IAAK,EAAA;AAAA,EACxD,CAAA,MAAA,IAAW,GAAG,QAAA,CAAS,SAAS,KAAK,CAAC,EAAA,CAAG,QAAA,CAAS,QAAQ,CAAA,EAAG;AAC3D,IAAA,OAAA,GAAU,QAAA;AACV,IAAA,cAAA,GAAiB,EAAA,CAAG,KAAA,CAAM,mBAAmB,CAAA,GAAI,CAAC,CAAA,IAAK,EAAA;AAAA,EACzD,CAAA,MAAA,IAAW,GAAG,QAAA,CAAS,OAAO,KAAK,EAAA,CAAG,QAAA,CAAS,MAAM,CAAA,EAAG;AACtD,IAAA,OAAA,GAAU,OAAA;AACV,IAAA,cAAA,GAAiB,EAAA,CAAG,KAAA,CAAM,yBAAyB,CAAA,GAAI,CAAC,CAAA,IAAK,EAAA;AAAA,EAC/D;AAGA,EAAA,IAAI,EAAA,CAAG,QAAA,CAAS,SAAS,CAAA,EAAG;AAC1B,IAAA,EAAA,GAAK,SAAA;AACL,IAAA,IAAI,EAAA,CAAG,QAAA,CAAS,iBAAiB,CAAA,EAAG,SAAA,GAAY,IAAA;AAAA,SAAA,IACvC,EAAA,CAAG,QAAA,CAAS,gBAAgB,CAAA,EAAG,SAAA,GAAY,KAAA;AAAA,SAAA,IAC3C,EAAA,CAAG,QAAA,CAAS,gBAAgB,CAAA,EAAG,SAAA,GAAY,GAAA;AAAA,SAAA,IAC3C,EAAA,CAAG,QAAA,CAAS,gBAAgB,CAAA,EAAG,SAAA,GAAY,GAAA;AAAA,EACtD,CAAA,MAAA,IAAW,EAAA,CAAG,QAAA,CAAS,UAAU,CAAA,EAAG;AAClC,IAAA,EAAA,GAAK,OAAA;AACL,IAAA,SAAA,GAAY,EAAA,CAAG,MAAM,mBAAmB,CAAA,GAAI,CAAC,CAAA,EAAG,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAA,IAAK,EAAA;AAAA,EACxE,CAAA,MAAA,IAAW,EAAA,CAAG,QAAA,CAAS,OAAO,CAAA,EAAG;AAC/B,IAAA,EAAA,GAAK,OAAA;AAAA,EACP,CAAA,MAAA,IAAW,EAAA,CAAG,QAAA,CAAS,SAAS,CAAA,EAAG;AACjC,IAAA,EAAA,GAAK,SAAA;AACL,IAAA,SAAA,GAAY,EAAA,CAAG,KAAA,CAAM,kBAAkB,CAAA,GAAI,CAAC,CAAA,IAAK,EAAA;AAAA,EACnD,CAAA,MAAA,IAAW,EAAA,CAAG,QAAA,CAAS,KAAK,CAAA,IAAK,EAAA,CAAG,QAAA,CAAS,QAAQ,CAAA,IAAK,EAAA,CAAG,QAAA,CAAS,MAAM,CAAA,EAAG;AAC7E,IAAA,EAAA,GAAK,KAAA;AACL,IAAA,SAAA,GAAY,EAAA,CAAG,MAAM,aAAa,CAAA,GAAI,CAAC,CAAA,EAAG,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAA,IAAK,EAAA;AAAA,EAClE;AAEA,EAAA,OAAO,EAAE,OAAA,EAAS,eAAA,EAAiB,cAAA,EAAgB,EAAA,EAAI,YAAY,SAAA,EAAU;AAC/E;;;ACzEO,IAAe,aAAf,MAA0B;AAAA,EAQ/B,YAAY,MAAA,EAA0B;AAJtC,IAAA,IAAA,CAAQ,cAAA,GAAwC,IAAA;AAChD,IAAA,IAAA,CAAQ,gBAAA,GAA4C,IAAA;AAIlD,IAAA,IAAI,CAAC,MAAA,CAAO,OAAA,EAAS,IAAA,EAAK,EAAG;AAC3B,MAAA,MAAM,IAAI,eAAA,CAAgB,oDAAA,EAAsD,CAAC,SAAS,CAAC,CAAA;AAAA,IAC7F;AACA,IAAA,IAAI,CAAC,MAAA,CAAO,QAAA,EAAU,IAAA,EAAK,EAAG;AAC5B,MAAA,MAAM,IAAI,eAAA,CAAgB,qDAAA,EAAuD,CAAC,UAAU,CAAC,CAAA;AAAA,IAC/F;AAIA,IAAA,IAAI,OAAO,UAAU,WAAA,EAAa;AAChC,MAAA,MAAM,IAAI,WAAA;AAAA,QACR,mGAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,YAAA,GAAe,MAAA,CAAO,YAAA,IAAgB,EAAC;AAC5C,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA,CAAO,MAAA,IAAU,mBAAA,EAAoB;AAGnD,IAAA,IAAI,cAAc,MAAA,CAAO,WAAA;AACzB,IAAA,MAAM,MAAA,GAAS,OAAO,MAAA,IAAU,EAAA;AAChC,IAAA,IAAI,MAAA,CAAO,UAAA,CAAW,UAAU,CAAA,EAAG;AACjC,MAAA,IAAI,gBAAgB,YAAA,EAAc;AAChC,QAAA,IAAA,CAAK,MAAA,CAAO,KAAK,gGAA2F,CAAA;AAAA,MAC9G;AACA,MAAA,WAAA,GAAc,SAAA;AAAA,IAChB,WAAW,MAAA,CAAO,UAAA,CAAW,UAAU,CAAA,IAAK,gBAAgB,SAAA,EAAW;AACrE,MAAA,IAAA,CAAK,MAAA,CAAO,KAAK,2IAAsI,CAAA;AAAA,IACzJ;AAEA,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,GAAG,MAAA;AAAA,MACH,MAAA;AAAA,MACA,WAAA;AAAA,MACA,OAAA,EAAS,MAAA,CAAO,OAAA,IAAW,EAAC;AAAA,MAC5B,OAAA,EAAS,OAAO,OAAA,IAAW,GAAA;AAAA,MAC3B,OAAA,EAAS,OAAO,OAAA,IAAW,CAAA;AAAA,MAC3B,KAAA,EAAO,OAAO,KAAA,IAAS,KAAA;AAAA,MACvB,cAAc,IAAA,CAAK,YAAA;AAAA,MACnB,QAAQ,IAAA,CAAK;AAAA,KACf;AAIA,IAAA,IAAA,CAAK,eAAe,MAAA,CAAO,YAAA,KAAiB,SAAS,IAAI,oBAAA,CAAqB,MAAM,CAAA,GAAI,MAAA,CAAA;AAExF,IAAA,IAAI,OAAO,cAAA,EAAgB;AACzB,MAAA,IAAA,CAAK,cAAA,GAAiB,IAAI,cAAA,CAAe,MAAA,CAAO,cAAc,CAAA;AAAA,IAChE;AACA,IAAA,IAAI,OAAO,uBAAA,EAAyB;AAClC,MAAA,IAAA,CAAK,gBAAA,GAAmB,IAAI,gBAAA,EAAiB;AAAA,IAC/C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,qBAAA,CAAsB,QAAgB,cAAA,EAAqD;AACjG,IAAA,MAAM,UAAA,GAAa,CAAC,MAAA,EAAQ,KAAA,EAAO,OAAO,EAAE,QAAA,CAAA,CAAU,MAAA,IAAU,KAAA,EAAO,WAAA,EAAa,CAAA;AACpF,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,OAAO,cAAA,EAAgB,kBAAkB,YAAA,EAAa;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,OAAA,CACd,QAAA,EACA,UAAuB,EAAC,EACxB,YACA,cAAA,EACY;AACZ,IAAA,MAAM,YAAY,YAAA,EAAa;AAG/B,IAAA,IAAI,KAAK,cAAA,IAAkB,CAAC,IAAA,CAAK,cAAA,CAAe,YAAW,EAAG;AAC5D,MAAA,MAAM,KAAA,GAAQ,IAAI,uBAAA,EAAwB;AAC1C,MAAA,KAAA,CAAM,SAAA,GAAY,SAAA;AAClB,MAAA,MAAM,KAAA;AAAA,IACR;AAGA,IAAA,IAAI,IAAA,CAAK,gBAAA,IAAoB,IAAA,CAAK,gBAAA,CAAiB,iBAAgB,EAAG;AACpE,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,gBAAA,CAAiB,SAAA,EAAU;AAC/C,MAAA,MAAM,KAAA,GAAQ,IAAI,cAAA,CAAe,MAAA,CAAO,cAAc,MAAS,CAAA;AAC/D,MAAA,KAAA,CAAM,SAAA,GAAY,SAAA;AAClB,MAAA,MAAM,KAAA;AAAA,IACR;AAEA,IAAA,MAAM,MAAM,CAAA,EAAG,UAAA,IAAc,KAAK,MAAA,CAAO,OAAO,GAAG,QAAQ,CAAA,CAAA;AAE3D,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,cAAA,EAAgB,kBAAA;AAAA,MAChB,aAAA,EAAe,KAAK,MAAA,CAAO,QAAA;AAAA,MAC3B,eAAA,EAAiB,iBAAiB,WAAW,CAAA,CAAA;AAAA,MAC7C,cAAA,EAAgB,SAAA;AAAA,MAChB,GAAG,KAAK,MAAA,CAAO,OAAA;AAAA,MACf,GAAK,OAAA,CAAQ,OAAA,IAAsC;AAAC,KACtD;AAIA,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,YAAA,EAAc,aAAA,CAAc;AAAA,MACxD,QAAA,EAAU,KAAK,MAAA,CAAO,QAAA;AAAA,MACtB;AAAA,KACD,CAAA;AACD,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,OAAA,CAAQ,eAAe,IAAI,CAAA,EAAG,UAAA,CAAW,UAAU,QAAQ,CAAA,CAAA,EAAI,WAAW,KAAK,CAAA,CAAA;AAAA,IACjF;AAGA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,WAAA,KAAgB,SAAA,EAAW;AACzC,MAAA,OAAA,CAAQ,WAAW,CAAA,GAAI,MAAA;AAAA,IACzB;AAKA,IAAA,MAAM,MAAA,GAAA,CAAU,OAAA,CAAQ,MAAA,IAAU,KAAA,EAAO,WAAA,EAAY;AACrD,IAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,qBAAA,CAAsB,MAAA,EAAQ,cAAc,CAAA;AACxE,IAAA,IAAI,cAAA,EAAgB;AAClB,MAAA,OAAA,CAAQ,iBAAiB,CAAA,GAAI,cAAA;AAAA,IAC/B;AAEA,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,SAAA,GAAY,WAAW,MAAM,UAAA,CAAW,OAAM,EAAG,IAAA,CAAK,OAAO,OAAO,CAAA;AAG1E,IAAA,IAAI,gBAAgB,MAAA,EAAQ;AAC1B,MAAA,IAAI,cAAA,CAAe,OAAO,OAAA,EAAS;AACjC,QAAA,UAAA,CAAW,KAAA,EAAM;AAAA,MACnB,CAAA,MAAO;AACL,QAAA,cAAA,CAAe,MAAA,CAAO,gBAAA,CAAiB,OAAA,EAAS,MAAM,UAAA,CAAW,OAAM,EAAG,EAAE,IAAA,EAAM,IAAA,EAAM,CAAA;AAAA,MAC1F;AAAA,IACF;AAEA,IAAA,IAAI;AAEF,MAAA,IAAI,YAAA,GAA4B,EAAE,GAAG,OAAA,EAAS,OAAA,EAAQ;AACtD,MAAA,KAAA,MAAW,WAAA,IAAe,KAAK,YAAA,EAAc;AAC3C,QAAA,IAAI,YAAY,SAAA,EAAW;AACzB,UAAA,YAAA,GAAe,MAAM,WAAA,CAAY,SAAA,CAAU,GAAA,EAAK,YAAY,CAAA;AAAA,QAC9D;AAAA,MACF;AAEA,MAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,EAAG,YAAA,CAAa,UAAU,KAAK,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAE,CAAA;AAAA,MACjE;AAEA,MAAA,IAAI,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,QAC9B,GAAG,YAAA;AAAA,QACH,QAAQ,UAAA,CAAW;AAAA,OACpB,CAAA;AAKD,MAAA,IAAI,SAAS,MAAA,KAAW,GAAA,IAAO,IAAA,CAAK,YAAA,EAAc,cAAa,EAAG;AAChE,QAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,YAAA,CAAa,aAAA,CAAc;AAAA,UACtD,QAAA,EAAU,KAAK,MAAA,CAAO,QAAA;AAAA,UACtB,SAAA;AAAA,UACA,YAAA,EAAc;AAAA,SACf,CAAA;AACD,QAAA,IAAI,SAAA,EAAW;AACb,UAAA,IAAA,CAAK,MAAA,CAAO,mBAAA,GAAsB,EAAE,MAAA,EAAQ,gBAAgB,CAAA;AAC5D,UAAA,YAAA,GAAe;AAAA,YACb,GAAG,YAAA;AAAA,YACH,OAAA,EAAS;AAAA,cACP,GAAI,YAAA,CAAa,OAAA;AAAA,cACjB,eAAe,CAAA,EAAG,SAAA,CAAU,UAAU,QAAQ,CAAA,CAAA,EAAI,UAAU,KAAK,CAAA;AAAA;AACnE,WACF;AACA,UAAA,QAAA,GAAW,MAAM,MAAM,GAAA,EAAK,EAAE,GAAG,YAAA,EAAc,MAAA,EAAQ,UAAA,CAAW,MAAA,EAAQ,CAAA;AAAA,QAC5E;AAAA,MACF;AAEA,MAAA,YAAA,CAAa,SAAS,CAAA;AAGtB,MAAA,IAAI,KAAK,gBAAA,EAAkB;AACzB,QAAA,IAAA,CAAK,gBAAA,CAAiB,iBAAA,CAAkB,QAAA,CAAS,OAAO,CAAA;AAAA,MAC1D;AAGA,MAAA,IAAI,cAAA,EAAgB,iBAAiB,aAAA,EAAe;AAClD,QAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,UAAA,IAAI,UAAmC,EAAC;AACxC,UAAA,IAAI;AAAE,YAAA,OAAA,GAAU,MAAM,SAAS,IAAA,EAAK;AAAA,UAAG,CAAA,CAAA,MAAQ;AAAA,UAAe;AAC9D,UAAA,IAAA,CAAK,mBAAA,CAAoB,QAAA,CAAS,MAAA,EAAQ,OAAA,EAAS,SAAS,CAAA;AAAA,QAC9D;AACA,QAAA,IAAA,CAAK,gBAAgB,SAAA,EAAU;AAC/B,QAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,WAAA,EAAY;AAC1C,QAAA,OAAO,MAAA;AAAA,MACT;AAEA,MAAA,IAAI,IAAA;AACJ,MAAA,IAAI;AACF,QAAA,IAAA,GAAO,MAAM,SAAS,IAAA,EAAK;AAAA,MAC7B,CAAA,CAAA,MAAQ;AAEN,QAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,UAAA,IAAA,CAAK,mBAAA,CAAoB,SAAS,MAAA,EAAQ;AAAA,YACxC,KAAA,EAAO,CAAA,KAAA,EAAQ,QAAA,CAAS,MAAM,CAAA,CAAA;AAAA,YAC9B,SAAS,QAAA,CAAS;AAAA,aACjB,SAAS,CAAA;AAAA,QACd;AAEA,QAAA,IAAA,CAAK,gBAAgB,SAAA,EAAU;AAC/B,QAAA,OAAO,KAAA,CAAA;AAAA,MACT;AAEA,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,QAAA,IAAA,CAAK,oBAAoB,QAAA,CAAS,MAAA,EAAQ,IAAA,IAAQ,IAAI,SAAS,CAAA;AAAA,MACjE;AAGA,MAAA,IAAA,CAAK,gBAAgB,SAAA,EAAU;AAG/B,MAAA,IAAI,MAAA,GAAkB,IAAA;AACtB,MAAA,KAAA,MAAW,WAAA,IAAe,KAAK,YAAA,EAAc;AAC3C,QAAA,IAAI,YAAY,UAAA,EAAY;AAC1B,UAAA,MAAA,GAAS,MAAM,WAAA,CAAY,UAAA,CAAW,GAAA,EAAK,MAAM,CAAA;AAAA,QACnD;AAAA,MACF;AAEA,MAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,QAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,CAAA,UAAA,EAAa,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAAA,MAClD;AAEA,MAAA,OAAO,MAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,YAAA,CAAa,SAAS,CAAA;AAGtB,MAAA,IACE,iBAAiB,WAAA,IACjB,KAAA,CAAM,UAAA,IACN,KAAA,CAAM,cAAc,GAAA,EACpB;AACA,QAAA,IAAA,CAAK,gBAAgB,SAAA,EAAU;AAAA,MACjC,CAAA,MAAA,IAAW,KAAA,YAAiB,YAAA,IAAgB,KAAA,YAAiB,YAAA,EAAc;AACzE,QAAA,IAAA,CAAK,gBAAgB,SAAA,EAAU;AAAA,MACjC;AAGA,MAAA,IAAI,KAAA,YAAiB,WAAA,IAAe,CAAC,KAAA,CAAM,SAAA,EAAW;AACpD,QAAA,KAAA,CAAM,SAAA,GAAY,SAAA;AAAA,MACpB;AAGA,MAAA,IAAI,iBAAiB,KAAA,EAAO;AAC1B,QAAA,KAAA,MAAW,WAAA,IAAe,KAAK,YAAA,EAAc;AAC3C,UAAA,IAAI,YAAY,OAAA,EAAS;AACvB,YAAA,MAAM,WAAA,CAAY,OAAA,CAAQ,GAAA,EAAK,KAAK,CAAA;AAAA,UACtC;AAAA,QACF;AAAA,MACF;AAEA,MAAA,IAAI,iBAAiB,KAAA,EAAO;AAC1B,QAAA,IAAI,KAAA,CAAM,SAAS,YAAA,EAAc;AAE/B,UAAA,IAAI,cAAA,EAAgB,QAAQ,OAAA,EAAS;AACnC,YAAA,MAAM,UAAA,GAAa,IAAI,WAAA,CAAY,iBAAA,EAAmB,iBAAiB,CAAA;AACvE,YAAA,UAAA,CAAW,SAAA,GAAY,SAAA;AACvB,YAAA,MAAM,UAAA;AAAA,UACR;AACA,UAAA,IAAA,CAAK,gBAAgB,SAAA,EAAU;AAC/B,UAAA,MAAM,YAAA,GAAe,IAAI,YAAA,CAAa,IAAA,CAAK,OAAO,OAAO,CAAA;AACzD,UAAA,YAAA,CAAa,SAAA,GAAY,SAAA;AACzB,UAAA,MAAM,YAAA;AAAA,QACR;AACA,QAAA,IAAI,iBAAiB,WAAA,EAAa;AAChC,UAAA,MAAM,KAAA;AAAA,QACR;AAAA,MACF;AAEA,MAAA,MAAM,YAAA,GAAe,IAAI,YAAA,CAAa,wBAAA,EAA0B,KAAK,CAAA;AACrE,MAAA,YAAA,CAAa,SAAA,GAAY,SAAA;AACzB,MAAA,IAAA,CAAK,gBAAgB,SAAA,EAAU;AAC/B,MAAA,MAAM,YAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,gBAAA,CACd,QAAA,EACA,OAAA,GAAuB,EAAC,EACxB,UAAA,EACA,OAAA,GAAkB,IAAA,CAAK,MAAA,CAAO,OAAA,EAC9B,cAAA,EACY;AACZ,IAAA,IAAI,SAAA;AAIJ,IAAA,MAAM,iBAAiB,IAAA,CAAK,qBAAA,CAAsB,OAAA,CAAQ,MAAA,IAAU,OAAO,cAAc,CAAA;AACzF,IAAA,MAAM,iBAA6C,cAAA,GAC/C,EAAE,GAAG,cAAA,EAAgB,gBAAe,GACpC,cAAA;AAEJ,IAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,IAAW,OAAA,EAAS,OAAA,EAAA,EAAW;AACnD,MAAA,IAAI;AACF,QAAA,OAAO,MAAM,IAAA,CAAK,OAAA,CAAW,QAAA,EAAU,OAAA,EAAS,YAAY,cAAc,CAAA;AAAA,MAC5E,SAAS,KAAA,EAAO;AACd,QAAA,SAAA,GAAY,KAAA,YAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,MAAM,eAAe,CAAA;AAGtE,QAAA,IAAI,cAAA,EAAgB,QAAQ,OAAA,EAAS;AACnC,UAAA,MAAM,SAAA;AAAA,QACR;AAGA,QAAA,IACE,SAAA,YAAqB,WAAA,IACrB,SAAA,CAAU,UAAA,IACV,SAAA,CAAU,UAAA,IAAc,GAAA,IACxB,SAAA,CAAU,UAAA,GAAa,GAAA,IACvB,SAAA,CAAU,UAAA,KAAe,GAAA,EACzB;AACA,UAAA,MAAM,SAAA;AAAA,QACR;AAGA,QAAA,IAAI,YAAY,OAAA,EAAS;AACvB,UAAA;AAAA,QACF;AAGA,QAAA,IAAI,KAAA;AACJ,QAAA,IAAI,SAAA,YAAqB,cAAA,IAAkB,SAAA,CAAU,UAAA,EAAY;AAC/D,UAAA,KAAA,GAAQ,UAAU,UAAA,GAAa,GAAA;AAAA,QACjC,CAAA,MAAO;AACL,UAAA,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,GAAA,GAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAO,CAAA,GAAI,IAAA,CAAK,MAAA,EAAO,GAAI,GAAA,EAAM,GAAK,CAAA;AAAA,QAC5E;AACA,QAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,KAAK,CAAC,CAAA;AAEzD,QAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,UAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,CAAA,cAAA,EAAiB,OAAA,GAAU,CAAC,CAAA,CAAA,EAAI,OAAO,CAAA,OAAA,EAAU,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,EAAA,CAAI,CAAA;AAAA,QACzF;AAAA,MACF;AAAA,IACF;AAEA,IAAA,MAAM,IAAI,YAAA,CAAa,CAAA,qBAAA,EAAwB,OAAO,YAAY,SAAS,CAAA;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA,EAKU,mBAAA,CAAoB,MAAA,EAAgB,IAAA,EAA+B,SAAA,EAA2B;AACtG,IAAA,MAAM,UAAW,IAAA,CAAK,KAAA,IAAqB,IAAA,CAAK,OAAA,IAAsB,QAAQ,MAAM,CAAA,CAAA;AAEpF,IAAA,MAAM,cAAc,MAAmB;AACrC,MAAA,QAAQ,MAAA;AAAQ,QACd,KAAK,GAAA;AACH,UAAA,OAAO,IAAI,WAAA,CAAY,OAAA,EAAS,aAAA,EAAe,GAAG,CAAA;AAAA,QACpD,KAAK,GAAA;AACH,UAAA,OAAO,IAAI,oBAAoB,OAAO,CAAA;AAAA,QACxC,KAAK,GAAA;AACH,UAAA,OAAO,IAAI,WAAA,CAAY,OAAA,EAAS,WAAA,EAAa,GAAG,CAAA;AAAA,QAClD,KAAK,GAAA;AACH,UAAA,OAAO,IAAI,WAAA,CAAY,OAAA,EAAS,WAAA,EAAa,GAAG,CAAA;AAAA,QAClD,KAAK,GAAA;AACH,UAAA,OAAO,IAAI,WAAA,CAAY,OAAA,EAAS,mBAAA,EAAqB,GAAG,CAAA;AAAA,QAC1D,KAAK,GAAA,EAAK;AACR,UAAA,MAAM,UAAA,GAAc,IAAA,CAAK,WAAA,IAAuC,IAAA,CAAK,UAAA;AACrE,UAAA,OAAO,IAAI,eAAe,UAAU,CAAA;AAAA,QACtC;AAAA,QACA,KAAK,GAAA;AAAA,QACL,KAAK,GAAA;AAAA,QACL,KAAK,GAAA;AAAA,QACL,KAAK,GAAA;AACH,UAAA,OAAO,IAAI,wBAAwB,OAAO,CAAA;AAAA,QAC5C;AACE,UAAA,OAAO,IAAI,WAAA,CAAY,OAAA,EAAS,eAAA,EAAiB,MAAM,CAAA;AAAA;AAC3D,IACF,CAAA;AAEA,IAAA,MAAM,QAAQ,WAAA,EAAY;AAC1B,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,KAAA,CAAM,SAAA,GAAY,SAAA;AAAA,IACpB;AACA,IAAA,MAAM,KAAA;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKU,iBAAiB,MAAA,EAAyC;AAClE,IAAA,MAAM,KAAA,GAAQ,IAAI,eAAA,EAAgB;AAElC,IAAA,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM;AAC/C,MAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AACzC,QAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,UAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,KAAS,KAAA,CAAM,OAAO,GAAA,EAAK,MAAA,CAAO,IAAI,CAAC,CAAC,CAAA;AAAA,QACzD,CAAA,MAAO;AACL,UAAA,KAAA,CAAM,MAAA,CAAO,GAAA,EAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,QACjC;AAAA,MACF;AAAA,IACF,CAAC,CAAA;AAED,IAAA,MAAM,WAAA,GAAc,MAAM,QAAA,EAAS;AACnC,IAAA,OAAO,WAAA,GAAc,CAAA,CAAA,EAAI,WAAW,CAAA,CAAA,GAAK,EAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,MAAA,EAAyC;AACpD,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,GAAG,IAAA,CAAK,MAAA;AAAA,MACR,GAAG,MAAA;AAAA,MACH,OAAA,EAAS;AAAA,QACP,GAAG,KAAK,MAAA,CAAO,OAAA;AAAA,QACf,GAAI,MAAA,CAAO,OAAA,IAAW;AAAC;AACzB,KACF;AACA,IAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,MAAA,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AAAA,IACvB;AACA,IAAA,IAAI,OAAO,YAAA,EAAc;AACvB,MAAA,IAAA,CAAK,eAAe,MAAA,CAAO,YAAA;AAAA,IAC7B;AAGA,IAAA,IAAI,MAAA,CAAO,YAAA,KAAiB,MAAA,IAAa,MAAA,CAAO,WAAW,MAAA,EAAW;AACpE,MAAA,IAAA,CAAK,YAAA,GACH,IAAA,CAAK,MAAA,CAAO,YAAA,KACX,IAAA,CAAK,MAAA,CAAO,MAAA,GAAS,IAAI,oBAAA,CAAqB,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,GAAI,MAAA,CAAA;AAAA,IACzE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,GAAwC;AACtC,IAAA,OAAO,EAAE,GAAG,IAAA,CAAK,MAAA,EAAO;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAA,GAA6C;AAC3C,IAAA,OAAO,IAAA,CAAK,gBAAA,EAAkB,SAAA,EAAU,IAAK,IAAA;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,uBAAA,GAAuD;AACrD,IAAA,OAAO,IAAA,CAAK,cAAA,EAAgB,SAAA,EAAU,IAAK,IAAA;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAA,GAA8D;AAClE,IAAA,OAAO,IAAA,CAAK,QAAQ,gBAAgB,CAAA;AAAA,EACtC;AACF;;;AC3eA,gBAAuB,SACrB,SAAA,EAC+B;AAC/B,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,IAAI,UAAA;AACJ,EAAA,GAAG;AACD,IAAA,MAAM,QAAA,GAAW,MAAM,SAAA,CAAU,IAAI,CAAA;AACrC,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,IAAA,IAAQ,EAAC;AAChC,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,MAAM,IAAA;AAAA,IACR;AACA,IAAA,UAAA,GAAa,SAAS,WAAA,IAAe,IAAA;AACrC,IAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,MAAA;AAAA,IACF;AACA,IAAA,IAAA,IAAQ,CAAA;AAAA,EACV,SAAS,IAAA,IAAQ,UAAA;AACnB;AAGA,eAAsB,WACpB,SAAA,EACc;AACd,EAAA,MAAM,QAAa,EAAC;AACpB,EAAA,WAAA,MAAiB,IAAA,IAAQ,QAAA,CAAS,SAAS,CAAA,EAAG;AAC5C,IAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,EACjB;AACA,EAAA,OAAO,KAAA;AACT;;;AClBO,IAAM,qBAAN,MAAsD;AAAA,EAK3D,WAAA,CAAY,IAAA,GAAkC,EAAC,EAAG;AAJlD,IAAA,IAAA,CAAiB,UAAA,uBAAiB,GAAA,EAAoB;AAKpD,IAAA,IAAA,CAAK,UAAA,GAAa,KAAK,UAAA,IAAc,GAAA;AACrC,IAAA,IAAA,CAAK,GAAA,GAAM,IAAA,CAAK,GAAA,KAAQ,MAAM,KAAK,GAAA,EAAI,CAAA;AAAA,EACzC;AAAA,EAEA,MAAM,KAAK,EAAA,EAA8B;AACvC,IAAA,OAAO,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,EAAE,CAAA;AAAA,EAC/B;AAAA,EAEA,MAAM,IAAA,CAAK,EAAA,EAAY,KAAA,EAA8B;AACnD,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,EAAA,EAAI,GAAA,GAAM,KAAK,CAAA;AAGnC,IAAA,IAAI,IAAA,CAAK,UAAA,CAAW,IAAA,GAAO,IAAA,CAAK,UAAA,EAAY;AAC1C,MAAA,KAAA,MAAW,CAAC,GAAA,EAAK,SAAS,CAAA,IAAK,KAAK,UAAA,EAAY;AAC9C,QAAA,IAAI,MAAM,SAAA,EAAW;AACnB,UAAA,IAAA,CAAK,UAAA,CAAW,OAAO,GAAG,CAAA;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ACnBA,eAAsB,uBACpB,OAAA,EACA,SAAA,EACA,MAAA,EACA,IAAA,GAAsC,EAAC,EACrB;AAClB,EAAA,MAAM,MAAA,GAAS,qBAAqB,SAAS,CAAA;AAC7C,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,MAAM,SAAA,GAAY,KAAK,SAAA,IAAa,GAAA;AACpC,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,IAAM,IAAK,KAAK,GAAA,EAAI;AAErC,IAAA,IAAI,SAAA,GAAY,KAAK,IAAA,CAAK,GAAA,CAAI,MAAM,MAAA,CAAO,CAAA,GAAI,GAAI,CAAA,GAAI,SAAA,EAAW;AAChE,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,MAAM,QAAA,GAAW,MAAM,iBAAA,CAAkB,CAAA,EAAG,OAAO,CAAC,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA,EAAI,MAAM,CAAA;AACzE,IAAA,OAAO,iBAAA,CAAkB,MAAA,CAAO,EAAA,EAAI,QAAQ,CAAA;AAAA,EAC9C;AAEA,EAAA,IAAI,IAAA,CAAK,gBAAgB,KAAA,EAAO;AAC9B,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,SAAA,GAAY,MAAM,iBAAA,CAAkB,OAAA,EAAS,MAAM,CAAA;AAEzD,EAAA,MAAM,gBAAA,GAAmB,UAAU,SAAS,CAAA,CAAA;AAE5C,EAAA,IAAI,SAAA,CAAU,UAAA,CAAW,SAAS,CAAA,EAAG;AACnC,IAAA,OAAO,iBAAA,CAAkB,WAAW,gBAAgB,CAAA;AAAA,EACtD;AAEA,EAAA,OAAO,iBAAA,CAAkB,WAAW,SAAS,CAAA;AAC/C;AAMA,SAAS,qBAAqB,SAAA,EAAqD;AACjF,EAAA,IAAI,CAAC,UAAU,QAAA,CAAS,IAAI,KAAK,CAAC,SAAA,CAAU,QAAA,CAAS,KAAK,CAAA,EAAG;AAC3D,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,CAAA;AACJ,EAAA,IAAI,EAAA;AACJ,EAAA,KAAA,MAAW,IAAA,IAAQ,SAAA,CAAU,KAAA,CAAM,GAAG,CAAA,EAAG;AACvC,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AAC3B,IAAA,IAAI,OAAO,EAAA,EAAI;AACf,IAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,EAAE,IAAA,EAAK;AACnC,IAAA,MAAM,QAAQ,IAAA,CAAK,KAAA,CAAM,EAAA,GAAK,CAAC,EAAE,IAAA,EAAK;AACtC,IAAA,IAAI,GAAA,KAAQ,GAAA,EAAK,CAAA,GAAI,MAAA,CAAO,KAAK,CAAA;AAAA,SAAA,IACxB,GAAA,KAAQ,MAAM,EAAA,GAAK,KAAA;AAAA,EAC9B;AACA,EAAA,IAAI,MAAM,MAAA,IAAa,MAAA,CAAO,MAAM,CAAC,CAAA,IAAK,CAAC,EAAA,EAAI;AAC7C,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,EAAE,GAAG,EAAA,EAAG;AACjB;AAMA,eAAe,iBAAA,CAAkB,SAAiB,MAAA,EAAiC;AAEjF,EAAA,IAAI,OAAO,UAAA,CAAW,MAAA,KAAW,WAAA,IAAe,UAAA,CAAW,OAAO,MAAA,EAAQ;AACxE,IAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,IAAA,MAAM,GAAA,GAAM,MAAM,UAAA,CAAW,MAAA,CAAO,MAAA,CAAO,SAAA;AAAA,MACzC,KAAA;AAAA,MACA,OAAA,CAAQ,OAAO,MAAM,CAAA;AAAA,MACrB,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAU;AAAA,MAChC,KAAA;AAAA,MACA,CAAC,MAAM;AAAA,KACT;AACA,IAAA,MAAM,GAAA,GAAM,MAAM,UAAA,CAAW,MAAA,CAAO,MAAA,CAAO,IAAA,CAAK,MAAA,EAAQ,GAAA,EAAK,OAAA,CAAQ,MAAA,CAAO,OAAO,CAAC,CAAA;AACpF,IAAA,OAAO,KAAA,CAAM,KAAK,IAAI,UAAA,CAAW,GAAG,CAAC,CAAA,CAClC,IAAI,CAAC,CAAA,KAAM,EAAE,QAAA,CAAS,EAAE,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAC1C,KAAK,EAAE,CAAA;AAAA,EACZ;AAGA,EAAA,IAAI;AACF,IAAA,MAAM,EAAE,UAAA,EAAW,GAAI,MAAM,OAAO,QAAQ,CAAA;AAC5C,IAAA,OAAO,UAAA,CAAW,UAAU,MAAM,CAAA,CAAE,OAAO,OAAO,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,EAClE,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,WAAA;AAAA,MACR,uFAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AACF;AAKA,SAAS,iBAAA,CAAkB,GAAW,CAAA,EAAoB;AACxD,EAAA,IAAI,CAAA,CAAE,MAAA,KAAW,CAAA,CAAE,MAAA,EAAQ;AACzB,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,IAAI,MAAA,GAAS,CAAA;AACb,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,CAAE,QAAQ,CAAA,EAAA,EAAK;AACjC,IAAA,MAAA,IAAU,EAAE,UAAA,CAAW,CAAC,CAAA,GAAI,CAAA,CAAE,WAAW,CAAC,CAAA;AAAA,EAC5C;AACA,EAAA,OAAO,MAAA,KAAW,CAAA;AACpB;;;ACjGA,IAAM,KAAA,GAAQ,CAAC,CAAA,KAAwD,CAAA,KAAM,QAAQ,CAAA,KAAM,MAAA;AAKpF,SAAS,kBAAA,CAAmB,KAAA,EAA0B,IAAA,GAA4B,EAAC,EAAuB;AAC/G,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,KAAQ,MAAM,KAAK,GAAA,EAAI,CAAA;AACxC,EAAA,MAAM,QAAA,GAAW,KAAK,QAAA,IAAY,GAAA;AAClC,EAAA,MAAM,WAAA,GAAc,KAAK,iBAAA,IAAqB,CAAA;AAC9C,EAAA,MAAM,EAAE,QAAA,EAAU,QAAA,EAAU,kBAAkB,OAAA,EAAS,KAAA,EAAO,WAAU,GAAI,KAAA;AAI5E,EAAA,IAAI,KAAA,CAAM,QAAQ,CAAA,EAAG;AACnB,IAAA,KAAA,CAAM,KAAK,kBAAkB,CAAA;AAAA,EAC/B,CAAA,MAAA,IAAW,aAAa,CAAA,EAAG;AACzB,IAAA,KAAA,CAAM,KAAK,eAAe,CAAA;AAAA,EAC5B,CAAA,MAAA,IAAW,WAAW,WAAA,EAAa;AACjC,IAAA,KAAA,CAAM,KAAK,4BAA4B,CAAA;AAAA,EACzC;AAGA,EAAA,MAAM,YAAY,CAAC,KAAA,CAAM,OAAO,CAAA,IAAK,CAAC,MAAM,KAAK,CAAA;AACjD,EAAA,IAAI,SAAA,KAAc,KAAA,CAAM,QAAQ,CAAA,IAAK,aAAa,CAAA,CAAA,EAAI;AACpD,IAAA,KAAA,CAAM,KAAK,yBAAyB,CAAA;AAAA,EACtC;AAGA,EAAA,IAAI,CAAC,KAAA,CAAM,QAAQ,CAAA,IAAK,KAAA,CAAM,gBAAgB,CAAA,EAAG;AAC/C,IAAA,KAAA,CAAM,KAAK,2BAA2B,CAAA;AAAA,EACxC;AAGA,EAAA,IAAI,SAAA,KAAc,MAAA,IAAa,GAAA,EAAI,GAAI,YAAY,QAAA,EAAU;AAC3D,IAAA,KAAA,CAAM,KAAK,iBAAiB,CAAA;AAAA,EAC9B;AAGA,EAAA,IAAI,IAAA,CAAK,eAAA,KAAoB,QAAA,IAAY,IAAA,CAAK,oBAAoB,QAAA,EAAU;AAC1E,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,WAAA,EAAc,IAAA,CAAK,eAAe,CAAA,CAAE,CAAA;AAAA,EACjD;AAEA,EAAA,OAAO,EAAE,UAAA,EAAY,KAAA,CAAM,MAAA,GAAS,GAAG,KAAA,EAAM;AAC/C;AAMO,SAAS,8BAA8B,QAAA,EAAkD;AAC9F,EAAA,MAAM,IAAI,QAAA,CAAS,MAAA;AACnB,EAAA,OAAO;AAAA,IACL,UAAU,CAAA,CAAE,QAAA;AAAA,IACZ,WAAW,CAAA,CAAE,SAAA;AAAA,IACb,UAAU,CAAA,CAAE,QAAA;AAAA,IACZ,UAAU,CAAA,CAAE,QAAA;AAAA,IACZ,kBAAkB,CAAA,CAAE,gBAAA;AAAA,IACpB,SAAS,CAAA,CAAE,OAAA;AAAA,IACX,OAAO,CAAA,CAAE,KAAA;AAAA,IACT,WAAW,QAAA,CAAS;AAAA,GACtB;AACF;AAOA,eAAsB,0BAAA,GAAuE;AAC3F,EAAA,IAAI;AACF,IAAA,IAAI,OAAO,SAAA,KAAc,WAAA,IAAe,CAAC,SAAA,CAAU,aAAa,KAAA,EAAO;AACrE,MAAA,OAAO,aAAA;AAAA,IACT;AACA,IAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU,WAAA,CAAY,MAAM,EAAE,IAAA,EAAM,eAAiC,CAAA;AAC1F,IAAA,OAAO,MAAA,CAAO,KAAA;AAAA,EAChB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,aAAA;AAAA,EACT;AACF;;;ACtFA,IAAM,0BAAA,GAA6B,CAAA;AAMnC,SAAS,YAAA,GAA4D;AACnE,EAAA,IAAI,OAAO,QAAA,KAAa,WAAA,EAAa,OAAO,IAAA;AAE5C,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC9C,IAAA,MAAM,KAAK,MAAA,CAAO,UAAA,CAAW,OAAO,CAAA,IAAK,MAAA,CAAO,WAAW,oBAAoB,CAAA;AAE/E,IAAA,IAAI,CAAC,IAAI,OAAO,IAAA;AAEhB,IAAA,MAAM,SAAA,GAAa,EAAA,CAA6B,YAAA,CAAa,2BAA2B,CAAA;AACxF,IAAA,IAAI,CAAC,WAAW,OAAO,IAAA;AAEvB,IAAA,OAAO;AAAA,MACL,MAAA,EAAS,EAAA,CAA6B,YAAA,CAAa,SAAA,CAAU,qBAAqB,CAAA,IAAK,EAAA;AAAA,MACvF,QAAA,EAAW,EAAA,CAA6B,YAAA,CAAa,SAAA,CAAU,uBAAuB,CAAA,IAAK;AAAA,KAC7F;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAKA,SAAS,cAAA,GAA2D;AAClE,EAAA,IAAI,OAAO,SAAA,KAAc,WAAA,EAAa,OAAO,MAAA;AAE7C,EAAA,MAAM,UAAA,GAAc,SAAA,CAAkB,UAAA,IACnC,SAAA,CAAkB,iBAClB,SAAA,CAAkB,gBAAA;AAErB,EAAA,IAAI,CAAC,YAAY,OAAO,MAAA;AAExB,EAAA,OAAO;AAAA,IACL,gBAAgB,UAAA,CAAW,aAAA;AAAA,IAC3B,UAAU,UAAA,CAAW,QAAA;AAAA,IACrB,KAAK,UAAA,CAAW,GAAA;AAAA,IAChB,WAAW,UAAA,CAAW;AAAA,GACxB;AACF;AAKA,eAAe,kBAAA,CACb,OAAA,GAAkB,GAAA,EAClB,YAAA,GAAwB,IAAA,EACuB;AAC/C,EAAA,IAAI,OAAO,SAAA,KAAc,WAAA,IAAe,CAAC,UAAU,WAAA,EAAa;AAC9D,IAAA,OAAO,IAAA;AAAA,EACT;AAIA,EAAA,MAAM,eAAA,GAAkB,MAAM,0BAAA,EAA2B;AAEzD,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC9B,IAAA,SAAA,CAAU,WAAA,CAAY,kBAAA;AAAA,MACpB,CAAC,QAAA,KAAa;AACZ,QAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAW,QAAA,KAAa,QAAA,CAAS,MAAA;AAGnD,QAAA,IAAI,QAAA,GAAW,GAAA,IAAO,QAAA,GAAW,EAAA,EAAI;AACnC,UAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,UAAA;AAAA,QACF;AACA,QAAA,IAAI,SAAA,GAAY,IAAA,IAAQ,SAAA,GAAY,GAAA,EAAK;AACvC,UAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,UAAA;AAAA,QACF;AACA,QAAA,IAAI,QAAA,KAAa,IAAA,IAAQ,QAAA,KAAa,MAAA,IAAa,YAAY,CAAA,EAAG;AAChE,UAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,UAAA;AAAA,QACF;AAEA,QAAA,MAAM,EAAE,OAAM,GAAI,kBAAA,CAAmB,8BAA8B,QAAQ,CAAA,EAAG,EAAE,eAAA,EAAiB,CAAA;AAEjG,QAAA,OAAA,CAAQ;AAAA,UACN,QAAA;AAAA,UACA,SAAA;AAAA,UACA,QAAA;AAAA,UACA,QAAA,EAAU,QAAA,CAAS,MAAA,CAAO,QAAA,IAAY,MAAA;AAAA,UACtC,iBAAA,EAAmB,QAAA,CAAS,MAAA,CAAO,gBAAA,IAAoB,MAAA;AAAA,UACvD,OAAA,EAAS,QAAA,CAAS,MAAA,CAAO,OAAA,IAAW,MAAA;AAAA,UACpC,KAAA,EAAO,QAAA,CAAS,MAAA,CAAO,KAAA,IAAS,MAAA;AAAA,UAChC,WAAW,QAAA,CAAS,SAAA;AAAA,UACpB,eAAA,EAAiB,KAAA,CAAM,MAAA,GAAS,KAAA,GAAQ;AAAA,SACzC,CAAA;AAAA,MACH,CAAA;AAAA,MACA,MAAM;AAEJ,QAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,MACd,CAAA;AAAA,MACA;AAAA,QACE,kBAAA,EAAoB,YAAA;AAAA,QACpB,OAAA;AAAA,QACA,UAAA,EAAY;AAAA;AACd,KACF;AAAA,EACF,CAAC,CAAA;AACH;AAKA,SAAS,kBAAkB,YAAA,EAAoD;AAC7E,EAAA,MAAM,cAAc,cAAA,EAAe;AACnC,EAAA,MAAM,SAAA,GAAY,YAAA,GAAe,YAAA,EAAa,GAAI,IAAA;AAElD,EAAA,OAAO;AAAA,IACL,WAAW,gBAAA,EAAoB;AAAA,IAC/B,UAAA,EAAY,OAAO,SAAA,KAAc,WAAA,GAAc,UAAU,SAAA,GAAY,EAAA;AAAA,IACrE,QAAA,EAAU,OAAO,SAAA,KAAc,WAAA,GAAc,UAAU,QAAA,GAAW,EAAA;AAAA,IAClE,SAAS,WAAA,CAAY,OAAA;AAAA,IACrB,iBAAiB,WAAA,CAAY,eAAA;AAAA,IAC7B,IAAI,WAAA,CAAY,EAAA;AAAA,IAChB,YAAY,WAAA,CAAY,UAAA;AAAA,IACxB,iBAAA,EACE,OAAO,MAAA,KAAW,WAAA,GAAc,CAAA,EAAG,OAAO,KAAK,CAAA,CAAA,EAAI,MAAA,CAAO,MAAM,CAAA,CAAA,GAAK,MAAA;AAAA,IACvE,QAAA,EAAU,OAAO,SAAA,KAAc,WAAA,GAAc,UAAU,QAAA,GAAW,MAAA;AAAA,IAClE,QAAA,EAAU,IAAA,EAAM,cAAA,IAAiB,EAAG,mBAAkB,EAAG,QAAA;AAAA,IACzD,WAAA,EAAa,OAAO,MAAA,KAAW,WAAA,GAAc,OAAO,UAAA,GAAa,MAAA;AAAA,IACjE,oBAAA,EACE,OAAO,SAAA,KAAc,WAAA,GAAc,UAAU,mBAAA,GAAsB,MAAA;AAAA,IACrE,aAAA,EAAe,OAAO,SAAA,KAAc,WAAA,GAAe,UAAkB,YAAA,GAAe,MAAA;AAAA,IACpF,eACE,OAAO,SAAA,KAAc,WAAA,GAAc,SAAA,CAAU,iBAAiB,CAAA,GAAI,MAAA;AAAA,IACpE,cAAc,SAAA,EAAW,MAAA;AAAA,IACzB,gBAAgB,SAAA,EAAW;AAAA,GAC7B;AACF;AAKA,SAAS,cAAc,OAAA,EAAoC;AACzD,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA;AAEnC,EAAA,IAAI,OAAO,SAAS,WAAA,EAAa;AAE/B,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,kBAAA,CAAmB,IAAI,CAAC,CAAC,CAAA;AAAA,EAChD,CAAA,MAAA,IAAW,OAAO,MAAA,KAAW,WAAA,EAAa;AAExC,IAAA,OAAO,OAAO,IAAA,CAAK,IAAA,EAAM,OAAO,CAAA,CAAE,SAAS,QAAQ,CAAA;AAAA,EACrD;AAEA,EAAA,MAAM,IAAI,WAAA,CAAY,qCAAA,EAAuC,oBAAoB,CAAA;AACnF;AA0BA,eAAsB,kBAAA,CACpB,SACA,MAAA,EAC2B;AAC3B,EAAA,MAAM,WAAqB,EAAC;AAG5B,EAAA,IAAI,eAAA,GAAkB,QAAQ,eAAA,IAAmB,KAAA;AACjD,EAAA,IAAI,mBAAA,GAAsB,KAAA;AAC1B,EAAA,IAAI,QAAQ,WAAA,EAAa;AACvB,IAAA,MAAM,SAAS,OAAA,CAAQ,MAAA;AACvB,IAAA,IACG,MAAA,KAAW,OAAA,IAAW,MAAA,CAAO,WAAA,CAAY,SACzC,MAAA,KAAW,cAAA,IAAkB,MAAA,CAAO,WAAA,CAAY,YAAA,IAChD,MAAA,KAAW,aAAA,IAAiB,MAAA,CAAO,YAAY,WAAA,EAChD;AACA,MAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,QAAA,mBAAA,GAAsB,IAAA;AAAA,MACxB;AACA,MAAA,eAAA,GAAkB,IAAA;AAAA,IACpB;AAAA,EACF;AAGA,EAAA,MAAM,UAAA,GAAa,iBAAA,CAAkB,OAAA,CAAQ,YAAA,KAAiB,KAAK,CAAA;AAGnE,EAAA,IAAI,YAAA;AACJ,EAAA,IAAI,eAAA,EAAiB;AACnB,IAAA,MAAM,WAAW,MAAM,kBAAA;AAAA,MACrB,QAAQ,eAAA,IAAmB,GAAA;AAAA,MAC3B,QAAQ,YAAA,KAAiB;AAAA,KAC3B;AAEA,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,YAAA,GAAe,QAAA;AACf,MAAA,IAAI,QAAA,CAAS,iBAAiB,MAAA,EAAQ;AACpC,QAAA,QAAA,CAAS,KAAK,CAAA,gCAAA,EAAmC,QAAA,CAAS,gBAAgB,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,MACxF;AAAA,IACF,WAAW,mBAAA,EAAqB;AAC9B,MAAA,MAAM,IAAI,WAAA;AAAA,QACR,CAAA,6BAAA,EAAgC,QAAQ,MAAM,CAAA,4EAAA,CAAA;AAAA,QAC9C;AAAA,OACF;AAAA,IACF,CAAA,MAAO;AACL,MAAA,QAAA,CAAS,KAAK,iDAAiD,CAAA;AAAA,IACjE;AAAA,EACF;AAGA,EAAA,IAAI,WAAA;AACJ,EAAA,IAAI,OAAA,CAAQ,uBAAuB,KAAA,EAAO;AACxC,IAAA,WAAA,GAAc,cAAA,EAAe;AAAA,EAC/B;AAGA,EAAA,MAAM,GAAA,uBAAU,IAAA,EAAK;AACrB,EAAA,MAAM,MAAA,GAAS,IAAI,IAAA,CAAK,GAAA,CAAI,SAAQ,GAAI,0BAAA,GAA6B,KAAK,GAAI,CAAA;AAE9E,EAAA,MAAM,OAAA,GAA6B;AAAA,IACjC,MAAA,EAAQ,UAAA;AAAA,IACR,QAAA,EAAU,YAAA;AAAA,IACV,OAAA,EAAS,WAAA;AAAA,IACT,QAAA,EAAU;AAAA,MACR,YAAA,EAAc,IAAI,WAAA,EAAY;AAAA,MAC9B,WAAA,EAAa,WAAA;AAAA,MACb,mBAAmB,OAAA,CAAQ,MAAA;AAAA,MAC3B,UAAU,OAAO,MAAA,KAAW,WAAA,GAAc,MAAA,CAAO,SAAS,IAAA,GAAO,MAAA;AAAA,MACjE,UAAU,OAAO,QAAA,KAAa,WAAA,GAAc,QAAA,CAAS,YAAY,MAAA,GAAY;AAAA;AAC/E,GACF;AAGA,EAAA,MAAM,OAAA,GAAU,cAAc,OAAO,CAAA;AAGrC,EAAA,MAAM,SAAA,GAAY,GAAA,CAAI,OAAA,EAAQ,CAAE,SAAS,EAAE,CAAA;AAO3C,EAAA,MAAM,UAAA,GAAa,CAAA,GAAA,EAAM,SAAS,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA;AAE7C,EAAA,OAAO;AAAA,IACL,UAAA;AAAA,IACA,gBAAA,EAAkB,CAAC,CAAC,YAAA;AAAA,IACpB,QAAA,EAAU,QAAA,CAAS,MAAA,GAAS,CAAA,GAAI,QAAA,GAAW,MAAA;AAAA,IAC3C,WAAA,EAAa,IAAI,WAAA,EAAY;AAAA,IAC7B,SAAA,EAAW,OAAO,WAAA;AAAY,GAChC;AACF;AAMO,IAAM,oBAAA,GAAuB;AAM7B,SAAS,iBAAiB,UAAA,EAA8C;AAC7E,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,KAAA,CAAM,GAAG,CAAA;AAElC,IAAA,IAAI,MAAM,MAAA,KAAW,CAAA,IAAK,KAAA,CAAM,MAAA,KAAW,GAAG,OAAO,IAAA;AAErD,IAAA,MAAM,CAAC,OAAA,IAAW,UAAU,CAAA,GAAI,KAAA;AAChC,IAAA,IAAI,OAAA,KAAY,IAAA,IAAQ,OAAA,KAAY,IAAA,EAAM,OAAO,IAAA;AAGjD,IAAA,MAAM,OAAO,kBAAA,CAAmB,MAAA,CAAO,IAAA,CAAK,UAAU,CAAC,CAAC,CAAA;AAExD,IAAA,OAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,EACxB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAKO,SAAS,oBAAoB,UAAA,EAA6B;AAC/D,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,KAAA,CAAM,GAAG,CAAA;AAClC,IAAA,IAAI,MAAM,MAAA,KAAW,CAAA,IAAK,KAAA,CAAM,MAAA,KAAW,GAAG,OAAO,IAAA;AAErD,IAAA,MAAM,YAAA,GAAe,MAAM,CAAC,CAAA;AAC5B,IAAA,MAAM,SAAA,GAAY,QAAA,CAAS,YAAA,EAAc,EAAE,CAAA;AAC3C,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,QAAA,GAAW,6BAA6B,EAAA,GAAK,GAAA;AAEnD,IAAA,OAAO,MAAM,SAAA,GAAY,QAAA;AAAA,EAC3B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;;;AC7SO,IAAM,iBAAA,GAAN,cAAgC,UAAA,CAAW;AAAA,EAEhD,YAAY,MAAA,EAAiC;AAE3C,IAAA,MAAM,UAAA,GAA+B;AAAA,MACnC,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,OAAA,EAAS,CAAA;AAAA;AAAA,MACT,OAAO,MAAA,CAAO,KAAA;AAAA,MACd,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,aAAa,MAAA,CAAO;AAAA,KACtB;AACA,IAAA,KAAA,CAAM,UAAU,CAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgCA,MAAM,QAAA,CAAS,OAAA,EAA0B,cAAA,EAAgE;AAGvG,IAAA,IAAI,QAAQ,UAAA,KAAe,MAAA,IAAa,CAAC,OAAA,CAAQ,UAAA,CAAW,MAAK,EAAG;AAClE,MAAA,MAAM,IAAI,eAAA,CAAgB,uDAAA,EAAyD,CAAC,YAAY,CAAC,CAAA;AAAA,IACnG;AAGA,IAAA,OAAO,IAAA,CAAK,iBAAuC,oBAAA,EAAsB;AAAA,MACvE,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,KAC9B,EAAG,MAAA,EAAW,MAAA,EAAW,cAAc,CAAA;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,eAAA,CAAgB,UAAA,EAAoB,cAAA,EAAmE;AAC3G,IAAA,OAAO,IAAA,CAAK,gBAAA;AAAA,MACV,CAAA,4BAAA,CAAA;AAAA,MACA;AAAA,QACE,MAAA,EAAQ,MAAA;AAAA,QACR,MAAM,IAAA,CAAK,SAAA,CAAU,EAAE,WAAA,EAAa,YAAY;AAAA,OAClD;AAAA,MAAG,MAAA;AAAA,MAAW,MAAA;AAAA,MAAW;AAAA,KAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAM,aAAa,cAAA,EAAqE;AACtF,IAAA,OAAO,KAAK,gBAAA,CAA4C,oBAAA,EAAsB,MAAA,EAAW,MAAA,EAAW,QAAW,cAAc,CAAA;AAAA,EAC/H;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,iBAAA,CACJ,MAAA,EACA,SAAA,EACA,cAAA,EACuB;AACvB,IAAA,IAAI,CAAC,MAAA,EAAQ,IAAA,EAAK,EAAG;AACnB,MAAA,MAAM,IAAI,eAAA,CAAgB,mDAAA,EAAqD,CAAC,QAAQ,CAAC,CAAA;AAAA,IAC3F;AAIA,IAAA,MAAM,OAAA,GAAU,EAAE,OAAA,EAAS,MAAA,EAAQ,YAAY,SAAA,EAAU;AACzD,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,2BAAA;AAAA,MACA;AAAA,QACE,MAAA,EAAQ,MAAA;AAAA,QACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,OAC9B;AAAA,MAAG,MAAA;AAAA,MAAW;AAAA,KAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,mBAAA,CACZ,MAAA,EACA,SAAA,EACA,cAAA,EAC6B;AAC7B,IAAA,IAAI;AACF,MAAA,MAAM,EAAE,OAAM,GAAI,MAAM,KAAK,iBAAA,CAAkB,MAAA,EAAQ,WAAW,cAAc,CAAA;AAChF,MAAA,OAAO,KAAA;AAAA,IACT,SAAS,GAAA,EAAK;AACZ,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA;AAAA,QACV,+DAA+D,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,OACjH;AACA,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+CA,MAAM,kBAAA,CACJ,UAAA,EACA,QACA,SAAA,EACA,UAAA,EACA,cACA,cAAA,EACqC;AACrC,IAAA,IAAI,CAAC,UAAA,EAAY,IAAA,EAAK,EAAG;AACvB,MAAA,MAAM,IAAI,eAAA,CAAgB,uDAAA,EAAyD,CAAC,YAAY,CAAC,CAAA;AAAA,IACnG;AACA,IAAA,IAAI,CAAC,MAAA,EAAQ,IAAA,EAAK,EAAG;AACnB,MAAA,MAAM,IAAI,eAAA,CAAgB,mDAAA,EAAqD,CAAC,QAAQ,CAAC,CAAA;AAAA,IAC3F;AAEA,IAAA,MAAM,QAAQ,MAAM,IAAA,CAAK,mBAAA,CAAoB,MAAA,EAAQ,WAAW,cAAc,CAAA;AAE9E,IAAA,MAAM,OAAA,GAAqC;AAAA,MACzC,WAAA,EAAa,UAAA;AAAA,MACb,OAAA,EAAS,MAAA;AAAA,MACT,UAAA,EAAY,SAAA;AAAA,MACZ,WAAA,EAAa,UAAA;AAAA,MACb,aAAA,EAAe,YAAA;AAAA,MACf;AAAA,KACF;AAEA,IAAA,OAAO,IAAA,CAAK,gBAAA;AAAA,MACV,iCAAA;AAAA,MACA;AAAA,QACE,MAAA,EAAQ,MAAA;AAAA,QACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,OAC9B;AAAA,MAAG,MAAA;AAAA,MAAW,MAAA;AAAA,MAAW;AAAA,KAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgCA,MAAM,iBAAA,CACJ,UAAA,EACA,SAAA,EACA,MAAA,EACA,WACA,cAAA,EAKC;AAID,IAAA,MAAM,gBAAA,GAAmB,MAAM,IAAA,CAAK,kBAAA;AAAA,MAClC,UAAA;AAAA,MACA,MAAA;AAAA,MACA,SAAA;AAAA,MACA,SAAA;AAAA,MACA,MAAA;AAAA,MACA;AAAA,KACF;AAIA,IAAA,MAAM,MAAM,gBAAA,CAAiB,QAAA;AAC7B,IAAA,MAAM,OAAO,gBAAA,CAAiB,IAAA;AAE9B,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,MAAM,cAAA,GAAiB,MAAM,IAAA,CAAK,QAAA,CAAS;AAAA,QACzC,UAAA,EAAY,SAAA;AAAA,QACZ,OAAA,EAAS,MAAA;AAAA,QACT,UAAA,EAAY;AAAA,SACX,cAAc,CAAA;AACjB,MAAA,OAAO;AAAA,QACL,kBAAkB,gBAAA,CAAiB,KAAA;AAAA,QACnC,iBAAA,EAAmB,gBAAA;AAAA,QACnB,QAAA,EAAU;AAAA,OACZ;AAAA,IACF;AAEA,IAAA,MAAM,QAAA,GAAiC;AAAA,MACrC,YAAY,gBAAA,CAAiB,UAAA;AAAA,MAC7B,QAAA,EAAU;AAAA,QACR,OAAA,EAAS,KAAK,OAAA,IAAW,EAAA;AAAA,QACzB,WAAA,EAAa,KAAK,WAAA,IAAe,EAAA;AAAA,QACjC,IAAA,EAAM,KAAK,IAAA,IAAQ,EAAA;AAAA,QACnB,MAAA,EAAQ,KAAK,MAAA,IAAU,EAAA;AAAA,QACvB,WAAA,EAAa,EAAA;AAAA,QACb,QAAA,EAAU,KAAK,QAAA,IAAY,CAAA;AAAA,QAC3B,SAAA,EAAW,KAAK,SAAA,IAAa,CAAA;AAAA,QAC7B,QAAA,EAAU,EAAA;AAAA,QACV,MAAA,EAAQ,KAAK,MAAA,IAAU,KAAA;AAAA,QACvB,QAAA,EAAU,KAAK,QAAA,IAAY,KAAA;AAAA,QAC3B,MAAA,EAAQ,KAAK,MAAA,IAAU,KAAA;AAAA,QACvB,UAAA,EAAY,KAAK,UAAA,IAAc,KAAA;AAAA,QAC/B,aAAA,EAAe,IAAA,CAAK,MAAA,IAAU,IAAA,CAAK,YAAY,IAAA,CAAK;AAAA,OACtD;AAAA,MACA,YAAA,EAAc,gBAAA,CAAiB,YAAA,IAAgB,CAAC,IAAA,CAAK,UAAA;AAAA,MACrD,UAAA,EAAY,KAAK,UAAA,IAAc,KAAA;AAAA,MAC/B,UAAA,EAAY,KAAK,KAAA,IAAS,KAAA;AAAA,MAC1B,UAAA,EAAY,KAAK,KAAA,IAAS,CAAA;AAAA,MAC1B,YAAA,EAAc,KAAK,UAAA,IAAc,IAAA,CAAK,gBAClC,IAAA,CAAK,aAAA,GACJ,IAAA,CAAK,OAAA,IAAW,EAAC;AAAA,MACtB,uBAAA,EAAyB,IAAA,CAAK,wBAAA,IAA4B,EAAC;AAAA,MAC3D,cAAc,gBAAA,CAAiB,YAAA;AAAA,MAC/B,qBAAqB,gBAAA,CAAiB,mBAAA;AAAA,MACtC,SAAA,EAAW,iBAAiB,SAAA,IAAa,EAAA;AAAA,MACzC,cAAc,gBAAA,CAAiB;AAAA,KACjC;AAEA,IAAA,OAAO;AAAA,MACL,kBAAkB,gBAAA,CAAiB,KAAA;AAAA,MACnC,iBAAA,EAAmB,gBAAA;AAAA,MACnB;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyBA,MAAM,qBAAA,CACJ,OAAA,EACA,cAAA,EACgC;AAChC,IAAA,OAAO,IAAA,CAAK,QAA+B,2BAAA,EAA6B;AAAA,MACtE,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,KAC9B,EAAG,QAAW,cAAc,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,kBAAA,CAAmB,SAAA,EAAmB,cAAA,EAA2D;AACrG,IAAA,OAAO,KAAK,OAAA,CAAyB,CAAA,0BAAA,EAA6B,SAAS,CAAA,CAAA,EAAI,MAAA,EAAW,QAAW,cAAc,CAAA;AAAA,EACrH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,oBAAA,CACJ,OAAA,EACA,UAAA,EACA,cAAA,EACsC;AACtC,IAAA,MAAM,MAAA,GAAkC;AAAA,MACtC,GAAG,OAAA;AAAA,MACH,GAAG;AAAA,KACL;AAEA,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,CAAA,yBAAA,EAA4B,IAAA,CAAK,gBAAA,CAAiB,MAAM,CAAC,CAAA,CAAA;AAAA,MACzD,MAAA;AAAA,MAAW,MAAA;AAAA,MAAW;AAAA,KACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,qBAAA,CAAsB,SAAA,EAAmB,cAAA,EAAgD;AAC7F,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAA,0BAAA,EAA6B,SAAS,CAAA,OAAA,CAAA,EAAW;AAAA,MAClE,MAAA,EAAQ;AAAA,KACV,EAAG,QAAW,cAAc,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAA,CACJ,SAAA,EACA,OAAA,EACA,cAAA,EACe;AACf,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAA,0BAAA,EAA6B,SAAS,CAAA,OAAA,CAAA,EAAW;AAAA,MAClE,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,KAC9B,EAAG,QAAW,cAAc,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,oBAAA,CAAqB,KAAA,EAAe,cAAA,EAA6D;AACrG,IAAA,OAAO,KAAK,OAAA,CAA2B,CAAA,uBAAA,EAA0B,KAAK,CAAA,CAAA,EAAI,MAAA,EAAW,QAAW,cAAc,CAAA;AAAA,EAChH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAM,eAAA,CACJ,KAAA,EACA,OAAA,EACA,cAAA,EACkC;AAClC,IAAA,OAAO,IAAA,CAAK,OAAA,CAAiC,CAAA,uBAAA,EAA0B,KAAK,CAAA,CAAA,EAAI;AAAA,MAC9E,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,KAC9B,EAAG,QAAW,cAAc,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAM,kBAAA,CACJ,OAAA,EACA,SAAA,EAC2B;AAI3B,IAAA,MAAM,iBAAA,GAAoB,SAAA,IAAc,MAAM,IAAA,CAAK,YAAA,EAAa;AAChE,IAAA,OAAO,kBAAA,CAAuB,SAAS,iBAAiB,CAAA;AAAA,EAC1D;AAAA;AAAA;AAAA;AAKF;;;ACnjBO,IAAM,iBAAA,GAAN,cAAgC,UAAA,CAAW;AAAA,EAChD,YAAY,MAAA,EAA0B;AACpC,IAAA,KAAA,CAAM,MAAM,CAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyBA,MAAM,aAAA,CAAc,OAAA,EAA+B,cAAA,EAA2D;AAC5G,IAAA,OAAO,IAAA,CAAK,QAAyB,kBAAA,EAAoB;AAAA,MACvD,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,KAC9B,EAAG,QAAW,cAAc,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,UAAA,CAAW,UAAA,EAAoB,cAAA,EAA2D;AAC9F,IAAA,IAAI;AAEF,MAAA,OAAO,MAAM,IAAA,CAAK,OAAA;AAAA,QAChB,CAAA,6BAAA,EAAgC,kBAAA,CAAmB,UAAU,CAAC,CAAA,CAAA;AAAA,QAC9D,KAAA,CAAA;AAAA,QAAW,KAAA,CAAA;AAAA,QAAW;AAAA,OACxB;AAAA,IACF,SAAS,KAAA,EAAO;AAEd,MAAA,IAAI,iBAAiB,WAAA,KAAgB,KAAA,CAAM,eAAe,GAAA,IAAO,KAAA,CAAM,SAAS,WAAA,CAAA,EAAc;AAC5F,QAAA,MAAM,IAAI,WAAA,CAAY,mBAAA,EAAqB,WAAA,EAAa,GAAG,CAAA;AAAA,MAC7D;AACA,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,aAAA,CACJ,SAAA,EACA,OAAA,EACA,cAAA,EAC0B;AAC1B,IAAA,OAAO,IAAA,CAAK,OAAA,CAAyB,CAAA,iBAAA,EAAoB,SAAS,CAAA,CAAA,EAAI;AAAA,MACpE,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,KAC9B,EAAG,QAAW,cAAc,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBA,MAAM,kBAAA,CACJ,UAAA,EACA,aAAA,EACA,cAAA,EAC0B;AAC1B,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,IAAA,CAAK,UAAA,CAAW,UAAA,EAAY,cAAc,CAAA;AAAA,IACzD,SAAS,KAAA,EAAO;AAEd,MAAA,IAAI,KAAA,YAAiB,WAAA,IAAe,KAAA,CAAM,IAAA,KAAS,WAAA,EAAa;AAC9D,QAAA,OAAO,MAAM,IAAA,CAAK,aAAA,CAAc,aAAA,EAAe,cAAc,CAAA;AAAA,MAC/D;AACA,MAAA,MAAM,KAAA;AAAA,IACR;AAAA,EACF;AAEF;;;AC7IO,IAAM,UAAA,GAAa;AAAA;AAAA,EAExB,mBAAA,EAAqB,CAAC,OAAA,EAAiB,UAAA,MAAqC;AAAA,IAC1E,IAAA,EAAM,sBAAA;AAAA,IACN,OAAA,EAAS,oCAAA;AAAA,IACT,QAAA,EAAU,EAAE,OAAA,EAAS,WAAA,EAAa,UAAA;AAAW,GAC/C,CAAA;AAAA,EACA,0BAA0B,OAAoB;AAAA,IAC5C,IAAA,EAAM,4BAAA;AAAA,IACN,OAAA,EAAS;AAAA,GACX,CAAA;AAAA,EACA,gCAAgC,OAAoB;AAAA,IAClD,IAAA,EAAM,kCAAA;AAAA,IACN,OAAA,EAAS;AAAA,GACX,CAAA;AAAA,EACA,wBAAwB,OAAoB;AAAA,IAC1C,IAAA,EAAM,yBAAA;AAAA,IACN,OAAA,EAAS;AAAA,GACX,CAAA;AAAA;AAAA,EAGA,mBAAmB,OAAoB;AAAA,IACrC,IAAA,EAAM,qBAAA;AAAA,IACN,OAAA,EAAS;AAAA,GACX,CAAA;AAAA,EACA,kBAAkB,OAAoB;AAAA,IACpC,IAAA,EAAM,wBAAA;AAAA,IACN,OAAA,EAAS;AAAA,GACX,CAAA;AAAA,EACA,gBAAgB,OAAoB;AAAA,IAClC,IAAA,EAAM,sBAAA;AAAA,IACN,OAAA,EAAS;AAAA,GACX,CAAA;AAAA,EACA,kBAAkB,OAAoB;AAAA,IACpC,IAAA,EAAM,oBAAA;AAAA,IACN,OAAA,EAAS;AAAA,GACX,CAAA;AAAA,EACA,kBAAkB,OAAoB;AAAA,IACpC,IAAA,EAAM,oBAAA;AAAA,IACN,OAAA,EAAS;AAAA,GACX,CAAA;AAAA;AAAA,EAGA,mBAAmB,OAAoB;AAAA,IACrC,IAAA,EAAM,2BAAA;AAAA,IACN,OAAA,EAAS;AAAA,GACX,CAAA;AAAA,EACA,eAAe,OAAoB;AAAA,IACjC,IAAA,EAAM,wBAAA;AAAA,IACN,OAAA,EAAS;AAAA,GACX,CAAA;AAAA,EACA,aAAa,OAAoB;AAAA,IAC/B,IAAA,EAAM,qBAAA;AAAA,IACN,OAAA,EAAS;AAAA,GACX,CAAA;AAAA;AAAA,EAGA,qBAAA,EAAuB,CAAC,MAAA,EAAgB,QAAA,EAAkB,SAAA,MAAoC;AAAA,IAC5F,IAAA,EAAM,yBAAA;AAAA,IACN,OAAA,EAAS,iDAAA;AAAA,IACT,QAAA,EAAU,EAAE,MAAA,EAAQ,QAAA,EAAU,SAAA;AAAU,GAC1C,CAAA;AAAA,EACA,yBAAA,EAA2B,CAAC,MAAA,EAAgB,QAAA,EAAkB,SAAA,MAAoC;AAAA,IAChG,IAAA,EAAM,6BAAA;AAAA,IACN,OAAA,EAAS,qDAAA;AAAA,IACT,QAAA,EAAU,EAAE,MAAA,EAAQ,QAAA,EAAU,SAAA;AAAU,GAC1C,CAAA;AAAA,EACA,8BAA8B,OAAoB;AAAA,IAChD,IAAA,EAAM,gCAAA;AAAA,IACN,OAAA,EAAS;AAAA,GACX,CAAA;AAAA,EACA,uBAAuB,OAAoB;AAAA,IACzC,IAAA,EAAM,6BAAA;AAAA,IACN,OAAA,EAAS;AAAA,GACX;AACF;;;AC2DO,IAAM,sBAAA,GAAwC;AAAA,EACnD,GAAA,EAAK,CAAA;AAAA,EACL,GAAA,EAAK,GAAA;AAAA,EACL,GAAA,EAAK,IAAA;AAAA,EACL,GAAA,EAAK,IAAA;AAAA,EACL,GAAA,EAAK,IAAA;AAAA,EACL,GAAA,EAAK,KAAA;AAAA,EACL,GAAA,EAAK,IAAA;AAAA,EACL,GAAA,EAAK,IAAA;AAAA,EACL,GAAA,EAAK,KAAA;AAAA,EACL,GAAA,EAAK,GAAA;AAAA,EACL,GAAA,EAAK,KAAA;AAAA,EACL,GAAA,EAAK;AACP;;;AC7GO,IAAM,mBAAN,MAAuB;AAAA,EAS5B,YAAY,MAAA,EAAsB;AAHlC,IAAA,IAAA,CAAQ,wBAAA,GAAoC,KAAA;AAC5C,IAAA,IAAA,CAAQ,oBAAA,GAAgC,KAAA;AAGtC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA,CAAO,MAAA,IAAU,mBAAA,EAAoB;AACnD,IAAA,MAAM,YAAA,GAAqC,MAAA,CAAO,YAAA,IAAgB,EAAC;AACnE,IAAA,IAAA,CAAK,MAAA,GAAS;AAAA,MACZ,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,MAAA,EAAQ,OAAO,MAAA,IAAU,EAAA;AAAA,MACzB,OAAA,EAAS,MAAA,CAAO,OAAA,IAAW,EAAC;AAAA,MAC5B,OAAA,EAAS,OAAO,OAAA,IAAW,GAAA;AAAA,MAC3B,OAAA,EAAS,OAAO,OAAA,IAAW,CAAA;AAAA,MAC3B,KAAA,EAAO,OAAO,KAAA,IAAS,KAAA;AAAA,MACvB,kBAAA,EAAoB,OAAO,kBAAA,KAAuB,KAAA;AAAA;AAAA,MAClD,QAAA,EAAU,OAAO,QAAA,IAAY,MAAA;AAAA,MAC7B,aAAa,MAAA,CAAO,WAAA;AAAA,MACpB,YAAA;AAAA,MACA,QAAQ,IAAA,CAAK;AAAA,KACf;AAEA,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,iBAAA,CAAkB;AAAA,MACrC,OAAA,EAAS,KAAK,MAAA,CAAO,OAAA;AAAA,MACrB,QAAA,EAAU,KAAK,MAAA,CAAO,QAAA;AAAA,MACtB,MAAA,EAAQ,KAAK,MAAA,CAAO,MAAA;AAAA,MACpB,OAAA,EAAS,KAAK,MAAA,CAAO,OAAA;AAAA,MACrB,OAAA,EAAS,KAAK,MAAA,CAAO,OAAA;AAAA,MACrB,KAAA,EAAO,KAAK,MAAA,CAAO,KAAA;AAAA,MACnB,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,WAAA,EAAa,KAAK,MAAA,CAAO;AAAA,KAC1B,CAAA;AAED,IAAA,IAAA,CAAK,UAAA,GAAa,IAAI,iBAAA,CAAkB;AAAA,MACtC,OAAA,EAAS,KAAK,MAAA,CAAO,OAAA;AAAA,MACrB,QAAA,EAAU,KAAK,MAAA,CAAO,QAAA;AAAA,MACtB,MAAA,EAAQ,KAAK,MAAA,CAAO,MAAA;AAAA,MACpB,OAAA,EAAS,KAAK,MAAA,CAAO,OAAA;AAAA,MACrB,OAAA,EAAS,KAAK,MAAA,CAAO,OAAA;AAAA,MACrB,KAAA,EAAO,KAAK,MAAA,CAAO,KAAA;AAAA,MACnB,YAAA;AAAA,MACA,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,WAAA,EAAa,KAAK,MAAA,CAAO;AAAA,KAC1B,CAAA;AAED,IAAA,IAAA,CAAK,aAAA,GAAgB,sBAAA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,oBAAA,GAA0C;AACxC,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EACd;AAAA;AAAA,EAGA,oBAAA,GAA0C;AACxC,IAAA,OAAO,IAAA,CAAK,UAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwCA,MAAM,oBAAA,CACJ,OAAA,EACA,cAAA,EAC2C;AAC3C,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAG3B,IAAA,IAAA,CAAK,4BAA4B,OAAO,CAAA;AAExC,IAAA,IAAI,eAAA,GAA+C,IAAA;AACnD,IAAA,IAAI,gBAAA;AAEJ,IAAA,IAAI;AACF,MAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,QAAA,IAAA,CAAK,OAAO,KAAA,CAAM,oCAAA,EAAsC,EAAE,UAAA,EAAY,OAAA,CAAQ,YAAY,CAAA;AAAA,MAC5F;AAIA,MAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,QAAA,gBAAA,GAAmB,MAAM,IAAA,CAAK,2BAAA;AAAA,UAC5B,OAAA,CAAQ,UAAA;AAAA,UACR,OAAA,CAAQ,UAAA;AAAA,UACR,cAAA;AAAA,UACA,OAAA,CAAQ,SAAA;AAAA,UACR;AAAA,YACE,WAAW,OAAA,CAAQ,QAAA;AAAA,YACnB,OAAO,OAAA,CAAQ,YAAA;AAAA,YACf,OAAO,OAAA,CAAQ,WAAA;AAAA,YACf,eAAe,OAAA,CAAQ;AAAA,WACzB;AAAA,UACA;AAAA,SACF;AACA,QAAA,eAAA,GAAA,CAAmB,gBAAA,IAAoB,IAAA,CAAK,2BAAA,CAA4B,gBAAA,EAAkB,OAAA,CAAQ,SAAS,CAAA,KACtG,MAAM,IAAA,CAAK,SAAA,CAAU,QAAA,CAAS;AAAA,UAC7B,YAAY,OAAA,CAAQ,SAAA;AAAA,UACpB,SAAS,OAAA,CAAQ,UAAA;AAAA,UACjB,UAAA,EAAY,cAAA;AAAA,UACZ,oBAAoB,OAAA,CAAQ;AAAA,WAC3B,cAAc,CAAA;AAAA,MACvB,CAAA,MAAO;AACL,QAAA,eAAA,GAAkB,MAAM,IAAA,CAAK,SAAA,CAAU,QAAA,CAAS;AAAA,UAC9C,YAAY,OAAA,CAAQ,SAAA;AAAA,UACpB,SAAS,OAAA,CAAQ,UAAA;AAAA,UACjB,UAAA,EAAY,cAAA;AAAA,UACZ,oBAAoB,OAAA,CAAQ;AAAA,WAC3B,cAAc,CAAA;AAAA,MACnB;AAIA,MAAA,MAAM,sBAAA,GAAyB,IAAA,CAAK,yBAAA,CAA0B,eAAA,EAAiB,gBAAgB,CAAA;AAE/F,MAAA,IAAI,sBAAA,CAAuB,SAAS,CAAA,EAAG;AACrC,QAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,UAAA,IAAA,CAAK,OAAO,KAAA,CAAM,mCAAA,EAAqC,EAAE,YAAA,EAAc,wBAAwB,CAAA;AAAA,QACjG;AAGA,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,KAAA;AAAA,UACT,WAAA,EAAa,eAAA;AAAA,UACb,OAAA,EAAS,IAAA;AAAA,UACT,WAAA,EAAa,KAAA;AAAA,UACb,WAAA,EAAa,KAAA;AAAA,UACb,GAAG,IAAA,CAAK,eAAA,CAAgB,sBAAA,EAAwB,WAAW,gBAAgB;AAAA,SAC7E;AAAA,MACF;AAGA,MAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,UAAA,CAAW,aAAA,CAAc;AAAA,QAClD,aAAa,OAAA,CAAQ,UAAA;AAAA,QACrB,WAAA,EAAa,QAAQ,UAAA,IAAc,YAAA;AAAA,QACnC,eAAA,EAAiB,QAAA;AAAA,QACjB,WAAW,OAAA,CAAQ,QAAA;AAAA,QACnB,eAAe,OAAA,CAAQ,YAAA;AAAA,QACvB,sBAAsB,OAAA,CAAQ,WAAA;AAAA,QAC9B,eAAe,OAAA,CAAQ,WAAA;AAAA,QACvB,qBAAqB,OAAA,CAAQ,OAAA;AAAA,QAC7B,oBAAA,EAAsB,gBAAgB,QAAA,CAAS,WAAA;AAAA;AAAA,QAG/C,QAAA,EAAU,GAAG,eAAA,CAAgB,QAAA,CAAS,IAAI,CAAA,EAAA,EAAK,eAAA,CAAgB,SAAS,OAAO,CAAA,CAAA;AAAA,QAC/E,mBAAA,EAAqB,eAAA,CAAgB,YAAA,GAAe,WAAA,GAAc,eAAA;AAAA;AAAA,QAGlE,UAAA,EAAY;AAAA,SACX,cAAc,CAAA;AAGjB,MAAA,MAAM,WAAA,GAAc,eAAA,CAAgB,YAAA,EAAc,WAAA,IAAe,KAAA;AACjE,MAAA,MAAM,WAAA,GAAc,eAAA,CAAgB,YAAA,EAAc,6BAAA,IAAiC,KAAA;AAEnF,MAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,oCAAA,EAAsC;AAAA,UACtD,OAAA,EAAS,IAAA;AAAA,UACT,WAAA;AAAA,UACA;AAAA,SACD,CAAA;AAAA,MACH;AAEA,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,IAAA;AAAA,QACT,WAAA,EAAa,eAAA;AAAA,QACb,OAAA;AAAA,QACA,WAAA;AAAA,QACA,WAAA;AAAA,QACA,GAAG,IAAA,CAAK,eAAA,CAAgB,EAAC,EAAG,WAAW,gBAAgB;AAAA,OACzD;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,kCAAA,EAAoC;AAAA,UACpD,IAAA,EAAM,KAAA,YAAiB,WAAA,GAAc,KAAA,CAAM,IAAA,GAAO,MAAA;AAAA,UAClD,OAAA,EAAS,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU;AAAA,SACnD,CAAA;AAAA,MACH;AAIA,MAAA,IAAI,KAAA,YAAiB,WAAA,IAAe,KAAA,CAAM,IAAA,KAAS,mBAAA,EAAqB;AACtE,QAAA,MAAM,KAAA;AAAA,MACR;AAEA,MAAA,MAAM,IAAI,eAAA;AAAA,QACR,kCAAA;AAAA,QACA,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,MAAA;AAAA,QACzC,kBAAkB,yBAAA,GAA4B;AAAA,OAChD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcQ,yBAAA,CACN,iBACA,gBAAA,EACe;AACf,IAAA,MAAM,eAA8B,EAAC;AAGrC,IAAA,IAAI,gBAAgB,UAAA,EAAY;AAC9B,MAAA,YAAA,CAAa,IAAA,CAAK,GAAI,eAAA,CAAgB,uBAAA,IAA2B,EAAG,CAAA;AAAA,IACtE;AAGA,IAAA,IAAI,CAAC,gBAAgB,YAAA,EAAc;AACjC,MAAA,IAAI,CAAC,YAAA,CAAa,IAAA,CAAK,OAAK,CAAA,CAAE,IAAA,KAAS,4BAA4B,CAAA,EAAG;AACpE,QAAA,YAAA,CAAa,IAAA,CAAK,UAAA,CAAW,wBAAA,EAA0B,CAAA;AAAA,MACzD;AAAA,IACF;AAIA,IAAA,MAAM,eAAe,eAAA,CAAgB,YAAA;AACrC,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,IAAI,YAAA,CAAa,uBAAuB,KAAA,EAAO;AAC7C,QAAA,YAAA,CAAa,IAAA,CAAK,UAAA,CAAW,8BAAA,EAAgC,CAAA;AAAA,MAC/D;AAGA,MAAA,IAAI,YAAA,CAAa,MAAA,KAAW,SAAA,IAAa,YAAA,CAAa,WAAW,YAAA,EAAc;AAC7E,QAAA,IAAI,CAAC,YAAA,CAAa,IAAA,CAAK,OAAK,CAAA,CAAE,IAAA,KAAS,sBAAsB,CAAA,EAAG;AAC9D,UAAA,YAAA,CAAa,IAAA,CAAK,WAAW,mBAAA,CAAoB,YAAA,CAAa,gBAAgB,EAAA,EAAI,YAAA,CAAa,WAAA,IAAe,EAAE,CAAC,CAAA;AAAA,QACnH;AAAA,MACF;AAGA,MAAA,IAAI,YAAA,CAAa,MAAA,KAAW,YAAA,IAAgB,YAAA,CAAa,uBAAuB,KAAA,EAAO;AACrF,QAAA,IAAI,CAAC,YAAA,CAAa,IAAA,CAAK,OAAK,CAAA,CAAE,IAAA,KAAS,yBAAyB,CAAA,EAAG;AACjE,UAAA,YAAA,CAAa,IAAA,CAAK,UAAA,CAAW,sBAAA,EAAwB,CAAA;AAAA,QACvD;AAAA,MACF;AAAA,IACF;AAGA,IAAA,IAAI,eAAA,CAAgB,qBAAqB,OAAA,EAAS;AAChD,MAAA,YAAA,CAAa,IAAA;AAAA,QACX,IAAI,eAAA,CAAgB,mBAAA,CAAoB,WAAW,EAAC,EAAG,IAAI,CAAA,CAAA,MAAM;AAAA,UAC/D,IAAA,EAAM,iCAAA;AAAA,UACN,OAAA,EAAS;AAAA,SACX,CAAE;AAAA,OACJ;AAAA,IACF;AAGA,IAAA,IAAI,eAAA,CAAgB,eAAe,UAAA,EAAY;AAC7C,MAAA,IAAI,CAAC,YAAA,CAAa,IAAA,CAAK,OAAK,CAAA,CAAE,IAAA,KAAS,qBAAqB,CAAA,EAAG;AAC7D,QAAA,YAAA,CAAa,IAAA,CAAK,UAAA,CAAW,iBAAA,EAAmB,CAAA;AAAA,MAClD;AAAA,IACF;AAGA,IAAA,IAAI,gBAAA,EAAkB;AACpB,MAAA,IAAI,CAAC,iBAAiB,KAAA,EAAO;AAC3B,QAAA,YAAA,CAAa,IAAA,CAAK,UAAA,CAAW,iBAAA,EAAmB,CAAA;AAAA,MAClD;AACA,MAAA,IAAI,gBAAA,CAAiB,MAAM,UAAA,EAAY;AACrC,QAAA,YAAA,CAAa,KAAK,GAAI,gBAAA,CAAiB,IAAA,CAAK,wBAAA,IAA4B,EAAG,CAAA;AAAA,MAC7E;AAAA,IAKF;AAGA,IAAA,IAAI,eAAA,CAAgB,YAAA,IAAgB,CAAC,gBAAA,EAAkB;AACrD,MAAA,YAAA,CAAa,IAAA,CAAK,UAAA,CAAW,WAAA,EAAa,CAAA;AAAA,IAC5C;AAEA,IAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,IAAA,OAAO,YAAA,CAAa,OAAO,CAAA,CAAA,KAAK;AAC9B,MAAA,IAAI,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,IAAI,GAAG,OAAO,KAAA;AAC7B,MAAA,IAAA,CAAK,GAAA,CAAI,EAAE,IAAI,CAAA;AACf,MAAA,OAAO,IAAA;AAAA,IACT,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,4BAA4B,OAAA,EAAgD;AAClF,IAAA,MAAM,SAAmB,EAAC;AAE1B,IAAA,IAAI,CAAC,OAAA,CAAQ,UAAA,EAAY,IAAA,EAAK,EAAG;AAC/B,MAAA,MAAA,CAAO,KAAK,wBAAwB,CAAA;AAAA,IACtC;AAEA,IAAA,IAAI,CAAC,OAAA,CAAQ,SAAA,EAAW,IAAA,EAAK,EAAG;AAC9B,MAAA,MAAA,CAAO,KAAK,uBAAuB,CAAA;AAAA,IACrC,WAAW,CAAC,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,SAAS,CAAA,EAAG;AAC7C,MAAA,MAAA,CAAO,KAAK,6BAA6B,CAAA;AAAA,IAC3C;AAEA,IAAA,IAAI,CAAC,OAAA,CAAQ,YAAA,EAAc,IAAA,EAAK,EAAG;AACjC,MAAA,MAAA,CAAO,KAAK,0BAA0B,CAAA;AAAA,IACxC,WAAW,CAAC,IAAA,CAAK,YAAA,CAAa,OAAA,CAAQ,YAAY,CAAA,EAAG;AACnD,MAAA,MAAA,CAAO,KAAK,gCAAgC,CAAA;AAAA,IAC9C;AAEA,IAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,EAAU,IAAA,EAAK,EAAG;AAC7B,MAAA,MAAA,CAAO,KAAK,sBAAsB,CAAA;AAAA,IACpC;AAEA,IAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,MAAA,MAAM,IAAI,gBAAgB,CAAA,8BAAA,EAAiC,MAAA,CAAO,KAAK,IAAI,CAAC,IAAI,MAAM,CAAA;AAAA,IACxF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,UAAU,EAAA,EAAqB;AAErC,IAAA,MAAM,SAAA,GAAY,6FAAA;AAElB,IAAA,MAAM,SAAA,GAAY,kMAAA;AAElB,IAAA,OAAO,UAAU,IAAA,CAAK,EAAE,CAAA,IAAK,SAAA,CAAU,KAAK,EAAE,CAAA;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAa,KAAA,EAAwB;AAC3C,IAAA,MAAM,UAAA,GAAa,4BAAA;AACnB,IAAA,OAAO,UAAA,CAAW,KAAK,KAAK,CAAA;AAAA,EAC9B;AAAA,EAEQ,qBAAqB,OAAA,EAAyC;AACpE,IAAA,MAAM,SAAmB,EAAC;AAE1B,IAAA,IAAI,CAAC,OAAA,CAAQ,UAAA,EAAY,IAAA,EAAK,EAAG;AAC/B,MAAA,MAAA,CAAO,KAAK,wBAAwB,CAAA;AAAA,IACtC;AAEA,IAAA,IAAI,CAAC,OAAA,CAAQ,SAAA,EAAW,IAAA,EAAK,EAAG;AAC9B,MAAA,MAAA,CAAO,KAAK,uBAAuB,CAAA;AAAA,IACrC,WAAW,CAAC,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,SAAS,CAAA,EAAG;AAC7C,MAAA,MAAA,CAAO,KAAK,6BAA6B,CAAA;AAAA,IAC3C;AAEA,IAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,MAAA,MAAM,IAAI,gBAAgB,CAAA,uBAAA,EAA0B,MAAA,CAAO,KAAK,IAAI,CAAC,IAAI,MAAM,CAAA;AAAA,IACjF;AAAA,EACF;AAAA,EAEQ,2BAA2B,OAAA,EAA+C;AAChF,IAAA,MAAM,SAAmB,EAAC;AAE1B,IAAA,IAAI,CAAC,OAAA,CAAQ,UAAA,EAAY,IAAA,EAAK,EAAG;AAC/B,MAAA,MAAA,CAAO,KAAK,wBAAwB,CAAA;AAAA,IACtC;AAEA,IAAA,IAAI,CAAC,OAAA,CAAQ,SAAA,EAAW,IAAA,EAAK,EAAG;AAC9B,MAAA,MAAA,CAAO,KAAK,uBAAuB,CAAA;AAAA,IACrC,WAAW,CAAC,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,SAAS,CAAA,EAAG;AAC7C,MAAA,MAAA,CAAO,KAAK,6BAA6B,CAAA;AAAA,IAC3C;AAEA,IAAA,IAAI,OAAA,CAAQ,UAAU,CAAA,EAAG;AACvB,MAAA,MAAA,CAAO,KAAK,+BAA+B,CAAA;AAAA,IAC7C;AAEA,IAAA,IAAI,CAAC,OAAA,CAAQ,QAAA,EAAU,IAAA,EAAK,EAAG;AAC7B,MAAA,MAAA,CAAO,KAAK,sBAAsB,CAAA;AAAA,IACpC;AAEA,IAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,MAAA,MAAM,IAAI,gBAAgB,CAAA,6BAAA,EAAgC,MAAA,CAAO,KAAK,IAAI,CAAC,IAAI,MAAM,CAAA;AAAA,IACvF;AAAA,EACF;AAAA,EAEQ,qBAAqB,OAAA,EAAyC;AACpE,IAAA,MAAM,SAAmB,EAAC;AAE1B,IAAA,IAAI,CAAC,OAAA,CAAQ,UAAA,EAAY,IAAA,EAAK,EAAG;AAC/B,MAAA,MAAA,CAAO,KAAK,wBAAwB,CAAA;AAAA,IACtC;AAEA,IAAA,IAAI,CAAC,OAAA,CAAQ,SAAA,EAAW,IAAA,EAAK,EAAG;AAC9B,MAAA,MAAA,CAAO,KAAK,uBAAuB,CAAA;AAAA,IACrC,WAAW,CAAC,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,SAAS,CAAA,EAAG;AAC7C,MAAA,MAAA,CAAO,KAAK,6BAA6B,CAAA;AAAA,IAC3C;AAEA,IAAA,IAAI,CAAC,OAAA,CAAQ,SAAA,EAAW,IAAA,EAAK,EAAG;AAC9B,MAAA,MAAA,CAAO,KAAK,uBAAuB,CAAA;AAAA,IACrC;AAEA,IAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,MAAA,MAAM,IAAI,gBAAgB,CAAA,uBAAA,EAA0B,MAAA,CAAO,KAAK,IAAI,CAAC,IAAI,MAAM,CAAA;AAAA,IACjF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA6BA,MAAM,aAAA,CACJ,OAAA,EACA,cAAA,EACoC;AACpC,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAE3B,IAAA,IAAA,CAAK,qBAAqB,OAAO,CAAA;AAEjC,IAAA,IAAI;AACF,MAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,QAAA,IAAA,CAAK,OAAO,KAAA,CAAM,6BAAA,EAA+B,EAAE,UAAA,EAAY,OAAA,CAAQ,YAAY,CAAA;AAAA,MACrF;AAKA,MAAA,IAAI,gBAAA;AACJ,MAAA,IAAI,eAAA;AACJ,MAAA,IAAI,aAAA;AAEJ,MAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,QAAA,CAAC,gBAAA,EAAkB,aAAa,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,UACpD,IAAA,CAAK,2BAAA;AAAA,YACH,OAAA,CAAQ,UAAA;AAAA,YAAY,OAAA,CAAQ,UAAA;AAAA,YAAY,OAAA;AAAA,YAAS,OAAA,CAAQ,SAAA;AAAA,YACzD,KAAA,CAAA;AAAA,YAAW;AAAA,WACb;AAAA,UACA,IAAA,CAAK,WAAW,UAAA,CAAW,OAAA,CAAQ,YAAY,cAAc,CAAA,CAAE,KAAA,CAAM,MAAM,IAAI;AAAA,SAChF,CAAA;AACD,QAAA,eAAA,GAAA,CAAmB,gBAAA,IAAoB,IAAA,CAAK,2BAAA,CAA4B,gBAAA,EAAkB,OAAA,CAAQ,SAAS,CAAA,KACtG,MAAM,IAAA,CAAK,SAAA,CAAU,QAAA,CAAS;AAAA,UAC7B,YAAY,OAAA,CAAQ,SAAA;AAAA,UACpB,SAAS,OAAA,CAAQ,UAAA;AAAA,UACjB,UAAA,EAAY,OAAA;AAAA,UACZ,oBAAoB,OAAA,CAAQ;AAAA,WAC3B,cAAc,CAAA;AAAA,MACvB,CAAA,MAAO;AACL,QAAA,GAAG,eAAA,EAAiB,aAAa,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,UACrD,OAAA,CAAQ,QAAQ,KAAA,CAAS,CAAA;AAAA,UACzB,IAAA,CAAK,UAAU,QAAA,CAAS;AAAA,YACtB,YAAY,OAAA,CAAQ,SAAA;AAAA,YACpB,SAAS,OAAA,CAAQ,UAAA;AAAA,YACjB,UAAA,EAAY,OAAA;AAAA,YACZ,oBAAoB,OAAA,CAAQ;AAAA,aAC3B,cAAc,CAAA;AAAA,UACjB,IAAA,CAAK,WAAW,UAAA,CAAW,OAAA,CAAQ,YAAY,cAAc,CAAA,CAAE,KAAA,CAAM,MAAM,IAAI;AAAA,SAChF,CAAA;AAAA,MACH;AAGA,MAAA,MAAM,iBAAA,GAAoB,IAAA,CAAK,eAAA,CAAgB,eAAA,EAAiB,eAAe,gBAAgB,CAAA;AAC/F,MAAA,MAAM,YACJ,CAAC,eAAA,CAAgB,YAAA,IACjB,eAAA,CAAgB,cAChB,CAAC,CAAE,gBAAA,EAAkB,IAAA,EAAM,cAC3B,gBAAA,EAAkB,KAAA,KAAU,KAAA,IAC3B,eAAA,CAAgB,gBAAgB,CAAC,gBAAA;AAEpC,MAAA,IAAI,SAAA,IAAa,CAAC,aAAA,EAAe;AAE/B,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,KAAA;AAAA,UACT,WAAA,EAAa,eAAA;AAAA,UACb,OAAA,EAAS,IAAA;AAAA,UACT,cAAA,EAAgB,KAAA;AAAA,UAChB,GAAG,IAAA,CAAK,eAAA,CAAgB,iBAAA,EAAmB,WAAW,gBAAgB;AAAA,SACxE;AAAA,MACF;AAGA,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI,aAAA,EAAe;AACjB,QAAA,OAAA,GAAU,aAAA;AAGV,QAAA,IAAI,CAAC,aAAa,IAAA,CAAK,mBAAA,CAAoB,SAAS,eAAA,CAAgB,QAAA,CAAS,IAAI,CAAA,EAAG;AAClF,UAAA,OAAA,GAAU,MAAM,IAAA,CAAK,UAAA,CAAW,aAAA,CAAc,QAAQ,EAAA,EAAI;AAAA,YACxD,sBAAA,EAAA,iBAAwB,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,YAC/C,QAAA,EAAU,GAAG,eAAA,CAAgB,QAAA,CAAS,IAAI,CAAA,EAAA,EAAK,eAAA,CAAgB,SAAS,OAAO,CAAA,CAAA;AAAA,YAC/E,mBAAA,EAAqB,eAAA,CAAgB,YAAA,GAAe,WAAA,GAAc;AAAA,aACjE,cAAc,CAAA;AAAA,QACnB;AAAA,MACF,CAAA,MAAO;AAEL,QAAA,IAAI,IAAA,CAAK,MAAA,CAAO,kBAAA,IAAsB,IAAA,CAAK,OAAO,KAAA,EAAO;AACvD,UAAA,IAAA,CAAK,MAAA,CAAO,KAAK,0CAA0C,CAAA;AAAA,QAC7D;AACA,QAAA,OAAA,GAAU,MAAM,IAAA,CAAK,oBAAA,CAAqB,OAAA,CAAQ,YAAY,eAAe,CAAA;AAAA,MAC/E;AAEA,MAAA,MAAM,cAAA,GACJ,gBAAgB,UAAA,KAAe,MAAA,IAC/B,gBAAgB,UAAA,KAAe,UAAA,IAC9B,gBAAA,EAAkB,IAAA,EAAM,iBAAA,KAAsB,IAAA;AAEjD,MAAA,MAAM,oBAAA,GAAuB,SAAA,IAAa,OAAA,CAAQ,eAAA,KAAoB,WAAA,GAClE,IAAA,CAAK,eAAA,CAAgB,eAAA,EAAiB,OAAA,EAAS,gBAAgB,CAAA,GAC/D,EAAC;AACL,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,CAAC,SAAA,IAAa,OAAA,CAAQ,eAAA,KAAoB,WAAA;AAAA,QACnD,WAAA,EAAa,eAAA;AAAA,QACb,OAAA;AAAA,QACA,cAAA;AAAA,QACA,GAAG,IAAA,CAAK,eAAA,CAAgB,oBAAA,EAAsB,WAAW,gBAAgB;AAAA,OAC3E;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,IAAI,eAAA,CAAgB,2BAAA,EAA6B,iBAAiB,KAAA,GAAQ,KAAA,CAAM,UAAU,MAAS,CAAA;AAAA,IAC3G;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgCA,MAAM,mBAAA,CACJ,OAAA,EACA,cAAA,EAC0C;AAC1C,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAE3B,IAAA,IAAA,CAAK,2BAA2B,OAAO,CAAA;AAEvC,IAAA,IAAI;AACF,MAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,mCAAA,EAAqC;AAAA,UACrD,YAAY,OAAA,CAAQ,UAAA;AAAA,UACpB,QAAQ,OAAA,CAAQ,MAAA;AAAA,UAChB,UAAU,OAAA,CAAQ;AAAA,SACnB,CAAA;AAAA,MACH;AAKA,MAAA,IAAI,gBAAA;AACJ,MAAA,IAAI,eAAA;AACJ,MAAA,IAAI,aAAA;AAEJ,MAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,QAAA,CAAC,gBAAA,EAAkB,aAAa,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,UACpD,IAAA,CAAK,2BAAA;AAAA,YACH,OAAA,CAAQ,UAAA;AAAA,YAAY,OAAA,CAAQ,UAAA;AAAA,YAAY,aAAA;AAAA,YAAe,OAAA,CAAQ,SAAA;AAAA,YAC/D,KAAA,CAAA;AAAA,YAAW;AAAA,WACb;AAAA,UACA,IAAA,CAAK,WAAW,UAAA,CAAW,OAAA,CAAQ,YAAY,cAAc,CAAA,CAAE,KAAA,CAAM,MAAM,IAAI;AAAA,SAChF,CAAA;AACD,QAAA,eAAA,GAAA,CAAmB,gBAAA,IAAoB,IAAA,CAAK,2BAAA,CAA4B,gBAAA,EAAkB,OAAA,CAAQ,SAAS,CAAA,KACtG,MAAM,IAAA,CAAK,SAAA,CAAU,QAAA,CAAS;AAAA,UAC7B,YAAY,OAAA,CAAQ,SAAA;AAAA,UACpB,SAAS,OAAA,CAAQ,UAAA;AAAA,UACjB,UAAA,EAAY,aAAA;AAAA,UACZ,oBAAoB,OAAA,CAAQ;AAAA,WAC3B,cAAc,CAAA;AAAA,MACvB,CAAA,MAAO;AACL,QAAA,GAAG,eAAA,EAAiB,aAAa,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,UACrD,OAAA,CAAQ,QAAQ,KAAA,CAAS,CAAA;AAAA,UACzB,IAAA,CAAK,UAAU,QAAA,CAAS;AAAA,YACtB,YAAY,OAAA,CAAQ,SAAA;AAAA,YACpB,SAAS,OAAA,CAAQ,UAAA;AAAA,YACjB,UAAA,EAAY,aAAA;AAAA,YACZ,oBAAoB,OAAA,CAAQ;AAAA,aAC3B,cAAc,CAAA;AAAA,UACjB,IAAA,CAAK,WAAW,UAAA,CAAW,OAAA,CAAQ,YAAY,cAAc,CAAA,CAAE,KAAA,CAAM,MAAM,IAAI;AAAA,SAChF,CAAA;AAAA,MACH;AAGA,MAAA,MAAM,aACJ,CAAC,eAAA,CAAgB,YAAA,IACjB,eAAA,CAAgB,cAChB,CAAC,CAAE,gBAAA,EAAkB,IAAA,EAAM,cAC3B,gBAAA,EAAkB,KAAA,KAAU,KAAA,IAC3B,eAAA,CAAgB,gBAAgB,CAAC,gBAAA;AAEpC,MAAA,IAAI,UAAA,IAAc,CAAC,aAAA,EAAe;AAEhC,QAAA,MAAM,kBAAkB,IAAA,CAAK,0BAAA;AAAA,UAC3B,eAAA;AAAA,UACA,EAAE,KAAA,EAAO,CAAA,EAAG,KAAA,EAAO,KAAA,EAAO,OAAA,EAAS,EAAC,EAAG,OAAA,EAAS,KAAA,EAAO,oBAAA,EAAsB,KAAA,EAAM;AAAA,UACnF,IAAA;AAAA,UACA;AAAA,SACF;AACA,QAAA,OAAO;AAAA,UACL,OAAA,EAAS,KAAA;AAAA,UACT,WAAA,EAAa,eAAA;AAAA,UACb,OAAA,EAAS,IAAA;AAAA,UACT,eAAA,EAAiB,EAAE,KAAA,EAAO,CAAA,EAAG,KAAA,EAAO,KAAA,EAAgB,OAAA,EAAS,EAAC,EAAG,OAAA,EAAS,KAAA,EAAO,oBAAA,EAAsB,KAAA,EAAM;AAAA,UAC7G,gBAAA,EAAkB,KAAA;AAAA,UAClB,GAAG,IAAA,CAAK,eAAA,CAAgB,eAAA,EAAiB,WAAW,gBAAgB;AAAA,SACtE;AAAA,MACF;AAEA,MAAA,IAAI,CAAC,aAAA,EAAe;AAClB,QAAA,MAAM,IAAI,eAAA,CAAgB,4BAAA,EAA8B,OAAA,CAAQ,UAAU,CAAA;AAAA,MAC5E;AACA,MAAA,MAAM,OAAA,GAAU,aAAA;AAGhB,MAAA,MAAM,kBAAkB,IAAA,CAAK,wBAAA;AAAA,QAC3B,OAAA,CAAQ,MAAA;AAAA,QACR,OAAA,CAAQ,QAAA;AAAA,QACR,eAAA;AAAA,QACA,OAAA;AAAA,QACA;AAAA,OACF;AAGA,MAAA,MAAM,sBAAsB,IAAA,CAAK,uBAAA;AAAA,QAC/B,OAAA,CAAQ,MAAA;AAAA,QACR,OAAA,CAAQ,QAAA;AAAA,QACR,eAAA,CAAgB;AAAA,OAClB;AAGA,MAAA,MAAM,YACJ,CAAC,UAAA,IACD,uBACA,eAAA,CAAgB,OAAA,IAChB,QAAQ,eAAA,KAAoB,WAAA;AAE9B,MAAA,MAAM,eAAe,IAAA,CAAK,0BAAA;AAAA,QACxB,eAAA;AAAA,QAAiB,eAAA;AAAA,QAAiB,mBAAA;AAAA,QAAqB;AAAA,OACzD;AACA,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,SAAA;AAAA,QACT,WAAA,EAAa,eAAA;AAAA,QACb,OAAA;AAAA,QACA,eAAA;AAAA,QACA,kBAAkB,eAAA,CAAgB,oBAAA;AAAA,QAClC,GAAG,IAAA,CAAK,eAAA,CAAgB,YAAA,EAAc,WAAW,gBAAgB;AAAA,OACnE;AAAA,IACF,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,IAAI,eAAA,CAAgB,iCAAA,EAAmC,iBAAiB,KAAA,GAAQ,KAAA,CAAM,UAAU,MAAS,CAAA;AAAA,IACjH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,WAAA,CAAY,OAAA,EAAmC,cAAA,EAAqE;AACxH,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAE3B,IAAA,IAAA,CAAK,qBAAqB,OAAO,CAAA;AAIjC,IAAA,IAAI,gBAAA;AACJ,IAAA,IAAI,eAAA;AAEJ,IAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,MAAA,gBAAA,GAAmB,MAAM,IAAA,CAAK,2BAAA;AAAA,QAC5B,OAAA,CAAQ,UAAA;AAAA,QAAY,OAAA,CAAQ,UAAA;AAAA,QAAY,OAAA,CAAQ,SAAA;AAAA,QAAW,OAAA,CAAQ,SAAA;AAAA,QACnE,MAAA;AAAA,QAAW;AAAA,OACb;AACA,MAAA,eAAA,GAAA,CAAmB,gBAAA,IAAoB,IAAA,CAAK,2BAAA,CAA4B,gBAAA,EAAkB,OAAA,CAAQ,SAAS,CAAA,KACtG,MAAM,IAAA,CAAK,SAAA,CAAU,QAAA,CAAS;AAAA,QAC7B,YAAY,OAAA,CAAQ,SAAA;AAAA,QACpB,SAAS,OAAA,CAAQ,UAAA;AAAA,QACjB,YAAY,OAAA,CAAQ,SAAA;AAAA,QACpB,oBAAoB,OAAA,CAAQ;AAAA,SAC3B,cAAc,CAAA;AAAA,IACvB,CAAA,MAAO;AACL,MAAA,eAAA,GAAkB,MAAM,IAAA,CAAK,SAAA,CAAU,QAAA,CAAS;AAAA,QAC9C,YAAY,OAAA,CAAQ,SAAA;AAAA,QACpB,SAAS,OAAA,CAAQ,UAAA;AAAA,QACjB,YAAY,OAAA,CAAQ,SAAA;AAAA,QACpB,oBAAoB,OAAA,CAAQ;AAAA,SAC3B,cAAc,CAAA;AAAA,IACnB;AAGA,IAAA,IAAI,IAAA,CAAK,OAAO,kBAAA,EAAoB;AAClC,MAAA,IAAI;AACF,QAAA,MAAM,UAAU,MAAM,IAAA,CAAK,WAAW,UAAA,CAAW,OAAA,CAAQ,YAAY,cAAc,CAAA;AACnF,QAAA,MAAM,IAAA,CAAK,UAAA,CAAW,aAAA,CAAc,OAAA,CAAQ,EAAA,EAAI;AAAA,UAC9C,sBAAA,EAAA,iBAAwB,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,WAC9C,cAAc,CAAA;AAAA,MACnB,SAAS,KAAA,EAAO;AAEd,QAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,UAAA,IAAA,CAAK,MAAA,CAAO,KAAK,6BAA6B,CAAA;AAAA,QAChD;AAAA,MACF;AAAA,IACF;AAEA,IAAA,MAAM,iBAAA,GAAoB,mBACrB,CAAC,gBAAA,CAAiB,SAAS,gBAAA,CAAiB,IAAA,EAAM,eAAe,IAAA,GAClE,KAAA;AAGJ,IAAA,MAAM,yBAAwC,CAAC,GAAI,eAAA,CAAgB,uBAAA,IAA2B,EAAG,CAAA;AACjG,IAAA,IAAI,gBAAA,EAAkB;AACpB,MAAA,IAAI,CAAC,iBAAiB,KAAA,EAAO;AAC3B,QAAA,sBAAA,CAAuB,IAAA,CAAK,UAAA,CAAW,iBAAA,EAAmB,CAAA;AAAA,MAC5D;AACA,MAAA,IAAI,gBAAA,CAAiB,MAAM,UAAA,EAAY;AACrC,QAAA,sBAAA,CAAuB,KAAK,GAAI,gBAAA,CAAiB,IAAA,CAAK,wBAAA,IAA4B,EAAG,CAAA;AAAA,MACvF;AAAA,IACF;AAGA,IAAA,MAAM,UAAA,GAAa,eAAA,CAAgB,YAAA,IAAgB,CAAC,gBAAA;AACpD,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,sBAAA,CAAuB,IAAA,CAAK,UAAA,CAAW,WAAA,EAAa,CAAA;AAAA,IACtD;AAEA,IAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,IAAA,MAAM,iBAAA,GAAoB,sBAAA,CAAuB,MAAA,CAAO,CAAA,CAAA,KAAK;AAC3D,MAAA,IAAI,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,IAAI,GAAG,OAAO,KAAA;AAC7B,MAAA,IAAA,CAAK,GAAA,CAAI,EAAE,IAAI,CAAA;AACf,MAAA,OAAO,IAAA;AAAA,IACT,CAAC,CAAA;AAED,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,gBAAgB,YAAA,IAAgB,CAAC,gBAAgB,UAAA,IAAc,CAAC,qBAAqB,CAAC,UAAA;AAAA,MAC/F,WAAA,EAAa,eAAA;AAAA,MACb,GAAG,IAAA,CAAK,eAAA,CAAgB,iBAAA,EAAmB,WAAW,gBAAgB;AAAA,KACxE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAA,CACN,UAAA,EACA,SAAA,EACA,gBAAA,EACA;AACA,IAAA,OAAO;AAAA,MACL,YAAA,EAAc,UAAA,CAAW,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,OAAO,CAAA;AAAA,MAC3C,sBAAA,EAAwB,UAAA;AAAA,MACxB,cAAA,EAAgB,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAAA,MAC7B,oBAAA,EAAsB;AAAA,KACxB;AAAA,EACF;AAAA,EAEQ,mBAAA,CAAoB,SAA0B,OAAA,EAA0B;AAE9E,IAAA,OAAO,CAAC,OAAA,CAAQ,QAAA,IAAY,CAAC,OAAA,CAAQ,QAAA,CAAS,SAAS,OAAO,CAAA;AAAA,EAChE;AAAA,EAEA,MAAc,oBAAA,CACZ,UAAA,EACA,eAAA,EACA,YAAA,EAM0B;AAE1B,IAAA,IAAI,CAAC,YAAA,EAAc,KAAA,IAAS,CAAC,cAAc,QAAA,EAAU;AACnD,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA;AAAA,QACV;AAAA,OAEF;AAAA,IACF;AAEA,IAAA,OAAO,IAAA,CAAK,WAAW,aAAA,CAAc;AAAA,MACnC,WAAA,EAAa,UAAA;AAAA,MACb,WAAA,EAAa,YAAA;AAAA,MACb,eAAA,EAAiB,QAAA;AAAA,MACjB,SAAA,EAAW,cAAc,QAAA,IAAY,MAAA;AAAA,MACrC,aAAA,EAAe,cAAc,KAAA,IAAS,EAAA;AAAA,MACtC,oBAAA,EAAsB,cAAc,KAAA,IAAS,MAAA;AAAA,MAC7C,aAAA,EAAe,cAAc,WAAA,IAAe,MAAA;AAAA,MAC5C,QAAA,EAAU,GAAG,eAAA,CAAgB,QAAA,CAAS,IAAI,CAAA,EAAA,EAAK,eAAA,CAAgB,SAAS,OAAO,CAAA,CAAA;AAAA,MAC/E,mBAAA,EAAqB,eAAA,CAAgB,YAAA,GAAe,WAAA,GAAc,eAAA;AAAA,MAClE,oBAAA,EAAsB,gBAAgB,QAAA,CAAS,WAAA;AAAA,MAC/C,UAAA,EAAY;AAAA,KACb,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,2BAAA,CACZ,UAAA,EACA,QACA,SAAA,EACA,SAAA,EACA,cAMA,cAAA,EACiD;AACjD,IAAA,IAAI,CAAC,YAAY,OAAO,MAAA;AAExB,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,KAAK,SAAA,CAAU,kBAAA;AAAA,QAC1B,UAAA;AAAA,QACA,MAAA;AAAA,QACA,SAAA;AAAA,QACA,SAAA;AAAA,QACA,YAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,IAAA,CAAK,MAAA,CAAO,KAAK,uDAAA,EAAyD;AAAA,QACxE,KAAA,EAAO,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU;AAAA,OAC7C,CAAA;AACD,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,2BAAA,CAA4B,IAAgC,SAAA,EAAgD;AAClH,IAAA,MAAM,MAAM,EAAA,CAAG,QAAA;AACf,IAAA,MAAM,OAAO,EAAA,CAAG,IAAA;AAChB,IAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAElB,IAAA,OAAO;AAAA,MACL,UAAA,EAAY,GAAG,UAAA,IAAc,SAAA;AAAA,MAC7B,QAAA,EAAU;AAAA,QACR,OAAA,EAAS,KAAK,OAAA,IAAW,EAAA;AAAA,QACzB,WAAA,EAAa,KAAK,WAAA,IAAe,EAAA;AAAA,QACjC,IAAA,EAAM,KAAK,IAAA,IAAQ,EAAA;AAAA,QACnB,MAAA,EAAQ,KAAK,MAAA,IAAU,EAAA;AAAA,QACvB,WAAA,EAAa,EAAA;AAAA,QACb,QAAA,EAAU,KAAK,QAAA,IAAY,CAAA;AAAA,QAC3B,SAAA,EAAW,KAAK,SAAA,IAAa,CAAA;AAAA,QAC7B,QAAA,EAAU,EAAA;AAAA,QACV,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,UAAU,IAAA,CAAK,QAAA;AAAA,QACf,QAAQ,IAAA,CAAK,MAAA;AAAA,QACb,UAAA,EAAY,KAAK,UAAA,IAAc,KAAA;AAAA,QAC/B,aAAA,EAAe,IAAA,CAAK,MAAA,IAAU,IAAA,CAAK,YAAY,IAAA,CAAK;AAAA,OACtD;AAAA,MACA,YAAA,EAAc,EAAA,CAAG,YAAA,IAAgB,CAAC,IAAA,CAAK,UAAA;AAAA,MACvC,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,YAAY,IAAA,CAAK,KAAA;AAAA,MACjB,YAAY,IAAA,CAAK,KAAA;AAAA,MACjB,cAAc,EAAC;AAAA,MACf,yBAAyB,IAAA,CAAK,UAAA,IAAc,KAAK,wBAAA,GAC7C,IAAA,CAAK,2BACL,EAAC;AAAA,MACL,cAAc,EAAA,CAAG,YAAA;AAAA,MACjB,qBAAqB,EAAA,CAAG,mBAAA;AAAA,MACxB,SAAA,EAAW,GAAG,SAAA,IAAa,EAAA;AAAA,MAC3B,cAAc,EAAA,CAAG;AAAA,KACnB;AAAA,EACF;AAAA,EAEQ,wBAAA,CACN,MAAA,EACA,QAAA,EACA,eAAA,EACA,SACA,gBAAA,EACuB;AACvB,IAAA,IAAI,CAAC,IAAA,CAAK,wBAAA,IAA4B,CAAC,KAAK,oBAAA,EAAsB;AAChE,MAAA,IAAA,CAAK,oBAAA,GAAuB,IAAA;AAC5B,MAAA,IAAA,CAAK,MAAA,CAAO,IAAA;AAAA,QACV;AAAA,OAEF;AAAA,IACF;AAEA,IAAA,IAAI,SAAA,GAAY,CAAA;AAChB,IAAA,MAAM,oBAAmC,EAAC;AAG1C,IAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,cAAA,CAAe,MAAA,EAAQ,QAAQ,CAAA;AAC7D,IAAA,IAAI,mBAAmB,GAAA,EAAO;AAC5B,MAAA,SAAA,IAAa,EAAA;AACb,MAAA,iBAAA,CAAkB,KAAK,UAAA,CAAW,qBAAA,CAAsB,gBAAA,EAAkB,QAAA,EAAU,GAAK,CAAC,CAAA;AAAA,IAC5F,CAAA,MAAA,IAAW,mBAAmB,GAAA,EAAM;AAClC,MAAA,SAAA,IAAa,EAAA;AACb,MAAA,iBAAA,CAAkB,KAAK,UAAA,CAAW,yBAAA,CAA0B,gBAAA,EAAkB,QAAA,EAAU,GAAI,CAAC,CAAA;AAAA,IAC/F;AAGA,IAAA,SAAA,IAAa,gBAAgB,UAAA,GAAa,GAAA;AAC1C,IAAA,IAAI,eAAA,CAAgB,UAAA,KAAe,MAAA,IAAU,eAAA,CAAgB,eAAe,UAAA,EAAY;AACtF,MAAA,iBAAA,CAAkB,IAAA,CAAK,UAAA,CAAW,gBAAA,EAAkB,CAAA;AAAA,IACtD;AAGA,IAAA,SAAA,IAAa,QAAQ,UAAA,GAAa,GAAA;AAClC,IAAA,IAAI,OAAA,CAAQ,aAAA,KAAkB,MAAA,IAAU,OAAA,CAAQ,kBAAkB,UAAA,EAAY;AAC5E,MAAA,iBAAA,CAAkB,IAAA,CAAK,UAAA,CAAW,gBAAA,EAAkB,CAAA;AAAA,IACtD;AAGA,IAAA,IAAI,eAAA,CAAgB,QAAA,CAAS,MAAA,IAAU,eAAA,CAAgB,SAAS,QAAA,EAAU;AACxE,MAAA,SAAA,IAAa,EAAA;AACb,MAAA,iBAAA,CAAkB,IAAA,CAAK,UAAA,CAAW,qBAAA,EAAuB,CAAA;AAAA,IAC3D;AAGA,IAAA,IAAI,OAAA,CAAQ,oBAAoB,WAAA,EAAa;AAC3C,MAAA,SAAA,IAAa,EAAA;AACb,MAAA,iBAAA,CAAkB,IAAA,CAAK,UAAA,CAAW,gBAAA,EAAkB,CAAA;AAAA,IACtD;AAGA,IAAA,IAAI,gBAAA,EAAkB;AACpB,MAAA,IAAI,gBAAA,CAAiB,MAAM,iBAAA,EAAmB;AAC5C,QAAA,SAAA,IAAa,EAAA;AACb,QAAA,iBAAA,CAAkB,IAAA,CAAK,UAAA,CAAW,aAAA,EAAe,CAAA;AAAA,MACnD;AACA,MAAA,IAAI,gBAAA,CAAiB,MAAM,KAAA,EAAO;AAChC,QAAA,SAAA,IAAa,gBAAA,CAAiB,KAAK,KAAA,GAAQ,GAAA;AAAA,MAC7C;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,IAAA,CAAK,GAAA,CAAI,SAAA,EAAW,GAAG,CAAA;AAAA,MAC9B,KAAA,EAAO,IAAA,CAAK,YAAA,CAAa,SAAS,CAAA;AAAA,MAClC,OAAA,EAAS,iBAAA,CAAkB,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,OAAO,CAAA;AAAA,MAC7C,iBAAA,EAAmB,iBAAA;AAAA,MACnB,SAAS,SAAA,GAAY,EAAA;AAAA,MACrB,oBAAA,EAAsB,SAAA,IAAa,EAAA,IAAM,SAAA,GAAY;AAAA,KACvD;AAAA,EACF;AAAA,EAEQ,uBAAA,CACN,MAAA,EACA,QAAA,EACA,YAAA,EACS;AACT,IAAA,IAAI,CAAC,YAAA,IAAgB,CAAC,YAAA,CAAa,sBAAA,EAAwB;AACzD,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,cAAA,CAAe,MAAA,EAAQ,QAAQ,CAAA;AAC7D,IAAA,OAAO,oBAAoB,YAAA,CAAa,sBAAA;AAAA,EAC1C;AAAA,EAEQ,cAAA,CAAe,QAAgB,QAAA,EAA0B;AAC/D,IAAA,MAAM,OAAO,IAAA,CAAK,aAAA,CAAc,QAAA,CAAS,WAAA,EAAa,CAAA,IAAK,CAAA;AAC3D,IAAA,OAAO,MAAA,GAAS,IAAA;AAAA,EAClB;AAAA,EAEQ,aAAa,KAAA,EAAuD;AAC1E,IAAA,IAAI,KAAA,IAAS,IAAI,OAAO,UAAA;AACxB,IAAA,IAAI,KAAA,IAAS,IAAI,OAAO,MAAA;AACxB,IAAA,IAAI,KAAA,IAAS,IAAI,OAAO,QAAA;AACxB,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEQ,eAAA,CACN,eAAA,EACA,OAAA,EACA,gBAAA,EACe;AACf,IAAA,MAAM,UAAyB,EAAC;AAEhC,IAAA,IAAI,gBAAgB,UAAA,EAAY;AAC9B,MAAA,OAAA,CAAQ,IAAA,CAAK,GAAI,eAAA,CAAgB,uBAAA,IAA2B,EAAG,CAAA;AAAA,IACjE;AAEA,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,IAAI,OAAA,CAAQ,oBAAoB,WAAA,EAAa;AAC3C,QAAA,OAAA,CAAQ,IAAA,CAAK,UAAA,CAAW,gBAAA,EAAkB,CAAA;AAAA,MAC5C;AAEA,MAAA,IAAI,QAAQ,aAAA,EAAe;AACzB,QAAA,OAAA,CAAQ,IAAA,CAAK,UAAA,CAAW,cAAA,EAAgB,CAAA;AAAA,MAC1C;AAAA,IACF;AAEA,IAAA,IAAI,gBAAA,EAAkB;AACpB,MAAA,IAAI,CAAC,iBAAiB,KAAA,EAAO;AAC3B,QAAA,OAAA,CAAQ,IAAA,CAAK,UAAA,CAAW,iBAAA,EAAmB,CAAA;AAAA,MAC7C;AACA,MAAA,IAAI,gBAAA,CAAiB,MAAM,UAAA,EAAY;AACrC,QAAA,OAAA,CAAQ,KAAK,GAAI,gBAAA,CAAiB,IAAA,CAAK,wBAAA,IAA4B,EAAG,CAAA;AAAA,MACxE;AAAA,IACF;AAGA,IAAA,IAAI,eAAA,CAAgB,YAAA,IAAgB,CAAC,gBAAA,EAAkB;AACrD,MAAA,OAAA,CAAQ,IAAA,CAAK,UAAA,CAAW,WAAA,EAAa,CAAA;AAAA,IACvC;AAEA,IAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,IAAA,OAAO,OAAA,CAAQ,OAAO,CAAA,CAAA,KAAK;AACzB,MAAA,IAAI,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,IAAI,GAAG,OAAO,KAAA;AAC7B,MAAA,IAAA,CAAK,GAAA,CAAI,EAAE,IAAI,CAAA;AACf,MAAA,OAAO,IAAA;AAAA,IACT,CAAC,CAAA;AAAA,EACH;AAAA,EAEQ,0BAAA,CACN,eAAA,EACA,eAAA,EACA,mBAAA,EACA,gBAAA,EACe;AACf,IAAA,MAAM,UAAyB,EAAC;AAEhC,IAAA,IAAI,CAAC,gBAAgB,YAAA,EAAc;AACjC,MAAA,OAAA,CAAQ,IAAA,CAAK,UAAA,CAAW,wBAAA,EAA0B,CAAA;AAAA,IACpD;AAEA,IAAA,IAAI,CAAC,mBAAA,EAAqB;AACxB,MAAA,OAAA,CAAQ,IAAA,CAAK,UAAA,CAAW,4BAAA,EAA8B,CAAA;AAAA,IACxD;AAEA,IAAA,IAAI,CAAC,gBAAgB,OAAA,EAAS;AAC5B,MAAA,OAAA,CAAQ,IAAA,CAAK,GAAI,eAAA,CAAgB,iBAAA,IAAqB,EAAG,CAAA;AAAA,IAC3D;AAEA,IAAA,IAAI,gBAAA,EAAkB;AACpB,MAAA,IAAI,CAAC,iBAAiB,KAAA,EAAO;AAC3B,QAAA,OAAA,CAAQ,IAAA,CAAK,UAAA,CAAW,iBAAA,EAAmB,CAAA;AAAA,MAC7C;AACA,MAAA,IAAI,gBAAA,CAAiB,MAAM,UAAA,EAAY;AACrC,QAAA,OAAA,CAAQ,KAAK,GAAI,gBAAA,CAAiB,IAAA,CAAK,wBAAA,IAA4B,EAAG,CAAA;AAAA,MACxE;AAAA,IACF;AAGA,IAAA,IAAI,eAAA,CAAgB,YAAA,IAAgB,CAAC,gBAAA,EAAkB;AACrD,MAAA,OAAA,CAAQ,IAAA,CAAK,UAAA,CAAW,WAAA,EAAa,CAAA;AAAA,IACvC;AAEA,IAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,IAAA,OAAO,OAAA,CAAQ,OAAO,CAAA,CAAA,KAAK;AACzB,MAAA,IAAI,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,IAAI,GAAG,OAAO,KAAA;AAC7B,MAAA,IAAA,CAAK,GAAA,CAAI,EAAE,IAAI,CAAA;AACf,MAAA,OAAO,IAAA;AAAA,IACT,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuCA,MAAM,uBAAA,CACJ,KAAA,EACA,cAAA,EAC0C;AAC1C,IAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,MAAA,IAAA,CAAK,OAAO,KAAA,CAAM,wCAAA,EAA0C,EAAE,UAAA,EAAY,KAAA,CAAM,YAAY,CAAA;AAAA,IAC9F;AAGA,IAAA,IAAA,CAAK,6BAA6B,KAAK,CAAA;AAGvC,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI;AACF,MAAA,OAAA,GAAU,MAAM,IAAA,CAAK,UAAA,CAAW,UAAA,CAAW,KAAA,CAAM,YAAY,cAAc,CAAA;AAAA,IAC7E,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,QAAA,IAAA,CAAK,OAAO,IAAA,CAAK,4BAAA,EAA8B,EAAE,UAAA,EAAY,KAAA,CAAM,YAAY,CAAA;AAAA,MACjF;AAAA,IACF;AAGA,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,IAAS,OAAA,EAAS,oBAAA;AACtC,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,IAAS,OAAA,EAAS,aAAA;AAGtC,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,SAAA,CAAU,qBAAA,CAAsB;AAAA,MACxD,SAAS,KAAA,CAAM,UAAA;AAAA,MACf,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,QAAQ,KAAA,CAAM,MAAA;AAAA,MACd,KAAA;AAAA,MACA,KAAA;AAAA,MACA,cAAc,KAAA,CAAM;AAAA,OACnB,cAAc,CAAA;AAEjB,IAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,0BAAA,EAA4B;AAAA,QAC5C,SAAA,EAAW,OAAO,OAAA,CAAQ,EAAA;AAAA,QAC1B,SAAS,KAAA,CAAM,OAAA;AAAA,QACf,WAAW,MAAA,CAAO;AAAA,OACnB,CAAA;AAAA,IACH;AAEA,IAAA,OAAO;AAAA,MACL,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,WAAW,MAAA,CAAO,UAAA;AAAA,MAClB,aAAa,MAAA,CAAO,YAAA;AAAA,MACpB;AAAA,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,kBAAA,CAAmB,SAAA,EAAmB,cAAA,EAA2D;AACrG,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,kBAAA,CAAmB,SAAA,EAAW,cAAc,CAAA;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBA,MAAM,oBAAA,CACJ,OAAA,EACA,UAAA,EACA,cAAA,EACsC;AACtC,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,oBAAA,CAAqB,OAAA,EAAS,YAAY,cAAc,CAAA;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,qBAAA,CAAsB,SAAA,EAAmB,cAAA,EAAgD;AAC7F,IAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,MAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,6BAAA,EAA+B,EAAE,WAAW,CAAA;AAAA,IAChE;AACA,IAAA,MAAM,IAAA,CAAK,SAAA,CAAU,qBAAA,CAAsB,SAAA,EAAW,cAAc,CAAA;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,qBAAA,CACJ,SAAA,EACA,OAAA,EACA,cAAA,EACe;AACf,IAAA,IAAI,IAAA,CAAK,OAAO,KAAA,EAAO;AACrB,MAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,4BAAA,EAA8B,EAAE,WAAW,CAAA;AAAA,IAC/D;AACA,IAAA,MAAM,IAAA,CAAK,SAAA,CAAU,qBAAA,CAAsB,SAAA,EAAW,SAAS,cAAc,CAAA;AAAA,EAC/E;AAAA;AAAA;AAAA;AAAA,EAKQ,6BAA6B,KAAA,EAA6C;AAChF,IAAA,MAAM,SAAmB,EAAC;AAE1B,IAAA,IAAI,CAAC,KAAA,CAAM,UAAA,EAAY,IAAA,EAAK,EAAG;AAC7B,MAAA,MAAA,CAAO,KAAK,wBAAwB,CAAA;AAAA,IACtC;AAEA,IAAA,IAAI,CAAC,MAAM,OAAA,EAAS;AAClB,MAAA,MAAA,CAAO,KAAK,qBAAqB,CAAA;AAAA,IACnC;AAEA,IAAA,IAAI,CAAC,KAAA,CAAM,MAAA,EAAQ,IAAA,EAAK,EAAG;AACzB,MAAA,MAAA,CAAO,KAAK,kDAAkD,CAAA;AAAA,IAChE;AAGA,IAAA,IAAI,KAAA,CAAM,OAAA,KAAY,KAAA,IAAS,CAAC,MAAM,KAAA,EAAO;AAC3C,MAAA,MAAA,CAAO,KAAK,mCAAmC,CAAA;AAAA,IACjD;AAEA,IAAA,IAAI,KAAA,CAAM,OAAA,KAAY,OAAA,IAAW,CAAC,MAAM,KAAA,EAAO;AAC7C,MAAA,MAAA,CAAO,KAAK,qCAAqC,CAAA;AAAA,IACnD;AAEA,IAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,MAAA,MAAM,IAAI,gBAAgB,CAAA,0BAAA,EAA6B,MAAA,CAAO,KAAK,IAAI,CAAC,IAAI,MAAM,CAAA;AAAA,IACpF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4BA,oBAAoB,KAAA,EAA4B;AAC9C,IAAA,IAAA,CAAK,gBAAgB,EAAE,GAAG,IAAA,CAAK,aAAA,EAAe,GAAG,KAAA,EAAM;AACvD,IAAA,IAAA,CAAK,wBAAA,GAA2B,IAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAA,GAA4C;AAC1C,IAAA,OAAO,EAAE,GAAG,IAAA,CAAK,aAAA,EAAc;AAAA,EACjC;AAEF;;;ACj3CA,SAAS,cAAA,CACP,MAAA,EACA,GAAA,EACA,KAAA,EACM;AACN,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,MAAA,CAAO,GAAG,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,GAAI,KAAA,CAAM,IAAA,CAAK,GAAG,CAAA,GAAI,KAAA;AAAA,EACzD;AACF;AAGA,SAAS,eAAA,CACP,MAAA,EACA,MAAA,EACA,IAAA,EACM;AACN,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,IAAI,MAAA,CAAO,GAAG,CAAA,KAAM,MAAA,EAAW;AAC7B,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,MAAA,CAAO,GAAG,CAAA;AAAA,IAC1B;AAAA,EACF;AACF;AAaO,IAAM,SAAA,GAAN,cAAwB,UAAA,CAAW;AAAA,EAIxC,YAAY,MAAA,EAAyB;AAEnC,IAAA,MAAM,UAAA,GAA+B;AAAA,MACnC,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,OAAA,EAAS,CAAA;AAAA;AAAA,MACT,OAAO,MAAA,CAAO,KAAA;AAAA,MACd,aAAa,MAAA,CAAO;AAAA,KACtB;AACA,IAAA,KAAA,CAAM,UAAU,CAAA;AAChB,IAAA,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AACrB,IAAA,IAAA,CAAK,qBAAqB,MAAA,CAAO,kBAAA;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,MAAA,EAAsB;AAC9B,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,GAAgC;AAC9B,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAA,GAAyC;AAC/C,IAAA,MAAM,UAAkC,EAAC;AACzC,IAAA,IAAI,KAAK,MAAA,EAAQ;AACf,MAAA,OAAA,CAAQ,WAAW,IAAI,IAAA,CAAK,MAAA;AAAA,IAC9B;AACA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiDA,MAAM,oBAAA,CACJ,OAAA,EACA,cAAA,EACuC;AAIvC,IAAA,OAAO,IAAA,CAAK,QAAsC,qBAAA,EAAuB;AAAA,MACvE,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA;AAAA,MAC5B,OAAA,EAAS,KAAK,cAAA;AAAe,KAC/B,EAAG,QAAW,cAAc,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,wCAAwC,OAAA,EAAmH;AAK/J,IAAA,OAAO,IAAA,CAAK,QAAyD,0BAAA,EAA4B;AAAA,MAC/F,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA;AAAA,MAC5B,OAAA,EAAS,KAAK,cAAA;AAAe,KAC9B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,uCAAA,CAAwC,OAAA,EAAyD,cAAA,EAA8E;AAQnL,IAAA,OAAO,IAAA,CAAK,QAA4C,yBAAA,EAA2B;AAAA,MACjF,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA;AAAA,MAC5B,OAAA,EAAS,KAAK,cAAA;AAAe,KAC/B,EAAG,QAAW,cAAc,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,2CAA2C,KAAA,EAA4D;AAC3G,IAAA,OAAO,KAAK,gBAAA,CAAqD,CAAA,wBAAA,EAA2B,kBAAA,CAAmB,KAAK,CAAC,CAAA,CAAA,EAAI;AAAA,MACvH,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS,KAAK,cAAA;AAAe,KAC9B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,uCAAuC,KAAA,EAAyE;AACpH,IAAA,OAAO,IAAA,CAAK,QAAyD,iCAAA,EAAmC;AAAA,MACtG,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,OAAO,CAAA;AAAA,MAC9B,OAAA,EAAS,KAAK,cAAA;AAAe,KAC9B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,kBAAkB,KAAA,EAA2C;AACjE,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,sBAAsB,IAAA,CAAK,gBAAA,CAAiB,EAAE,KAAA,EAAO,CAAC,CAAA,CAAA;AAAA,MACtD,EAAE,OAAA,EAAS,IAAA,CAAK,cAAA,EAAe;AAAE,KACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,oBAAA,CAAqB,KAAA,EAAe,YAAA,GAAe,KAAA,EAA+C;AACtG,IAAA,OAAO,IAAA,CAAK,QAAuC,6BAAA,EAA+B;AAAA,MAChF,MAAA,EAAQ,KAAA;AAAA,MACR,MAAM,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,aAAA,EAAe,cAAc,CAAA;AAAA,MAC3D,OAAA,EAAS,KAAK,cAAA;AAAe,KAC9B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkCA,MAAM,eACJ,OAAA,EACiC;AACjC,IAAA,MAAM,MAAA,GAAS;AAAA,MACb,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,QAAQ,OAAA,CAAQ;AAAA,KAClB;AAEA,IAAA,OAAO,IAAA,CAAK,gBAAA;AAAA,MACV,CAAA,0BAAA,EAA6B,IAAA,CAAK,gBAAA,CAAiB,MAAM,CAAC,CAAA,CAAA;AAAA,MAC1D;AAAA,QACE,MAAA,EAAQ,KAAA;AAAA,QACR,OAAA,EAAS,KAAK,cAAA;AAAe;AAC/B,KACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgCA,MAAM,kBAAA,CACJ,OAAA,EACA,cAAA,EACuC;AAEvC,IAAA,OAAO,IAAA,CAAK,QAAsC,oBAAA,EAAsB;AAAA,MACtE,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA;AAAA,MAC5B,OAAA,EAAS,KAAK,cAAA;AAAe,KAC/B,EAAG,QAAW,cAAc,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,cAAc,EAAA,EAAiC;AACnD,IAAA,OAAO,IAAA,CAAK,OAAA,CAAoB,CAAA,qBAAA,EAAwB,EAAE,CAAA,CAAE,CAAA;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,eAAA,CACJ,OAAA,EACA,UAAA,EACiC;AACjC,IAAA,MAAM,SAAkC,EAAC;AAEzC,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,cAAA,CAAe,MAAA,EAAQ,QAAA,EAAU,OAAA,CAAQ,MAAM,CAAA;AAC/C,MAAA,eAAA,CAAgB,MAAA,EAAQ,SAA+C,CAAC,QAAA,EAAU,YAAY,QAAA,EAAU,QAAA,EAAU,OAAO,CAAC,CAAA;AAAA,IAC5H;AAEA,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,IAAI,UAAA,CAAW,IAAA,EAAM,MAAA,CAAO,IAAA,GAAO,UAAA,CAAW,IAAA;AAC9C,MAAA,IAAI,UAAA,CAAW,SAAA,EAAW,MAAA,CAAO,KAAA,GAAQ,UAAA,CAAW,SAAA;AAAA,IACtD;AAEA,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,CAAA,oBAAA,EAAuB,IAAA,CAAK,gBAAA,CAAiB,MAAM,CAAC,CAAA,CAAA;AAAA,MACpD,EAAE,OAAA,EAAS,IAAA,CAAK,cAAA,EAAe;AAAE,KACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBA,MAAM,gBAAgB,OAAA,EAAgD;AACpE,IAAA,MAAM,IAAA,CAAK,QAAQ,oBAAA,EAAsB;AAAA,MACvC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA;AAAA,MAC5B,OAAA,EAAS,KAAK,cAAA;AAAe,KAC9B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,MAAM,2BACJ,OAAA,EACe;AACf,IAAA,MAAM,IAAA,CAAK,QAAQ,sBAAA,EAAwB;AAAA,MACzC,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA;AAAA,MAC5B,OAAA,EAAS,KAAK,cAAA;AAAe,KAC9B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,MAAM,qBAAqB,KAAA,EAA4C;AACrE,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,sBAAsB,KAAK,CAAA,CAAA;AAAA,MAC3B,EAAE,OAAA,EAAS,IAAA,CAAK,cAAA,EAAe;AAAE,KACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBA,MAAM,WAAA,CAAY,QAAA,EAAmB,MAAA,EAAuC;AAC1E,IAAA,MAAM,SAAkC,EAAC;AACzC,IAAA,IAAI,QAAA,SAAiB,QAAA,GAAW,QAAA;AAChC,IAAA,IAAI,MAAA,SAAe,MAAA,GAAS,MAAA;AAE5B,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,CAAA,oBAAA,EAAuB,IAAA,CAAK,gBAAA,CAAiB,MAAM,CAAC,CAAA;AAAA,KACtD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,SAAS,OAAA,EAAoC;AACjD,IAAA,OAAO,IAAA,CAAK,OAAA,CAAkB,CAAA,mBAAA,EAAsB,OAAO,CAAA,CAAE,CAAA;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAM,UAAA,CACJ,OAAA,EACA,UAAA,EAC+B;AAC/B,IAAA,MAAM,SAAkC,EAAC;AAEzC,IAAA,IAAI,OAAA,EAAS;AAEX,MAAA,cAAA,CAAe,MAAA,EAAQ,QAAA,EAAU,OAAA,CAAQ,MAAM,CAAA;AAC/C,MAAA,cAAA,CAAe,MAAA,EAAQ,YAAA,EAAc,OAAA,CAAQ,UAAU,CAAA;AACvD,MAAA,cAAA,CAAe,MAAA,EAAQ,cAAA,EAAgB,OAAA,CAAQ,YAAY,CAAA;AAC3D,MAAA,cAAA,CAAe,MAAA,EAAQ,QAAA,EAAU,OAAA,CAAQ,MAAM,CAAA;AAC/C,MAAA,cAAA,CAAe,MAAA,EAAQ,MAAA,EAAQ,OAAA,CAAQ,IAAI,CAAA;AAE3C,MAAA,eAAA,CAAgB,MAAA,EAAQ,SAA+C,CAAC,QAAA,EAAU,YAAY,QAAA,EAAU,SAAA,EAAW,OAAO,CAAC,CAAA;AAAA,IAC7H;AAEA,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,IAAI,UAAA,CAAW,IAAA,EAAM,MAAA,CAAO,IAAA,GAAO,UAAA,CAAW,IAAA;AAC9C,MAAA,IAAI,UAAA,CAAW,SAAA,EAAW,MAAA,CAAO,KAAA,GAAQ,UAAA,CAAW,SAAA;AAAA,IACtD;AAEA,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,CAAA,kBAAA,EAAqB,IAAA,CAAK,gBAAA,CAAiB,MAAM,CAAC,CAAA;AAAA,KACpD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA8BA,MAAM,WAAA,CAAY,OAAA,EAAiB,MAAA,EAA8C;AAC/E,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,CAAA,mBAAA,EAAsB,OAAO,CAAA,CAAA,EAAI;AAAA,MAClD,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA;AAAA,MAC3B,OAAA,EAAS,KAAK,cAAA;AAAe,KAC9B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,cAAA,GAA0C;AAC9C,IAAA,OAAO,IAAA,CAAK,QAAwB,yBAAyB,CAAA;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA2BA,MAAM,kBACJ,MAAA,EACyB;AACzB,IAAA,OAAO,IAAA,CAAK,QAAwB,yBAAA,EAA2B;AAAA,MAC7D,MAAA,EAAQ,KAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,MAAM;AAAA,KAC5B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAc,kBAAA,CACZ,IAAA,EACA,OAAA,GAAuB,EAAC,EACZ;AACZ,IAAA,IAAI,CAAC,KAAK,kBAAA,EAAoB;AAC5B,MAAA,MAAM,IAAI,eAAA;AAAA,QACR,gGAAA;AAAA,QACA,CAAC,oBAAoB;AAAA,OACvB;AAAA,IACF;AAEA,IAAA,OAAO,IAAA,CAAK,QAAW,IAAA,EAAM;AAAA,MAC3B,GAAG,OAAA;AAAA,MACH,OAAA,EAAS;AAAA,QACP,GAAG,KAAK,cAAA,EAAe;AAAA,QACvB,GAAI,OAAA,CAAQ;AAAA;AACd,KACF,EAAG,KAAK,kBAAkB,CAAA;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAM,oBAAA,CACJ,OAAA,EACA,UAAA,EACsC;AACtC,IAAA,MAAM,SAAkC,EAAC;AAEzC,IAAA,IAAI,OAAA,EAAS;AAEX,MAAA,IAAI,QAAQ,aAAA,EAAe;AACzB,QAAA,MAAA,CAAO,aAAA,GAAgB,KAAA,CAAM,OAAA,CAAQ,OAAA,CAAQ,aAAa,IACtD,OAAA,CAAQ,aAAA,GACR,CAAC,OAAA,CAAQ,aAAa,CAAA;AAAA,MAC5B;AACA,MAAA,IAAI,QAAQ,WAAA,EAAa;AACvB,QAAA,MAAA,CAAO,WAAA,GAAc,KAAA,CAAM,OAAA,CAAQ,OAAA,CAAQ,WAAW,IAClD,OAAA,CAAQ,WAAA,GACR,CAAC,OAAA,CAAQ,WAAW,CAAA;AAAA,MAC1B;AACA,MAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,QAAA,MAAA,CAAO,MAAA,GAAS,KAAA,CAAM,OAAA,CAAQ,OAAA,CAAQ,MAAM,IACxC,OAAA,CAAQ,MAAA,GACR,CAAC,OAAA,CAAQ,MAAM,CAAA;AAAA,MACrB;AAEA,MAAA,eAAA,CAAgB,QAAQ,OAAA,EAA+C;AAAA,QACrE,QAAA;AAAA,QAAU,QAAA;AAAA,QAAU,eAAA;AAAA,QAAiB,cAAA;AAAA,QAAgB,SAAA;AAAA,QAAW;AAAA,OACjE,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,eAAA,CAAgB,MAAA,EAAQ,UAAA,EAAY,CAAC,OAAA,EAAS,QAAQ,CAAC,CAAA;AAAA,IACzD;AAEA,IAAA,OAAO,IAAA,CAAK,kBAAA;AAAA,MACV,CAAA,+BAAA,EAAkC,IAAA,CAAK,gBAAA,CAAiB,MAAM,CAAC,CAAA;AAAA,KACjE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,mBAAmB,SAAA,EAA6C;AACpE,IAAA,OAAO,IAAA,CAAK,kBAAA;AAAA,MACV,mCAAmC,SAAS,CAAA;AAAA,KAC9C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA8BA,MAAM,sBACJ,OAAA,EAC0B;AAC1B,IAAA,OAAO,IAAA,CAAK,mBAAoC,kBAAA,EAAoB;AAAA,MAClE,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,KAC7B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAKF;;;ACzyBO,IAAM,yBAAA,GAA6D;AAAA,EACxE,oBAAA,EAAsB,oCAAA;AAAA,EACtB,oBAAA,EAAsB,8CAAA;AAAA,EACtB,iBAAA,EAAmB,uDAAA;AAAA,EACnB,mBAAA,EAAqB,yBAAA;AAAA,EACrB,sBAAA,EAAwB,+DAAA;AAAA,EACxB,oBAAA,EAAsB,6BAAA;AAAA,EACtB,iBAAA,EAAmB,qDAAA;AAAA,EACnB,qBAAA,EAAuB,iEAAA;AAAA,EACvB,YAAA,EAAc;AAChB;AAyvBO,SAAS,kCACd,KAAA,EAC0C;AAC1C,EAAA,OACE,OAAO,KAAA,KAAU,QAAA,IACjB,KAAA,KAAU,IAAA,IACT,MAA8B,KAAA,KAAU,sBAAA;AAE7C;;;AC7xBO,IAAM,SAAA,GAAN,cAAwB,UAAA,CAAW;AAAA,EACxC,YAAY,MAAA,EAAyB;AACnC,IAAA,MAAM,UAAA,GAA+B;AAAA,MACnC,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,QAAQ,MAAA,CAAO,MAAA;AAAA,MACf,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,OAAA,EAAS,CAAA;AAAA,MACT,OAAO,MAAA,CAAO,KAAA;AAAA,MACd,aAAa,MAAA,CAAO;AAAA,KACtB;AACA,IAAA,KAAA,CAAM,UAAU,CAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,4BAA4B,UAAA,EAAuD;AACvF,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,qCAAqC,UAAU,CAAA;AAAA,KACjD;AAAA,EACF;AAAA,EAEA,MAAM,eAAe,UAAA,EAAuD;AAC1E,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,qCAAqC,UAAU,CAAA,aAAA,CAAA;AAAA,MAC/C,EAAE,QAAQ,MAAA;AAAO,KACnB;AAAA,EACF;AAAA,EAEA,MAAM,cAAA,CAAe,UAAA,EAAoB,cAAA,EAA0D;AACjG,IAAA,OAAO,IAAA,CAAK,gBAAA;AAAA,MACV,qCAAqC,UAAU,CAAA,UAAA,CAAA;AAAA,MAC/C,EAAE,QAAQ,MAAA,EAAO;AAAA,MACjB,MAAA;AAAA,MACA,MAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAAA,EAEA,MAAM,gBAAA,CACJ,UAAA,EACA,KAAA,EACmC;AACnC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,qCAAqC,UAAU,CAAA,gBAAA,CAAA;AAAA,MAC/C;AAAA,QACE,MAAA,EAAQ,MAAA;AAAA,QACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,KAAK;AAAA;AAC5B,KACF;AAAA,EACF;AAAA,EAEA,MAAM,uBAAA,CACJ,UAAA,EACA,KAAA,EACoC;AACpC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,qCAAqC,UAAU,CAAA,mBAAA,CAAA;AAAA,MAC/C;AAAA,QACE,MAAA,EAAQ,MAAA;AAAA,QACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,KAAK;AAAA;AAC5B,KACF;AAAA,EACF;AAAA,EAEC,MAAM,qBAAqB,UAAA,EAA0D;AACpF,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,oCAAoC,UAAU,CAAA,UAAA;AAAA,KAChD;AAAA,EACF;AAAA,EAEA,MAAM,eAAA,CACJ,UAAA,EACA,cAAA,EACsB;AACtB,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,qCAAqC,UAAU,CAAA,cAAA,CAAA;AAAA,MAC/C,EAAE,QAAQ,KAAA,EAAM;AAAA,MAChB,MAAA;AAAA,MACA,EAAE,GAAG,cAAA,EAAgB,YAAA,EAAc,aAAA;AAAc,KACnD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAAA,GAAiC;AACrC,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,OAAA,CAA6B,mBAAmB,CAAA;AACvE,IAAA,OAAO,GAAA,CAAI,KAAA;AAAA,EACb;AAAA,EAEA,MAAM,eAAe,KAAA,EAAqD;AACxE,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,OAAA,CAAqC,mBAAA,EAAqB;AAAA,MAC/E,MAAA,EAAQ,KAAA;AAAA,MACR,MAAM,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,OAAO;AAAA,KACtC,CAAA;AACD,IAAA,OAAO,GAAA,CAAI,OAAA;AAAA,EACb;AAAA,EAEA,MAAM,YAAA,GAA4C;AAChD,IAAA,OAAO,KAAK,OAAA,CAA4B,2BAAA,EAA6B,EAAE,MAAA,EAAQ,QAAQ,CAAA;AAAA,EACzF;AAAA,EAEA,MAAM,mBAAmB,OAAA,EAA4D;AACnF,IAAA,MAAM,SAAkC,EAAC;AACzC,IAAA,IAAI,OAAA,EAAS,UAAA,EAAY,MAAA,CAAO,UAAA,GAAa,OAAA,CAAQ,UAAA;AACrD,IAAA,IAAI,OAAA,EAAS,SAAA,EAAW,MAAA,CAAO,SAAA,GAAY,OAAA,CAAQ,SAAA;AACnD,IAAA,IAAI,OAAA,EAAS,OAAA,EAAS,MAAA,CAAO,OAAA,GAAU,OAAA,CAAQ,OAAA;AAC/C,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,MACV,CAAA,sCAAA,EAAyC,IAAA,CAAK,gBAAA,CAAiB,MAAM,CAAC,CAAA;AAAA,KACxE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,uBAAA,GAAkD;AACtD,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,OAAA;AAAA,MACrB;AAAA,KACF;AACA,IAAA,OAAO,GAAA,CAAI,IAAA;AAAA,EACb;AAAA,EAEA,MAAM,mBAAA,GAA0D;AAC9D,IAAA,OAAO,IAAA,CAAK,QAAmC,8BAA8B,CAAA;AAAA,EAC/E;AAAA,EAEA,MAAM,iBAAiB,IAAA,EAAsC;AAC3D,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,OAAA;AAAA,MACrB,CAAA,6BAAA,EAAgC,kBAAA,CAAmB,IAAI,CAAC,CAAA;AAAA,KAC1D;AACA,IAAA,OAAO,GAAA,CAAI,cAAA;AAAA,EACb;AACF;;;AC/IA,SAAS,eAAe,KAAA,EAAyC;AAC/D,EAAA,IAAI,MAAM,EAAA,EAAI;AACZ,IAAA,OAAO,KAAA,CAAM,EAAA;AAAA,EACf;AACA,EAAA,IAAI,KAAA,CAAM,eAAe,sBAAA,EAAwB;AAC/C,IAAA,OAAO,MAAM,YAAA,EAAc,EAAA;AAAA,EAC7B;AACA,EAAA,OAAO,MAAA;AACT;AAEO,IAAM,iBAAN,MAAqB;AAAA,EAS1B,YAAY,MAAA,EAA8B;AAR1C,IAAA,IAAA,CAAQ,QAAA,uBAAe,GAAA,EAA6C;AACpE,IAAA,IAAA,CAAQ,cAAmC,EAAC;AAQ1C,IAAA,IAAA,CAAK,SAAS,MAAA,CAAO,MAAA;AACrB,IAAA,IAAA,CAAK,SAAA,GAAY,OAAO,SAAA,IAAa,GAAA;AACrC,IAAA,IAAA,CAAK,gBAAA,GAAmB,OAAO,gBAAA,IAAoB,IAAA;AACnD,IAAA,IAAA,CAAK,oBAAA,GAAuB,OAAO,oBAAA,IAAwB,IAAA;AAC3D,IAAA,IAAA,CAAK,UAAA,GAAa,MAAA,CAAO,UAAA,IAAc,IAAI,kBAAA,EAAmB;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA,EAKA,EAAA,CACE,WACA,OAAA,EACM;AACN,IAAA,MAAM,WAAW,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,SAAS,KAAK,EAAC;AAClD,IAAA,QAAA,CAAS,KAAK,OAAyC,CAAA;AACvD,IAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,SAAA,EAAW,QAAQ,CAAA;AACrC,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAA,EAAkC;AACtC,IAAA,IAAA,CAAK,WAAA,CAAY,KAAK,OAAO,CAAA;AAC7B,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAA,CAAe,IAAA,EAAc,SAAA,EAA0C;AAC3E,IAAA,MAAM,UAAU,MAAM,sBAAA,CAAuB,IAAA,EAAM,SAAA,EAAW,KAAK,MAAA,EAAQ;AAAA,MACzE,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,aAAa,IAAA,CAAK;AAAA,KACnB,CAAA;AACD,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,IAAI,eAAA,CAAgB,2BAAA,EAA6B,CAAC,WAAW,CAAC,CAAA;AAAA,IACtE;AAEA,IAAA,OAAO,IAAA,CAAK,iBAAiB,IAAI,CAAA;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAA,CAAO,IAAA,EAAc,SAAA,EAAkC;AAC3D,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,cAAA,CAAe,MAAM,SAAS,CAAA;AACvD,IAAA,MAAM,IAAA,CAAK,SAAS,KAAK,CAAA;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,IAAA,EAAqC;AACpD,IAAA,OAAO,IAAA,CAAK,iBAAiB,IAAI,CAAA;AAAA,EACnC;AAAA,EAEA,MAAc,iBAAiB,IAAA,EAAqC;AAClE,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC7B,IAAA,MAAM,OAAA,GAAU,eAAe,KAAK,CAAA;AAEpC,IAAA,IAAI,CAAC,KAAA,CAAM,UAAA,IAAc,CAAC,OAAA,IAAW,CAAC,MAAM,SAAA,EAAW;AACrD,MAAA,MAAM,IAAI,eAAA;AAAA,QACR,4EAAA;AAAA,QACA,CAAC,YAAA,EAAc,IAAA,EAAM,WAAW;AAAA,OAClC;AAAA,IACF;AAIA,IAAA,IAAI,IAAA,CAAK,YAAY,CAAA,EAAG;AACtB,MAAA,MAAM,YAAY,IAAI,IAAA,CAAK,KAAA,CAAM,SAAS,EAAE,OAAA,EAAQ;AACpD,MAAA,IAAI,IAAA,CAAK,IAAI,IAAA,CAAK,GAAA,KAAQ,SAAS,CAAA,GAAI,KAAK,SAAA,EAAW;AACrD,QAAA,MAAM,IAAI,eAAA;AAAA,UACR,CAAA,qDAAA,EAAwD,KAAK,SAAS,CAAA,GAAA,CAAA;AAAA,UACtE,CAAC,WAAW;AAAA,SACd;AAAA,MACF;AAAA,IACF;AAGA,IAAA,IAAI,KAAK,gBAAA,EAAkB;AACzB,MAAA,IAAI,MAAM,IAAA,CAAK,UAAA,CAAW,IAAA,CAAK,OAAO,CAAA,EAAG;AACvC,QAAA,MAAM,IAAI,eAAA;AAAA,UACR,4BAA4B,OAAO,CAAA,2BAAA,CAAA;AAAA,UACnC,CAAC,IAAI;AAAA,SACP;AAAA,MACF;AACA,MAAA,MAAM,IAAA,CAAK,UAAA,CAAW,IAAA,CAAK,OAAA,EAAS,KAAK,SAAS,CAAA;AAAA,IACpD;AAEA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA,EAEA,MAAc,SAAS,KAAA,EAAoC;AACzD,IAAA,MAAM,eAAe,IAAA,CAAK,QAAA,CAAS,IAAI,KAAA,CAAM,UAAU,KAAK,EAAC;AAC7D,IAAA,MAAM,cAAc,CAAC,GAAG,YAAA,EAAc,GAAG,KAAK,WAAW,CAAA;AAEzD,IAAA,KAAA,MAAW,WAAW,WAAA,EAAa;AACjC,MAAA,MAAO,QAA8B,KAAK,CAAA;AAAA,IAC5C;AAAA,EACF;AACF;;;ACrHO,SAAS,wBAAwB,OAAA,EAAmC;AACzE,EAAA,MAAM,OAAA,GAAU,aAAa,OAAO,CAAA;AACpC,EAAA,MAAM,eAAA,GAAkB,QAAQ,eAAA,IAAmB,qBAAA;AAEnD,EAAA,OAAO,OACL,GAAA,EACA,GAAA,EACA,IAAA,KACG;AACH,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,OAAO,GAAA,CAAI,IAAA,KAAS,QAAA,GAAW,IAAI,IAAA,GAAO,GAAA,CAAI,IAAA,CAAK,QAAA,CAAS,OAAO,CAAA;AAChF,MAAA,MAAM,SAAA,GAAY,GAAA,CAAI,OAAA,CAAQ,eAAe,CAAA;AAE7C,MAAA,IAAI,CAAC,SAAA,IAAa,OAAO,SAAA,KAAc,QAAA,EAAU;AAC/C,QAAA,GAAA,CAAI,OAAO,GAAG,CAAA,CAAE,KAAK,EAAE,KAAA,EAAO,6BAA6B,CAAA;AAC3D,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,OAAA,CAAQ,MAAA,CAAO,IAAA,EAAM,SAAS,CAAA;AACpC,MAAA,GAAA,CAAI,OAAO,GAAG,CAAA,CAAE,KAAK,EAAE,QAAA,EAAU,MAAM,CAAA;AAAA,IACzC,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,OAAA,GAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,2BAAA;AAEzD,MAAA,IAAI,OAAA,CAAQ,QAAA,CAAS,WAAW,CAAA,EAAG;AACjC,QAAA,GAAA,CAAI,OAAO,GAAG,CAAA,CAAE,KAAK,EAAE,KAAA,EAAO,SAAS,CAAA;AAAA,MACzC,CAAA,MAAA,IAAW,QAAQ,QAAA,CAAS,WAAW,KAAK,OAAA,CAAQ,QAAA,CAAS,WAAW,CAAA,EAAG;AACzE,QAAA,GAAA,CAAI,OAAO,GAAG,CAAA,CAAE,KAAK,EAAE,KAAA,EAAO,SAAS,CAAA;AAAA,MACzC,CAAA,MAAA,IAAW,OAAA,CAAQ,QAAA,CAAS,WAAW,CAAA,EAAG;AACxC,QAAA,GAAA,CAAI,OAAO,GAAG,CAAA,CAAE,KAAK,EAAE,KAAA,EAAO,SAAS,CAAA;AAAA,MACzC,WAAW,IAAA,EAAM;AACf,QAAA,IAAA,CAAK,KAAK,CAAA;AAAA,MACZ,CAAA,MAAO;AACL,QAAA,GAAA,CAAI,OAAO,GAAG,CAAA,CAAE,KAAK,EAAE,KAAA,EAAO,SAAS,CAAA;AAAA,MACzC;AAAA,IACF;AAAA,EACF,CAAA;AACF;AAOO,SAAS,yBACd,OAAA,EACyC;AACzC,EAAA,MAAM,OAAA,GAAU,aAAa,OAAO,CAAA;AACpC,EAAA,MAAM,eAAA,GAAkB,QAAQ,eAAA,IAAmB,qBAAA;AAEnD,EAAA,OAAO,OAAO,OAAA,KAAwC;AACpD,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,IAAA,EAAK;AAChC,MAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,eAAe,CAAA;AAErD,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,OAAO,IAAI,SAAS,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,2BAAA,EAA6B,CAAA,EAAG;AAAA,UAC1E,MAAA,EAAQ,GAAA;AAAA,UACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA;AAAmB,SAC/C,CAAA;AAAA,MACH;AAEA,MAAA,MAAM,OAAA,CAAQ,MAAA,CAAO,IAAA,EAAM,SAAS,CAAA;AAEpC,MAAA,OAAO,IAAI,SAAS,IAAA,CAAK,SAAA,CAAU,EAAE,QAAA,EAAU,IAAA,EAAM,CAAA,EAAG;AAAA,QACtD,MAAA,EAAQ,GAAA;AAAA,QACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA;AAAmB,OAC/C,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,OAAA,GAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,2BAAA;AACzD,MAAA,MAAM,SAAS,OAAA,CAAQ,QAAA,CAAS,WAAW,CAAA,GACvC,GAAA,GACA,QAAQ,QAAA,CAAS,WAAW,KAAK,OAAA,CAAQ,QAAA,CAAS,WAAW,CAAA,GAC3D,GAAA,GACA,QAAQ,QAAA,CAAS,WAAW,IAC1B,GAAA,GACA,GAAA;AAER,MAAA,OAAO,IAAI,SAAS,IAAA,CAAK,SAAA,CAAU,EAAE,KAAA,EAAO,OAAA,EAAS,CAAA,EAAG;AAAA,QACtD,MAAA;AAAA,QACA,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA;AAAmB,OAC/C,CAAA;AAAA,IACH;AAAA,EACF,CAAA;AACF;AAEA,SAAS,aAAa,OAAA,EAAmD;AACvE,EAAA,MAAM,OAAA,GAAU,IAAI,cAAA,CAAe,OAAO,CAAA;AAE1C,EAAA,IAAI,QAAQ,QAAA,EAAU;AACpB,IAAA,KAAA,MAAW,CAAC,WAAW,YAAY,CAAA,IAAK,OAAO,OAAA,CAAQ,OAAA,CAAQ,QAAQ,CAAA,EAAG;AACxE,MAAA,IAAI,YAAA,EAAc;AAChB,QAAA,OAAA,CAAQ,EAAA,CAAG,WAA+B,YAAY,CAAA;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAI,QAAQ,KAAA,EAAO;AACjB,IAAA,OAAA,CAAQ,KAAA,CAAM,QAAQ,KAAK,CAAA;AAAA,EAC7B;AAEA,EAAA,OAAO,OAAA;AACT","file":"index.js","sourcesContent":["/**\n * Pluggable authentication for BaseClient.\n *\n * A TokenProvider supplies the credential used for the Authorization header on\n * every request, resolved per-request (async) so callers can source short-lived\n * or rotating credentials (OAuth2 client-credentials, STS, Vault / Secrets\n * Manager) instead of a single static API key. The default StaticApiKeyProvider\n * preserves the original `apiKey` behavior with zero change for existing callers.\n */\n\nexport interface AuthCredential {\n /** Authorization scheme (e.g. 'Bearer'); defaults to 'Bearer' when omitted. */\n scheme?: string;\n /** The credential value (bearer token / API key). */\n token: string;\n}\n\nexport interface TokenProviderContext {\n tenantId: string;\n requestId: string;\n /** When true, bypass any cache and obtain a fresh credential (e.g. after a 401). */\n forceRefresh?: boolean;\n}\n\nexport interface TokenProvider {\n /** Resolve the credential for a request, or null to send no Authorization header. */\n getCredential(ctx: TokenProviderContext): Promise<AuthCredential | null>;\n /** Whether this provider can obtain a fresh credential on demand (drives 401 retry). */\n canRefresh?(): boolean;\n}\n\n/**\n * Default provider: wraps a static API key. Returns null when the key is empty\n * so the client sends no Authorization header, matching the pre-provider behavior.\n */\nexport class StaticApiKeyProvider implements TokenProvider {\n constructor(private readonly apiKey: string) {}\n\n async getCredential(): Promise<AuthCredential | null> {\n return this.apiKey ? { scheme: 'Bearer', token: this.apiKey } : null;\n }\n\n canRefresh(): boolean {\n return false;\n }\n}\n\ninterface CachedToken {\n token: string;\n expiresAt?: number;\n}\n\nexport interface RefreshingTokenProviderOptions {\n /** Fetches a fresh token. `expiresAt` is epoch milliseconds (optional). */\n fetchToken: () => Promise<CachedToken>;\n /** Refresh this many ms before expiry (default: 30_000). */\n skewMs?: number;\n /** Authorization scheme to emit (default: 'Bearer'). */\n scheme?: string;\n /** Observe each successful (re)fetch — for logging / metrics. */\n onRotate?: (meta: { expiresAt?: number }) => void;\n /** Injectable clock (default: Date.now). */\n now?: () => number;\n}\n\n/**\n * Caches a fetched token and refreshes it when it is within the skew window of\n * expiry or when `forceRefresh` is requested. Concurrent refreshes are de-duped\n * into a single in-flight fetch.\n */\nexport class RefreshingTokenProvider implements TokenProvider {\n private cached: CachedToken | null = null;\n private inFlight: Promise<CachedToken> | null = null;\n private readonly skewMs: number;\n private readonly scheme: string;\n private readonly now: () => number;\n\n constructor(private readonly opts: RefreshingTokenProviderOptions) {\n this.skewMs = opts.skewMs ?? 30_000;\n this.scheme = opts.scheme ?? 'Bearer';\n this.now = opts.now ?? (() => Date.now());\n }\n\n canRefresh(): boolean {\n return true;\n }\n\n async getCredential(ctx?: TokenProviderContext): Promise<AuthCredential | null> {\n const forceRefresh = ctx?.forceRefresh ?? false;\n if (!forceRefresh && this.cached && !this.isExpiring(this.cached)) {\n return { scheme: this.scheme, token: this.cached.token };\n }\n const fresh = await this.refresh();\n return { scheme: this.scheme, token: fresh.token };\n }\n\n private isExpiring(token: CachedToken): boolean {\n if (token.expiresAt === undefined) {\n return false;\n }\n return this.now() >= token.expiresAt - this.skewMs;\n }\n\n private refresh(): Promise<CachedToken> {\n if (this.inFlight) {\n return this.inFlight;\n }\n this.inFlight = (async () => {\n try {\n const fresh = await this.opts.fetchToken();\n this.cached = fresh;\n this.opts.onRotate?.({ expiresAt: fresh.expiresAt });\n return fresh;\n } finally {\n this.inFlight = null;\n }\n })();\n return this.inFlight;\n }\n}\n","/**\n * Error hierarchy for Vesant SDK\n *\n * Provides structured error handling with specific error types\n * for different failure scenarios.\n */\n\nexport class VesantError extends Error {\n public requestId?: string;\n\n constructor(\n message: string,\n public code: string,\n public statusCode?: number,\n public details?: Record<string, unknown>\n ) {\n super(message);\n this.name = 'VesantError';\n Object.setPrototypeOf(this, VesantError.prototype);\n }\n}\n\n/** @deprecated Use VesantError instead */\nexport const CGSError = VesantError;\n/** @deprecated Use VesantError instead */\nexport type CGSError = VesantError;\n\nexport class NetworkError extends VesantError {\n constructor(message: string, public originalError?: unknown) {\n super(message, 'NETWORK_ERROR');\n this.name = 'NetworkError';\n Object.setPrototypeOf(this, NetworkError.prototype);\n }\n}\n\nexport class ValidationError extends VesantError {\n constructor(message: string, fields?: string[]) {\n super(message, 'VALIDATION_ERROR', 400, { fields });\n this.name = 'ValidationError';\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\nexport class ServiceUnavailableError extends VesantError {\n constructor(message: string = 'Service unavailable') {\n super(message, 'SERVICE_UNAVAILABLE', 503);\n this.name = 'ServiceUnavailableError';\n Object.setPrototypeOf(this, ServiceUnavailableError.prototype);\n }\n}\n\nexport class ComplianceBlockedError extends VesantError {\n constructor(reasons: string[]) {\n super('Access blocked due to compliance rules', 'COMPLIANCE_BLOCKED', 403, { reasons });\n this.name = 'ComplianceBlockedError';\n Object.setPrototypeOf(this, ComplianceBlockedError.prototype);\n }\n}\n\nexport class AuthenticationError extends VesantError {\n constructor(message: string = 'Authentication failed') {\n super(message, 'AUTHENTICATION_ERROR', 401);\n this.name = 'AuthenticationError';\n Object.setPrototypeOf(this, AuthenticationError.prototype);\n }\n}\n\nexport class RateLimitError extends VesantError {\n constructor(public retryAfter?: number) {\n super('Rate limit exceeded', 'RATE_LIMIT_EXCEEDED', 429, { retryAfter });\n this.name = 'RateLimitError';\n Object.setPrototypeOf(this, RateLimitError.prototype);\n }\n}\n\nexport class TimeoutError extends VesantError {\n constructor(public timeout: number) {\n super(`Request timeout after ${timeout}ms`, 'TIMEOUT', 408, { timeout });\n this.name = 'TimeoutError';\n Object.setPrototypeOf(this, TimeoutError.prototype);\n }\n}\n\nexport class ComplianceError extends VesantError {\n constructor(\n message: string,\n public originalError?: unknown,\n code: string = 'COMPLIANCE_ERROR'\n ) {\n super(message, code);\n this.name = 'ComplianceError';\n Object.setPrototypeOf(this, ComplianceError.prototype);\n }\n}\n\nexport class CircuitBreakerOpenError extends VesantError {\n constructor() {\n super('Circuit breaker is open — requests are temporarily blocked', 'CIRCUIT_BREAKER_OPEN', 503);\n this.name = 'CircuitBreakerOpenError';\n Object.setPrototypeOf(this, CircuitBreakerOpenError.prototype);\n }\n}\n","/**\n * Circuit breaker pattern for resilient HTTP requests.\n *\n * States: closed (normal) -> open (failing) -> half-open (testing) -> closed\n */\n\nexport type CircuitBreakerState = 'closed' | 'open' | 'half-open';\n\nexport interface CircuitBreakerConfig {\n /** Number of consecutive failures before opening the circuit (default: 5) */\n failureThreshold?: number;\n /** Time in ms to wait before transitioning from open to half-open (default: 30000) */\n resetTimeout?: number;\n /** Number of successes in half-open state before closing (default: 1) */\n successThreshold?: number;\n}\n\nexport interface CircuitBreakerStatus {\n state: CircuitBreakerState;\n failures: number;\n successes: number;\n lastFailureTime: number | null;\n nextRetryTime: number | null;\n}\n\nexport class CircuitBreaker {\n private state: CircuitBreakerState = 'closed';\n private failures = 0;\n private successes = 0;\n private lastFailureTime: number | null = null;\n\n private readonly failureThreshold: number;\n private readonly resetTimeout: number;\n private readonly successThreshold: number;\n\n constructor(config: CircuitBreakerConfig = {}) {\n this.failureThreshold = config.failureThreshold ?? 5;\n this.resetTimeout = config.resetTimeout ?? 30000;\n this.successThreshold = config.successThreshold ?? 1;\n }\n\n /**\n * Check if a request can proceed through the circuit breaker.\n */\n canExecute(): boolean {\n if (this.state === 'closed') {\n return true;\n }\n\n if (this.state === 'open') {\n const now = Date.now();\n if (this.lastFailureTime && now - this.lastFailureTime >= this.resetTimeout) {\n this.state = 'half-open';\n this.successes = 0;\n return true;\n }\n return false;\n }\n\n // half-open: allow requests through for testing\n return true;\n }\n\n /**\n * Record a successful request.\n */\n onSuccess(): void {\n if (this.state === 'half-open') {\n this.successes++;\n if (this.successes >= this.successThreshold) {\n this.state = 'closed';\n this.failures = 0;\n this.successes = 0;\n this.lastFailureTime = null;\n }\n } else if (this.state === 'closed') {\n this.failures = 0;\n }\n }\n\n /**\n * Record a failed request.\n */\n onFailure(): void {\n this.failures++;\n this.lastFailureTime = Date.now();\n\n if (this.state === 'half-open') {\n this.state = 'open';\n this.successes = 0;\n } else if (this.state === 'closed' && this.failures >= this.failureThreshold) {\n this.state = 'open';\n }\n }\n\n /**\n * Get current circuit breaker status.\n */\n getStatus(): CircuitBreakerStatus {\n return {\n state: this.state,\n failures: this.failures,\n successes: this.successes,\n lastFailureTime: this.lastFailureTime,\n nextRetryTime:\n this.state === 'open' && this.lastFailureTime\n ? this.lastFailureTime + this.resetTimeout\n : null,\n };\n }\n\n /**\n * Reset the circuit breaker to its initial closed state.\n */\n reset(): void {\n this.state = 'closed';\n this.failures = 0;\n this.successes = 0;\n this.lastFailureTime = null;\n }\n}\n","/**\n * Rate limit tracking from API response headers.\n *\n * Tracks X-RateLimit-* headers to enable pre-flight checks\n * before making requests.\n */\n\nexport interface RateLimitStatus {\n /** Maximum requests allowed in the window */\n limit: number | null;\n /** Remaining requests in the current window */\n remaining: number | null;\n /** Unix timestamp (seconds) when the rate limit resets */\n reset: number | null;\n /** Seconds until the rate limit resets */\n retryAfter: number | null;\n}\n\nexport class RateLimitTracker {\n private limit: number | null = null;\n private remaining: number | null = null;\n private reset: number | null = null;\n private retryAfter: number | null = null;\n\n /**\n * Extract rate limit information from response headers.\n */\n updateFromHeaders(headers: Headers): void {\n const limit = headers.get('x-ratelimit-limit');\n const remaining = headers.get('x-ratelimit-remaining');\n const reset = headers.get('x-ratelimit-reset');\n const retryAfter = headers.get('retry-after');\n\n if (limit !== null) this.limit = parseInt(limit, 10);\n if (remaining !== null) this.remaining = parseInt(remaining, 10);\n if (reset !== null) this.reset = parseInt(reset, 10);\n if (retryAfter !== null) this.retryAfter = parseInt(retryAfter, 10);\n }\n\n /**\n * Check if the rate limit has been exceeded based on tracked headers.\n */\n isLimitExceeded(): boolean {\n if (this.remaining !== null && this.remaining <= 0) {\n // Check if the reset time has passed\n if (this.reset !== null) {\n const now = Math.floor(Date.now() / 1000);\n if (now >= this.reset) {\n // Reset window has passed, allow requests\n this.remaining = null;\n this.reset = null;\n this.retryAfter = null;\n return false;\n }\n }\n return true;\n }\n return false;\n }\n\n /**\n * Get current rate limit status.\n */\n getStatus(): RateLimitStatus {\n return {\n limit: this.limit,\n remaining: this.remaining,\n reset: this.reset,\n retryAfter: this.retryAfter,\n };\n }\n}\n","import type { Logger } from './config';\n\nexport function createConsoleLogger(): Logger {\n return {\n debug(message: string, meta?: Record<string, unknown>) {\n console.log(`[Vesant SDK] ${message}`, meta !== undefined ? meta : '');\n },\n info(message: string, meta?: Record<string, unknown>) {\n console.info(`[Vesant SDK] ${message}`, meta !== undefined ? meta : '');\n },\n warn(message: string, meta?: Record<string, unknown>) {\n console.warn(`[Vesant SDK] ${message}`, meta !== undefined ? meta : '');\n },\n error(message: string, meta?: Record<string, unknown>) {\n console.error(`[Vesant SDK] ${message}`, meta !== undefined ? meta : '');\n },\n };\n}\n\nexport const noopLogger: Logger = {\n debug() {},\n info() {},\n warn() {},\n error() {},\n};\n","/**\n * Single source of truth for the SDK version.\n */\nexport const SDK_VERSION = '1.7.2';\n","/**\n * Shared browser utility functions.\n *\n * Extracted from ciphertext.ts and hooks.ts to avoid duplication.\n * All functions include SSR guards for safe server-side rendering.\n */\n\n/**\n * Generate a UUID v4\n */\nexport function generateUUID(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n // Fallback for older browsers\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n/**\n * Generate a unique device ID that persists across sessions.\n * Falls back to a random UUID when localStorage is unavailable (SSR).\n */\nexport function generateDeviceId(): string {\n if (typeof window === 'undefined' || typeof localStorage === 'undefined') {\n return generateUUID();\n }\n\n const storageKey = 'vesant_device_id';\n let deviceId = localStorage.getItem(storageKey);\n\n if (!deviceId) {\n deviceId = generateUUID();\n localStorage.setItem(storageKey, deviceId);\n }\n\n return deviceId;\n}\n\n/**\n * Detect browser information from user agent.\n * Returns safe defaults when running server-side.\n */\nexport function getBrowserInfo(): {\n browser: string;\n browser_version: string;\n os: string;\n os_version: string;\n} {\n if (typeof navigator === 'undefined') {\n return { browser: 'unknown', browser_version: '', os: 'unknown', os_version: '' };\n }\n\n const ua = navigator.userAgent;\n let browser = 'unknown';\n let browserVersion = '';\n let os = 'unknown';\n let osVersion = '';\n\n // Detect browser\n if (ua.includes('Firefox/')) {\n browser = 'Firefox';\n browserVersion = ua.match(/Firefox\\/([\\d.]+)/)?.[1] || '';\n } else if (ua.includes('Edg/')) {\n browser = 'Edge';\n browserVersion = ua.match(/Edg\\/([\\d.]+)/)?.[1] || '';\n } else if (ua.includes('Chrome/')) {\n browser = 'Chrome';\n browserVersion = ua.match(/Chrome\\/([\\d.]+)/)?.[1] || '';\n } else if (ua.includes('Safari/') && !ua.includes('Chrome')) {\n browser = 'Safari';\n browserVersion = ua.match(/Version\\/([\\d.]+)/)?.[1] || '';\n } else if (ua.includes('Opera') || ua.includes('OPR/')) {\n browser = 'Opera';\n browserVersion = ua.match(/(?:Opera|OPR)\\/([\\d.]+)/)?.[1] || '';\n }\n\n // Detect OS\n if (ua.includes('Windows')) {\n os = 'Windows';\n if (ua.includes('Windows NT 10.0')) osVersion = '10';\n else if (ua.includes('Windows NT 6.3')) osVersion = '8.1';\n else if (ua.includes('Windows NT 6.2')) osVersion = '8';\n else if (ua.includes('Windows NT 6.1')) osVersion = '7';\n } else if (ua.includes('Mac OS X')) {\n os = 'macOS';\n osVersion = ua.match(/Mac OS X ([\\d_]+)/)?.[1]?.replace(/_/g, '.') || '';\n } else if (ua.includes('Linux')) {\n os = 'Linux';\n } else if (ua.includes('Android')) {\n os = 'Android';\n osVersion = ua.match(/Android ([\\d.]+)/)?.[1] || '';\n } else if (ua.includes('iOS') || ua.includes('iPhone') || ua.includes('iPad')) {\n os = 'iOS';\n osVersion = ua.match(/OS ([\\d_]+)/)?.[1]?.replace(/_/g, '.') || '';\n }\n\n return { browser, browser_version: browserVersion, os, os_version: osVersion };\n}\n","/**\n * Base HTTP client for all Vesant SDK clients\n *\n * Provides common functionality:\n * - Request/response handling\n * - Error handling\n * - Retry logic with exponential backoff\n * - Timeout management\n * - Debug logging\n */\n\nimport type { BaseClientConfig, Logger, RequestInterceptor, RequestOptions } from './config';\nimport { type TokenProvider, StaticApiKeyProvider } from './auth';\nimport {\n VesantError,\n NetworkError,\n TimeoutError,\n AuthenticationError,\n RateLimitError,\n ServiceUnavailableError,\n ValidationError,\n CircuitBreakerOpenError,\n} from './errors';\nimport { CircuitBreaker, type CircuitBreakerStatus } from './circuit-breaker';\nimport { RateLimitTracker, type RateLimitStatus } from './rate-limiter';\nimport { createConsoleLogger } from './logger';\nimport { SDK_VERSION } from './version';\nimport { generateUUID } from '../shared/browser-utils';\n\nexport abstract class BaseClient {\n protected config: BaseClientConfig & { timeout: number; retries: number };\n protected logger: Logger;\n private interceptors: RequestInterceptor[];\n private circuitBreaker: CircuitBreaker | null = null;\n private rateLimitTracker: RateLimitTracker | null = null;\n private authProvider: TokenProvider | undefined;\n\n constructor(config: BaseClientConfig) {\n if (!config.baseURL?.trim()) {\n throw new ValidationError('baseURL is required and must be a non-empty string', ['baseURL']);\n }\n if (!config.tenantId?.trim()) {\n throw new ValidationError('tenantId is required and must be a non-empty string', ['tenantId']);\n }\n\n // The SDK relies on a global fetch (Node.js >= 18). Fail fast with a clear\n // message rather than a later \"fetch is not defined\" ReferenceError.\n if (typeof fetch === 'undefined') {\n throw new VesantError(\n 'The Vesant SDK requires a global fetch (Node.js >= 18). Upgrade Node or provide a fetch polyfill.',\n 'RUNTIME_UNSUPPORTED'\n );\n }\n\n this.interceptors = config.interceptors || [];\n this.logger = config.logger || createConsoleLogger();\n\n // Auto-detect environment from API key prefix\n let environment = config.environment;\n const apiKey = config.apiKey || '';\n if (apiKey.startsWith('pk_test_')) {\n if (environment === 'production') {\n this.logger.warn('Sandbox API key (pk_test_*) used with environment: \"production\" — overriding to \"sandbox\"');\n }\n environment = 'sandbox';\n } else if (apiKey.startsWith('pk_live_') && environment === 'sandbox') {\n this.logger.warn('Production API key (pk_live_*) used with environment: \"sandbox\" — sandbox isolation will still be applied for backward compatibility');\n }\n\n this.config = {\n ...config,\n apiKey,\n environment,\n headers: config.headers || {},\n timeout: config.timeout || 10000,\n retries: config.retries ?? 3,\n debug: config.debug || false,\n interceptors: this.interceptors,\n logger: this.logger,\n };\n\n // Default to a static-apiKey provider so the apiKey path is unchanged; an\n // explicit authProvider (OAuth2 / rotating secrets) takes precedence.\n this.authProvider = config.authProvider ?? (apiKey ? new StaticApiKeyProvider(apiKey) : undefined);\n\n if (config.circuitBreaker) {\n this.circuitBreaker = new CircuitBreaker(config.circuitBreaker);\n }\n if (config.enableRateLimitTracking) {\n this.rateLimitTracker = new RateLimitTracker();\n }\n }\n\n /**\n * Resolve the Idempotency-Key for a request. Mutating methods (POST/PUT/PATCH)\n * get the caller-supplied key or a freshly minted UUID; non-mutating methods get\n * none. requestWithRetry resolves this once and injects it so every retry reuses\n * one key (letting the server dedup replays); a direct request() resolves per call.\n */\n private resolveIdempotencyKey(method: string, requestOptions?: RequestOptions): string | undefined {\n const isMutating = ['POST', 'PUT', 'PATCH'].includes((method || 'GET').toUpperCase());\n if (!isMutating) {\n return undefined;\n }\n return requestOptions?.idempotencyKey ?? generateUUID();\n }\n\n /**\n * Make an HTTP request with timeout and error handling\n */\n protected async request<T>(\n endpoint: string,\n options: RequestInit = {},\n serviceURL?: string,\n requestOptions?: RequestOptions\n ): Promise<T> {\n const requestId = generateUUID();\n\n // Circuit breaker check\n if (this.circuitBreaker && !this.circuitBreaker.canExecute()) {\n const error = new CircuitBreakerOpenError();\n error.requestId = requestId;\n throw error;\n }\n\n // Rate limit pre-check\n if (this.rateLimitTracker && this.rateLimitTracker.isLimitExceeded()) {\n const status = this.rateLimitTracker.getStatus();\n const error = new RateLimitError(status.retryAfter ?? undefined);\n error.requestId = requestId;\n throw error;\n }\n\n const url = `${serviceURL || this.config.baseURL}${endpoint}`;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-Tenant-ID': this.config.tenantId,\n 'X-SDK-Version': `vesant-sdk-ts/${SDK_VERSION}`,\n 'X-Request-ID': requestId,\n ...this.config.headers,\n ...((options.headers as Record<string, string>) || {}),\n };\n\n // Resolve the auth credential per-request via the token provider (async, so a\n // provider can fetch/refresh short-lived credentials). No credential = no header.\n const credential = await this.authProvider?.getCredential({\n tenantId: this.config.tenantId,\n requestId,\n });\n if (credential) {\n headers['Authorization'] = `${credential.scheme ?? 'Bearer'} ${credential.token}`;\n }\n\n // Sandbox header\n if (this.config.environment === 'sandbox') {\n headers['X-Sandbox'] = 'true';\n }\n\n // Idempotency key for mutating methods. Via requestWithRetry the key arrives\n // pre-resolved in requestOptions so all attempts share one; a direct request()\n // falls back to minting one here.\n const method = (options.method || 'GET').toUpperCase();\n const idempotencyKey = this.resolveIdempotencyKey(method, requestOptions);\n if (idempotencyKey) {\n headers['Idempotency-Key'] = idempotencyKey;\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n // Link consumer AbortSignal to internal controller\n if (requestOptions?.signal) {\n if (requestOptions.signal.aborted) {\n controller.abort();\n } else {\n requestOptions.signal.addEventListener('abort', () => controller.abort(), { once: true });\n }\n }\n\n try {\n // Run onRequest interceptors\n let finalOptions: RequestInit = { ...options, headers };\n for (const interceptor of this.interceptors) {\n if (interceptor.onRequest) {\n finalOptions = await interceptor.onRequest(url, finalOptions);\n }\n }\n\n if (this.config.debug) {\n this.logger.debug(`${finalOptions.method || 'GET'} ${endpoint}`);\n }\n\n let response = await fetch(url, {\n ...finalOptions,\n signal: controller.signal,\n });\n\n // Single-shot 401 re-auth: if the provider can refresh, a 401 forces one\n // credential refresh and retry, reusing the same headers (incl. the\n // Idempotency-Key) so a mutating request is not double-submitted.\n if (response.status === 401 && this.authProvider?.canRefresh?.()) {\n const refreshed = await this.authProvider.getCredential({\n tenantId: this.config.tenantId,\n requestId,\n forceRefresh: true,\n });\n if (refreshed) {\n this.config.onCredentialRotated?.({ reason: 'unauthorized' });\n finalOptions = {\n ...finalOptions,\n headers: {\n ...(finalOptions.headers as Record<string, string>),\n Authorization: `${refreshed.scheme ?? 'Bearer'} ${refreshed.token}`,\n },\n };\n response = await fetch(url, { ...finalOptions, signal: controller.signal });\n }\n }\n\n clearTimeout(timeoutId);\n\n // Track rate limit headers\n if (this.rateLimitTracker) {\n this.rateLimitTracker.updateFromHeaders(response.headers);\n }\n\n // Binary download path\n if (requestOptions?.responseType === 'arraybuffer') {\n if (!response.ok) {\n let errData: Record<string, unknown> = {};\n try { errData = await response.json(); } catch { /* ignore */ }\n this.handleErrorResponse(response.status, errData, requestId);\n }\n this.circuitBreaker?.onSuccess();\n const buffer = await response.arrayBuffer();\n return buffer as unknown as T;\n }\n\n let data: Record<string, unknown> | undefined;\n try {\n data = await response.json();\n } catch {\n // Non-JSON response (HTML error pages, 204 No Content, etc.)\n if (!response.ok) {\n this.handleErrorResponse(response.status, {\n error: `HTTP ${response.status}`,\n message: response.statusText,\n }, requestId);\n }\n // OK response but no JSON body (e.g., 204)\n this.circuitBreaker?.onSuccess();\n return undefined as unknown as T;\n }\n\n if (!response.ok) {\n this.handleErrorResponse(response.status, data || {}, requestId);\n }\n\n // Record success for circuit breaker\n this.circuitBreaker?.onSuccess();\n\n // Run onResponse interceptors\n let result: unknown = data;\n for (const interceptor of this.interceptors) {\n if (interceptor.onResponse) {\n result = await interceptor.onResponse(url, result);\n }\n }\n\n if (this.config.debug) {\n this.logger.debug(`Response: ${response.status}`);\n }\n\n return result as T;\n } catch (error) {\n clearTimeout(timeoutId);\n\n // Record failure for circuit breaker (skip for client errors)\n if (\n error instanceof VesantError &&\n error.statusCode &&\n error.statusCode >= 500\n ) {\n this.circuitBreaker?.onFailure();\n } else if (error instanceof NetworkError || error instanceof TimeoutError) {\n this.circuitBreaker?.onFailure();\n }\n\n // Attach requestId to VesantError instances\n if (error instanceof VesantError && !error.requestId) {\n error.requestId = requestId;\n }\n\n // Run onError interceptors\n if (error instanceof Error) {\n for (const interceptor of this.interceptors) {\n if (interceptor.onError) {\n await interceptor.onError(url, error);\n }\n }\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n // Distinguish consumer abort from timeout\n if (requestOptions?.signal?.aborted) {\n const abortError = new VesantError('Request aborted', 'REQUEST_ABORTED');\n abortError.requestId = requestId;\n throw abortError;\n }\n this.circuitBreaker?.onFailure();\n const timeoutError = new TimeoutError(this.config.timeout);\n timeoutError.requestId = requestId;\n throw timeoutError;\n }\n if (error instanceof VesantError) {\n throw error;\n }\n }\n\n const networkError = new NetworkError('Network request failed', error);\n networkError.requestId = requestId;\n this.circuitBreaker?.onFailure();\n throw networkError;\n }\n }\n\n /**\n * Make an HTTP request with retry logic\n */\n protected async requestWithRetry<T>(\n endpoint: string,\n options: RequestInit = {},\n serviceURL?: string,\n retries: number = this.config.retries,\n requestOptions?: RequestOptions\n ): Promise<T> {\n let lastError: Error | undefined;\n\n // Resolve the idempotency key once so every retry attempt reuses it, letting\n // the server dedup replays instead of re-processing (and re-billing) each try.\n const idempotencyKey = this.resolveIdempotencyKey(options.method || 'GET', requestOptions);\n const attemptOptions: RequestOptions | undefined = idempotencyKey\n ? { ...requestOptions, idempotencyKey }\n : requestOptions;\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n return await this.request<T>(endpoint, options, serviceURL, attemptOptions);\n } catch (error) {\n lastError = error instanceof Error ? error : new Error('Unknown error');\n\n // Don't retry on consumer abort\n if (requestOptions?.signal?.aborted) {\n throw lastError;\n }\n\n // Don't retry on client errors (4xx), except 429 (rate limit)\n if (\n lastError instanceof VesantError &&\n lastError.statusCode &&\n lastError.statusCode >= 400 &&\n lastError.statusCode < 500 &&\n lastError.statusCode !== 429\n ) {\n throw lastError;\n }\n\n // Don't retry on last attempt\n if (attempt === retries) {\n break;\n }\n\n // Use Retry-After for 429, otherwise exponential backoff with jitter\n let delay: number;\n if (lastError instanceof RateLimitError && lastError.retryAfter) {\n delay = lastError.retryAfter * 1000;\n } else {\n delay = Math.min(1000 * Math.pow(2, attempt) + Math.random() * 1000, 10000);\n }\n await new Promise((resolve) => setTimeout(resolve, delay));\n\n if (this.config.debug) {\n this.logger.debug(`Retry attempt ${attempt + 1}/${retries} after ${delay.toFixed(0)}ms`);\n }\n }\n }\n\n throw new NetworkError(`Request failed after ${retries} retries`, lastError);\n }\n\n /**\n * Handle error responses from API\n */\n protected handleErrorResponse(status: number, data: Record<string, unknown>, requestId?: string): never {\n const message = (data.error as string) || (data.message as string) || `HTTP ${status}`;\n\n const createError = (): VesantError => {\n switch (status) {\n case 400:\n return new VesantError(message, 'BAD_REQUEST', 400);\n case 401:\n return new AuthenticationError(message);\n case 403:\n return new VesantError(message, 'FORBIDDEN', 403);\n case 404:\n return new VesantError(message, 'NOT_FOUND', 404);\n case 409:\n return new VesantError(message, 'DUPLICATE_PROFILE', 409);\n case 429: {\n const retryAfter = (data.retry_after as number | undefined) || (data.retryAfter as number | undefined);\n return new RateLimitError(retryAfter);\n }\n case 500:\n case 502:\n case 503:\n case 504:\n return new ServiceUnavailableError(message);\n default:\n return new VesantError(message, 'UNKNOWN_ERROR', status);\n }\n };\n\n const error = createError();\n if (requestId) {\n error.requestId = requestId;\n }\n throw error;\n }\n\n /**\n * Build query string from parameters\n */\n protected buildQueryString(params: Record<string, unknown>): string {\n const query = new URLSearchParams();\n\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (Array.isArray(value)) {\n value.forEach((item) => query.append(key, String(item)));\n } else {\n query.append(key, String(value));\n }\n }\n });\n\n const queryString = query.toString();\n return queryString ? `?${queryString}` : '';\n }\n\n /**\n * Update client configuration\n */\n updateConfig(config: Partial<BaseClientConfig>): void {\n this.config = {\n ...this.config,\n ...config,\n headers: {\n ...this.config.headers,\n ...(config.headers || {}),\n },\n };\n if (config.logger) {\n this.logger = config.logger;\n }\n if (config.interceptors) {\n this.interceptors = config.interceptors;\n }\n // Rebuild the auth provider when auth-related config changes so a rotated key\n // or a swapped provider takes effect on subsequent requests.\n if (config.authProvider !== undefined || config.apiKey !== undefined) {\n this.authProvider =\n this.config.authProvider ??\n (this.config.apiKey ? new StaticApiKeyProvider(this.config.apiKey) : undefined);\n }\n }\n\n /**\n * Get current configuration (readonly)\n */\n getConfig(): Readonly<BaseClientConfig> {\n return { ...this.config };\n }\n\n /**\n * Get rate limit status from tracked response headers.\n */\n getRateLimitStatus(): RateLimitStatus | null {\n return this.rateLimitTracker?.getStatus() ?? null;\n }\n\n /**\n * Get circuit breaker status.\n */\n getCircuitBreakerStatus(): CircuitBreakerStatus | null {\n return this.circuitBreaker?.getStatus() ?? null;\n }\n\n /**\n * Health check endpoint\n */\n async healthCheck(): Promise<{ status: string; timestamp: string }> {\n return this.request('/api/v1/health');\n }\n}\n","import type { PaginatedResponse } from './types';\n\n/**\n * Lazily walk every item across all pages of a paginated endpoint. `fetchPage`\n * is called with a 1-based page number and must return a PaginatedResponse.\n * Iteration advances until `total_pages` is reached, and stops early if a page\n * returns no items (a guard against a runaway loop on an over-reported\n * total_pages). Pages are fetched on demand as the consumer iterates.\n *\n * @example\n * for await (const profile of paginate((page) => client.listProfiles({ page }))) {\n * // ...\n * }\n */\nexport async function* paginate<T>(\n fetchPage: (page: number) => Promise<PaginatedResponse<T>>\n): AsyncGenerator<T, void, void> {\n let page = 1;\n let totalPages: number;\n do {\n const response = await fetchPage(page);\n const items = response.data ?? [];\n for (const item of items) {\n yield item;\n }\n totalPages = response.total_pages ?? page;\n if (items.length === 0) {\n break;\n }\n page += 1;\n } while (page <= totalPages);\n}\n\n/** Collect every item from a paginated endpoint into a single array. */\nexport async function collectAll<T>(\n fetchPage: (page: number) => Promise<PaginatedResponse<T>>\n): Promise<T[]> {\n const items: T[] = [];\n for await (const item of paginate(fetchPage)) {\n items.push(item);\n }\n return items;\n}\n","/**\n * Pluggable dedup store for webhook replay protection.\n *\n * The default InMemoryDedupStore is process-local — correct for a single\n * long-lived process, but useless across replicas / serverless invocations where\n * the backend's at-least-once retries land on different instances. Supply a\n * shared implementation (e.g. Redis with SETNX + TTL) via WebhookHandlerConfig\n * to dedup reliably in those deployments.\n */\n\nexport interface WebhookDedupStore {\n /** Has this event id already been processed? */\n seen(id: string): Promise<boolean>;\n /** Record this event id as processed, retained for at least ttlMs. */\n mark(id: string, ttlMs: number): Promise<void>;\n}\n\nexport interface InMemoryDedupStoreOptions {\n /** Purge expired entries once the map grows past this size (default: 1000). */\n maxEntries?: number;\n /** Injectable clock (default: Date.now). */\n now?: () => number;\n}\n\nexport class InMemoryDedupStore implements WebhookDedupStore {\n private readonly expiryById = new Map<string, number>();\n private readonly maxEntries: number;\n private readonly now: () => number;\n\n constructor(opts: InMemoryDedupStoreOptions = {}) {\n this.maxEntries = opts.maxEntries ?? 1000;\n this.now = opts.now ?? (() => Date.now());\n }\n\n async seen(id: string): Promise<boolean> {\n return this.expiryById.has(id);\n }\n\n async mark(id: string, ttlMs: number): Promise<void> {\n const now = this.now();\n this.expiryById.set(id, now + ttlMs);\n\n // Bounded memory: purge expired entries once the map grows too large.\n if (this.expiryById.size > this.maxEntries) {\n for (const [key, expiresAt] of this.expiryById) {\n if (now > expiresAt) {\n this.expiryById.delete(key);\n }\n }\n }\n }\n}\n","/**\n * Webhook signature verification utilities.\n *\n * Supports both Web Crypto API (browsers, Deno, Cloudflare Workers)\n * and Node.js crypto module with automatic runtime detection.\n * Uses constant-time comparison to prevent timing attacks.\n */\n\nimport { VesantError } from './errors';\n\nexport interface VerifyWebhookSignatureOptions {\n /** Max allowed clock skew in ms for the signed-timestamp scheme (default: 300000). */\n tolerance?: number;\n /** Clock source for the tolerance check (default: Date.now). */\n now?: () => number;\n /** Accept the legacy body-only `sha256=<hex>` format (default: true, for migration). */\n allowLegacy?: boolean;\n}\n\n/**\n * Verify an HMAC-SHA256 webhook signature.\n *\n * Supports two schemes:\n * - Signed-timestamp (preferred): `t=<unix>,v1=<hex>` where the HMAC is computed\n * over `${t}.${payload}`. The timestamp is inside the signed material, so a\n * replayed body is rejected once `|now - t|` exceeds the tolerance — the check\n * is done BEFORE the HMAC compare and authenticates the timestamp.\n * - Legacy (body-only): `sha256=<hex>` (or raw hex) over the payload alone. Kept\n * for the migration window; disable via `allowLegacy: false`.\n *\n * @returns true if the signature is valid\n */\nexport async function verifyWebhookSignature(\n payload: string,\n signature: string,\n secret: string,\n opts: VerifyWebhookSignatureOptions = {}\n): Promise<boolean> {\n const signed = parseSignedTimestamp(signature);\n if (signed) {\n const tolerance = opts.tolerance ?? 300000;\n const now = opts.now?.() ?? Date.now();\n // Authenticate the timestamp first — reject replays before any HMAC compare.\n if (tolerance > 0 && Math.abs(now - signed.t * 1000) > tolerance) {\n return false;\n }\n const expected = await computeHmacSha256(`${signed.t}.${payload}`, secret);\n return constantTimeEqual(signed.v1, expected);\n }\n\n if (opts.allowLegacy === false) {\n return false;\n }\n\n const hexDigest = await computeHmacSha256(payload, secret);\n // Backend sends \"sha256=<hex>\" format — support both prefixed and raw signatures\n const expectedPrefixed = `sha256=${hexDigest}`;\n\n if (signature.startsWith('sha256=')) {\n return constantTimeEqual(signature, expectedPrefixed);\n }\n\n return constantTimeEqual(signature, hexDigest);\n}\n\n/**\n * Parse the `t=<unix>,v1=<hex>` signed-timestamp scheme; returns null if the\n * signature is not in that form (e.g. legacy `sha256=<hex>`).\n */\nfunction parseSignedTimestamp(signature: string): { t: number; v1: string } | null {\n if (!signature.includes('t=') || !signature.includes('v1=')) {\n return null;\n }\n let t: number | undefined;\n let v1: string | undefined;\n for (const part of signature.split(',')) {\n const eq = part.indexOf('=');\n if (eq === -1) continue;\n const key = part.slice(0, eq).trim();\n const value = part.slice(eq + 1).trim();\n if (key === 't') t = Number(value);\n else if (key === 'v1') v1 = value;\n }\n if (t === undefined || Number.isNaN(t) || !v1) {\n return null;\n }\n return { t, v1 };\n}\n\n/**\n * Compute HMAC-SHA256 hex digest.\n * Automatically selects Web Crypto API or Node.js crypto.\n */\nasync function computeHmacSha256(message: string, secret: string): Promise<string> {\n // Try Web Crypto API first (browsers, Deno, Cloudflare Workers, Node 18+)\n if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto.subtle) {\n const encoder = new TextEncoder();\n const key = await globalThis.crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign']\n );\n const sig = await globalThis.crypto.subtle.sign('HMAC', key, encoder.encode(message));\n return Array.from(new Uint8Array(sig))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n }\n\n // Fallback to Node.js crypto module\n try {\n const { createHmac } = await import('crypto');\n return createHmac('sha256', secret).update(message).digest('hex');\n } catch {\n throw new VesantError(\n 'No crypto implementation available. Requires Web Crypto API or Node.js crypto module.',\n 'CRYPTO_UNAVAILABLE'\n );\n }\n}\n\n/**\n * Constant-time string comparison to prevent timing attacks.\n */\nfunction constantTimeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n\n let result = 0;\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return result === 0;\n}\n","/**\n * Browser-feasible GPS integrity heuristics.\n *\n * The web SDK cannot detect OS-level mock-location or do sensor fusion (that\n * needs the native mobile SDK). What it CAN do is sanity-check the shape of a\n * `getCurrentPosition` fix for signatures of a devtools override / fake-GPS\n * extension, and surface advisory `integrity_flags` for the server to weigh as\n * risk factors. These heuristics are advisory and fail-open — they never throw\n * and never block; the server remains the fail-closed authority.\n */\n\nexport interface GpsIntegrityInput {\n latitude: number;\n longitude: number;\n accuracy?: number | null;\n altitude?: number | null;\n altitudeAccuracy?: number | null;\n heading?: number | null;\n speed?: number | null;\n timestamp?: number;\n}\n\nexport interface GpsIntegrityOptions {\n /** Geolocation permission state, if probed (see probeGeolocationPermission). */\n permissionState?: PermissionState | 'unavailable';\n /** Current time source (default: Date.now). */\n now?: () => number;\n /** Max fix age (ms) before it is considered stale (default: 60_000). */\n maxAgeMs?: number;\n /** Smallest plausible browser-GPS accuracy in meters; below this is suspicious (default: 1). */\n minAccuracyMeters?: number;\n}\n\nexport interface GpsIntegrityResult {\n suspicious: boolean;\n flags: string[];\n}\n\nconst isNil = (v: number | null | undefined): v is null | undefined => v === null || v === undefined;\n\n/**\n * Assess a raw GPS fix for spoof/integrity signals. Pure and fail-open.\n */\nexport function assessGpsIntegrity(input: GpsIntegrityInput, opts: GpsIntegrityOptions = {}): GpsIntegrityResult {\n const flags: string[] = [];\n const now = opts.now ?? (() => Date.now());\n const maxAgeMs = opts.maxAgeMs ?? 60_000;\n const minAccuracy = opts.minAccuracyMeters ?? 1;\n const { accuracy, altitude, altitudeAccuracy, heading, speed, timestamp } = input;\n\n // Accuracy sanity — a genuine browser GPS fix reports a positive, non-trivial\n // radius; exactly 0, absurdly small, or absent is a devtools-override tell.\n if (isNil(accuracy)) {\n flags.push('accuracy_missing');\n } else if (accuracy === 0) {\n flags.push('accuracy_zero');\n } else if (accuracy < minAccuracy) {\n flags.push('accuracy_implausibly_small');\n }\n\n // Motion fields present but no valid accuracy — inconsistent with a real fix.\n const hasMotion = !isNil(heading) || !isNil(speed);\n if (hasMotion && (isNil(accuracy) || accuracy === 0)) {\n flags.push('motion_without_accuracy');\n }\n\n // Real fixes report altitude and altitude_accuracy together, or neither.\n if (!isNil(altitude) && isNil(altitudeAccuracy)) {\n flags.push('altitude_without_accuracy');\n }\n\n // Stale fix.\n if (timestamp !== undefined && now() - timestamp > maxAgeMs) {\n flags.push('stale_timestamp');\n }\n\n // A position obtained while permission is not 'granted' is inconsistent.\n if (opts.permissionState === 'denied' || opts.permissionState === 'prompt') {\n flags.push(`permission_${opts.permissionState}`);\n }\n\n return { suspicious: flags.length > 0, flags };\n}\n\n/**\n * Map a browser GeolocationPosition to the integrity input shape. Shared by the\n * cipherText and location-capture flows so the coord mapping lives in one place.\n */\nexport function gpsIntegrityInputFromPosition(position: GeolocationPosition): GpsIntegrityInput {\n const c = position.coords;\n return {\n latitude: c.latitude,\n longitude: c.longitude,\n accuracy: c.accuracy,\n altitude: c.altitude,\n altitudeAccuracy: c.altitudeAccuracy,\n heading: c.heading,\n speed: c.speed,\n timestamp: position.timestamp,\n };\n}\n\n/**\n * Probe the geolocation permission state. Guarded for browsers that lack the\n * Permissions API (Safari / older WebKit) — returns 'unavailable' rather than\n * throwing, so callers can pass the result straight into assessGpsIntegrity.\n */\nexport async function probeGeolocationPermission(): Promise<PermissionState | 'unavailable'> {\n try {\n if (typeof navigator === 'undefined' || !navigator.permissions?.query) {\n return 'unavailable';\n }\n const status = await navigator.permissions.query({ name: 'geolocation' as PermissionName });\n return status.state;\n } catch {\n return 'unavailable';\n }\n}\n","/**\n * Device-signals envelope utility.\n *\n * Collects device fingerprint and location data from the browser into a compact\n * envelope that the server validates. `collectDeviceSignals` is the preferred\n * name; `generateCipherText` remains available as an alias.\n *\n * The cipherText is used for:\n * - Registration verification\n * - Login verification\n * - Transaction verification\n * - Periodic location checks\n *\n * Scope: the web SDK collects GPS + IP only. WiFi/cell/sensor-fusion positioning\n * and OS-level mock-location detection are not possible in a browser and require\n * the native mobile SDK (separate backlog item). GPS fixes are additionally run\n * through advisory in-browser integrity heuristics (see ./integrity).\n */\n\nimport type {\n CipherTextPayload,\n CipherTextOptions,\n CipherTextResult,\n CipherTextReason,\n GeolocationConfigResponse,\n} from './types';\nimport { SDK_VERSION } from '../core/version';\nimport { VesantError } from '../core/errors';\nimport { getBrowserInfo, generateDeviceId as getOrCreateDeviceId } from '../shared/browser-utils';\nimport { assessGpsIntegrity, gpsIntegrityInputFromPosition, probeGeolocationPermission } from './integrity';\n\nconst CIPHER_TEXT_EXPIRY_MINUTES = 5;\n\n\n/**\n * Get WebGL renderer information for fingerprinting\n */\nfunction getWebGLInfo(): { vendor: string; renderer: string } | null {\n if (typeof document === 'undefined') return null;\n\n try {\n const canvas = document.createElement('canvas');\n const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\n\n if (!gl) return null;\n\n const debugInfo = (gl as WebGLRenderingContext).getExtension('WEBGL_debug_renderer_info');\n if (!debugInfo) return null;\n\n return {\n vendor: (gl as WebGLRenderingContext).getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) || '',\n renderer: (gl as WebGLRenderingContext).getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) || '',\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Get network information if available\n */\nfunction getNetworkInfo(): CipherTextPayload['network'] | undefined {\n if (typeof navigator === 'undefined') return undefined;\n\n const connection = (navigator as any).connection ||\n (navigator as any).mozConnection ||\n (navigator as any).webkitConnection;\n\n if (!connection) return undefined;\n\n return {\n effective_type: connection.effectiveType,\n downlink: connection.downlink,\n rtt: connection.rtt,\n save_data: connection.saveData,\n };\n}\n\n/**\n * Request GPS location from the browser\n */\nasync function requestGPSLocation(\n timeout: number = 10000,\n highAccuracy: boolean = true\n): Promise<CipherTextPayload['location'] | null> {\n if (typeof navigator === 'undefined' || !navigator.geolocation) {\n return null;\n }\n\n // Probed once up-front so the (synchronous) success callback can pass it to the\n // advisory integrity heuristics without awaiting inside the callback.\n const permissionState = await probeGeolocationPermission();\n\n return new Promise((resolve) => {\n navigator.geolocation.getCurrentPosition(\n (position) => {\n const { latitude, longitude, accuracy } = position.coords;\n\n // Validate coordinates\n if (latitude < -90 || latitude > 90) {\n resolve(null);\n return;\n }\n if (longitude < -180 || longitude > 180) {\n resolve(null);\n return;\n }\n if (accuracy !== null && accuracy !== undefined && accuracy <= 0) {\n resolve(null);\n return;\n }\n\n const { flags } = assessGpsIntegrity(gpsIntegrityInputFromPosition(position), { permissionState });\n\n resolve({\n latitude,\n longitude,\n accuracy,\n altitude: position.coords.altitude ?? undefined,\n altitude_accuracy: position.coords.altitudeAccuracy ?? undefined,\n heading: position.coords.heading ?? undefined,\n speed: position.coords.speed ?? undefined,\n timestamp: position.timestamp,\n integrity_flags: flags.length ? flags : undefined,\n });\n },\n () => {\n // Location denied or error - resolve with null (non-fatal)\n resolve(null);\n },\n {\n enableHighAccuracy: highAccuracy,\n timeout: timeout,\n maximumAge: 0,\n }\n );\n });\n}\n\n/**\n * Collect device fingerprint data\n */\nfunction collectDeviceData(includeWebGL: boolean): CipherTextPayload['device'] {\n const browserInfo = getBrowserInfo();\n const webglInfo = includeWebGL ? getWebGLInfo() : null;\n\n return {\n device_id: getOrCreateDeviceId(),\n user_agent: typeof navigator !== 'undefined' ? navigator.userAgent : '',\n platform: typeof navigator !== 'undefined' ? navigator.platform : '',\n browser: browserInfo.browser,\n browser_version: browserInfo.browser_version,\n os: browserInfo.os,\n os_version: browserInfo.os_version,\n screen_resolution:\n typeof screen !== 'undefined' ? `${screen.width}x${screen.height}` : undefined,\n language: typeof navigator !== 'undefined' ? navigator.language : undefined,\n timezone: Intl?.DateTimeFormat?.()?.resolvedOptions?.()?.timeZone,\n color_depth: typeof screen !== 'undefined' ? screen.colorDepth : undefined,\n hardware_concurrency:\n typeof navigator !== 'undefined' ? navigator.hardwareConcurrency : undefined,\n device_memory: typeof navigator !== 'undefined' ? (navigator as any).deviceMemory : undefined,\n touch_support:\n typeof navigator !== 'undefined' ? navigator.maxTouchPoints > 0 : undefined,\n webgl_vendor: webglInfo?.vendor,\n webgl_renderer: webglInfo?.renderer,\n };\n}\n\n/**\n * Encode payload to base64\n */\nfunction encodePayload(payload: CipherTextPayload): string {\n const json = JSON.stringify(payload);\n\n if (typeof btoa !== 'undefined') {\n // Browser\n return btoa(unescape(encodeURIComponent(json)));\n } else if (typeof Buffer !== 'undefined') {\n // Node.js\n return Buffer.from(json, 'utf-8').toString('base64');\n }\n\n throw new VesantError('No base64 encoding method available', 'BASE64_UNAVAILABLE');\n}\n\n/**\n * Generate a cipherText containing encrypted device and location data\n *\n * @param options - Options for cipherText generation\n * @returns CipherText result with the encrypted string\n *\n * @example\n * ```typescript\n * // Basic usage for login\n * const result = await generateCipherText({ reason: 'login' });\n * console.log(result.cipherText);\n *\n * // With GPS location for registration\n * const result = await generateCipherText({\n * reason: 'registration',\n * requestLocation: true,\n * locationTimeout: 15000\n * });\n *\n * if (result.locationCaptured) {\n * console.log('GPS location included');\n * }\n * ```\n */\nexport async function generateCipherText(\n options: CipherTextOptions,\n config?: GeolocationConfigResponse\n): Promise<CipherTextResult> {\n const warnings: string[] = [];\n\n // Auto-enable GPS if tenant config requires it for this event type\n let requestLocation = options.requestLocation ?? false;\n let gpsRequiredByConfig = false;\n if (config?.require_gps) {\n const reason = options.reason;\n if (\n (reason === 'login' && config.require_gps.login) ||\n (reason === 'registration' && config.require_gps.registration) ||\n (reason === 'transaction' && config.require_gps.transaction)\n ) {\n if (!requestLocation) {\n gpsRequiredByConfig = true;\n }\n requestLocation = true;\n }\n }\n\n // Collect device data\n const deviceData = collectDeviceData(options.includeWebGL !== false);\n\n // Optionally request GPS location\n let locationData: CipherTextPayload['location'] | undefined;\n if (requestLocation) {\n const location = await requestGPSLocation(\n options.locationTimeout || 10000,\n options.highAccuracy !== false\n );\n\n if (location) {\n locationData = location;\n if (location.integrity_flags?.length) {\n warnings.push(`GPS integrity flags (advisory): ${location.integrity_flags.join(', ')}`);\n }\n } else if (gpsRequiredByConfig) {\n throw new VesantError(\n `GPS location is required for ${options.reason} by tenant configuration, but GPS was not available or permission was denied`,\n 'GPS_REQUIRED'\n );\n } else {\n warnings.push('GPS location not available or permission denied');\n }\n }\n\n // Collect network info\n let networkData: CipherTextPayload['network'] | undefined;\n if (options.includeNetworkInfo !== false) {\n networkData = getNetworkInfo();\n }\n\n // Build payload\n const now = new Date();\n const expiry = new Date(now.getTime() + CIPHER_TEXT_EXPIRY_MINUTES * 60 * 1000);\n\n const payload: CipherTextPayload = {\n device: deviceData,\n location: locationData,\n network: networkData,\n metadata: {\n collected_at: now.toISOString(),\n sdk_version: SDK_VERSION,\n collection_reason: options.reason,\n page_url: typeof window !== 'undefined' ? window.location.href : undefined,\n referrer: typeof document !== 'undefined' ? document.referrer || undefined : undefined,\n },\n };\n\n // Encode payload (no obfuscation - HTTPS provides transport security)\n const encoded = encodePayload(payload);\n\n // Create final cipherText with version and timestamp prefix\n const timestamp = now.getTime().toString(36); // Base36 timestamp\n\n // Always emit the unsigned v01 envelope `01.{timestamp}.{base64(JSON)}`. The\n // SDK never holds a signing key — a client-side HMAC signed with a tenant secret\n // pulled into the browser proves possession of a leakable secret, not device\n // authenticity, so the server is the sole signer. This is a base64 JSON envelope,\n // NOT encryption; integrity is enforced server-side.\n const cipherText = `01.${timestamp}.${encoded}`;\n\n return {\n cipherText,\n locationCaptured: !!locationData,\n warnings: warnings.length > 0 ? warnings : undefined,\n generatedAt: now.toISOString(),\n expiresAt: expiry.toISOString(),\n };\n}\n\n/**\n * Collect a device-signals envelope for server-side validation. Preferred name\n * for {@link generateCipherText}, which remains available as an alias.\n */\nexport const collectDeviceSignals = generateCipherText;\n\n/**\n * Decode a cipherText (for debugging/testing - not for production use)\n * In production, decryption happens on the server\n */\nexport function decodeCipherText(cipherText: string): CipherTextPayload | null {\n try {\n const parts = cipherText.split('.');\n // v01: 3 parts, v02: 4 parts (4th is HMAC — ignored when decoding)\n if (parts.length !== 3 && parts.length !== 4) return null;\n\n const [version, , encodedB64] = parts;\n if (version !== '01' && version !== '02') return null;\n\n // Decode matches encode: just base64 decode (no obfuscation)\n const json = decodeURIComponent(escape(atob(encodedB64)));\n\n return JSON.parse(json) as CipherTextPayload;\n } catch {\n return null;\n }\n}\n\n/**\n * Check if a cipherText is expired\n */\nexport function isCipherTextExpired(cipherText: string): boolean {\n try {\n const parts = cipherText.split('.');\n if (parts.length !== 3 && parts.length !== 4) return true;\n\n const timestampB36 = parts[1];\n const timestamp = parseInt(timestampB36, 36);\n const now = Date.now();\n const expiryMs = CIPHER_TEXT_EXPIRY_MINUTES * 60 * 1000;\n\n return now - timestamp > expiryMs;\n } catch {\n return true;\n }\n}\n\n// Re-export types\nexport type { CipherTextPayload, CipherTextOptions, CipherTextResult, CipherTextReason, GeolocationConfigResponse };\n","/**\n * GeolocationClient - TypeScript SDK for Vesant Geolocation & Compliance Service\n *\n * Provides type-safe methods to interact with the geolocation service API.\n * Extends BaseClient for consistent retry logic, timeout handling, and error management.\n */\n\nimport { BaseClient } from '../core/client';\nimport { ValidationError } from '../core/errors';\nimport type { BaseClientConfig, RequestOptions } from '../core/config';\nimport type {\n GeolocationClientConfig,\n GeolocationConfigResponse,\n VerifyIPRequest,\n LocationVerification,\n ComplianceCheckResponse,\n PaginationParams,\n // Location Request Types\n LocationRequest,\n CreateLocationRequestRequest,\n LocationRequestResult,\n LocationRequestFilters,\n LocationRequestListResponse,\n ResendLocationRequestRequest,\n LocationShareInfo,\n LocationCaptureRequest,\n LocationCaptureResponse,\n // CipherText Types\n ValidateCipherTextRequest,\n SignalsNonce,\n ValidateCipherTextResponse,\n CipherTextReason,\n CipherTextCustomerData,\n CipherTextOptions,\n CipherTextResult,\n} from './types';\nimport { generateCipherText as generateCipherTextUtil } from './ciphertext';\n\n/**\n * GeolocationClient extends BaseClient for:\n * - Consistent retry logic with exponential backoff\n * - Unified error handling (VesantError, NetworkError, TimeoutError, etc.)\n * - Automatic timeout management\n * - Debug logging\n *\n * All geolocation verification calls use requestWithRetry() to handle\n * transient failures gracefully.\n */\nexport class GeolocationClient extends BaseClient {\n\n constructor(config: GeolocationClientConfig) {\n // Convert GeolocationClientConfig to BaseClientConfig\n const baseConfig: BaseClientConfig = {\n baseURL: config.baseURL,\n tenantId: config.tenantId,\n apiKey: config.apiKey,\n headers: config.headers,\n timeout: config.timeout,\n retries: 3, // Default retry count for geolocation calls\n debug: config.debug,\n logger: config.logger,\n environment: config.environment,\n };\n super(baseConfig);\n }\n\n // ============================================================================\n // IP Verification & Compliance\n // ============================================================================\n\n /**\n * Verify an IP address and check compliance\n *\n * Uses requestWithRetry() for automatic retry on transient failures.\n *\n * @param request - Verification request with IP, user ID, event type, and optional device fingerprint\n * @returns Location verification result with risk assessment\n *\n * @example\n * ```typescript\n * const result = await client.verifyIP({\n * ip_address: \"8.8.8.8\",\n * user_id: \"user_123\",\n * event_type: \"login\",\n * device_fingerprint: {\n * device_id: \"device_abc\",\n * user_agent: navigator.userAgent,\n * platform: \"web\"\n * }\n * });\n *\n * if (result.is_blocked) {\n * console.log(\"Access blocked:\", result.risk_reasons);\n * }\n * ```\n */\n async verifyIP(request: VerifyIPRequest, requestOptions?: RequestOptions): Promise<LocationVerification> {\n // ip_address is optional: when omitted the server derives the connecting IP.\n // If a value is supplied it must be non-empty (empty string is a caller bug).\n if (request.ip_address !== undefined && !request.ip_address.trim()) {\n throw new ValidationError('ip_address, when provided, must be a non-empty string', ['ip_address']);\n }\n\n // Use requestWithRetry for critical verification calls\n return this.requestWithRetry<LocationVerification>('/api/v1/geo/verify', {\n method: 'POST',\n body: JSON.stringify(request),\n }, undefined, undefined, requestOptions);\n }\n\n /**\n * Check compliance for a specific country\n *\n * @param countryISO - ISO 3166-1 alpha-2 country code (e.g., \"US\", \"GB\")\n * @returns Jurisdiction configuration and compliance status\n *\n * @example\n * ```typescript\n * const compliance = await client.checkCompliance(\"KP\"); // North Korea\n * if (!compliance.is_compliant) {\n * console.log(\"Country is not allowed:\", compliance.jurisdiction?.status);\n * }\n * ```\n */\n async checkCompliance(countryISO: string, requestOptions?: RequestOptions): Promise<ComplianceCheckResponse> {\n return this.requestWithRetry<ComplianceCheckResponse>(\n `/api/v1/geo/check-compliance`,\n {\n method: 'POST',\n body: JSON.stringify({ country_iso: countryISO }),\n }, undefined, undefined, requestOptions\n );\n }\n\n // ============================================================================\n // GPS Configuration\n // ============================================================================\n\n /**\n * Get the tenant's GPS requirement configuration\n *\n * Returns which event types require GPS location to be collected.\n * Use this to auto-enable GPS collection in generateCipherText when required.\n *\n * @returns GPS requirement config per event type\n *\n * @example\n * ```typescript\n * const config = await client.getGPSConfig();\n * if (config.require_gps.login) {\n * // GPS is required for login — auto-enable location\n * }\n * ```\n */\n async getGPSConfig(requestOptions?: RequestOptions): Promise<GeolocationConfigResponse> {\n return this.requestWithRetry<GeolocationConfigResponse>('/api/v1/geo/config', undefined, undefined, undefined, requestOptions);\n }\n\n /**\n * Mint a short-lived, single-use device-signals nonce.\n *\n * The nonce is bound to the tenant, user, and event type and is consumed\n * server-side during validation, so a captured device-signals envelope cannot\n * be replayed. `validateCipherText` mints and attaches one automatically; call\n * this directly only if you manage the nonce yourself.\n *\n * @param userId - User ID the nonce is bound to\n * @param eventType - Event type the nonce is bound to (login, registration, ...)\n * @returns The nonce and its expiry\n */\n async fetchSignalsNonce(\n userId: string,\n eventType: CipherTextReason,\n requestOptions?: RequestOptions\n ): Promise<SignalsNonce> {\n if (!userId?.trim()) {\n throw new ValidationError('userId is required and must be a non-empty string', ['userId']);\n }\n // Single attempt (no retry): minting is on the validation critical path and\n // is best-effort — the server enforces when a nonce is required, so a retry\n // storm would only add latency.\n const request = { user_id: userId, event_type: eventType };\n return this.request<SignalsNonce>(\n '/api/v1/geo/signals-token',\n {\n method: 'POST',\n body: JSON.stringify(request),\n }, undefined, requestOptions\n );\n }\n\n /**\n * Best-effort nonce mint for validation. Returns undefined if minting fails —\n * the server is the sole authority and blocks when a nonce is required, so this\n * never downgrades security on the client's say-so.\n */\n private async resolveSignalsNonce(\n userId: string,\n eventType: CipherTextReason,\n requestOptions?: RequestOptions\n ): Promise<string | undefined> {\n try {\n const { nonce } = await this.fetchSignalsNonce(userId, eventType, requestOptions);\n return nonce;\n } catch (err) {\n this.logger.warn(\n `Failed to mint device-signals nonce; proceeding without it: ${err instanceof Error ? err.message : String(err)}`\n );\n return undefined;\n }\n }\n\n // ============================================================================\n // CipherText Validation\n // ============================================================================\n\n /**\n * Validate a cipherText generated by the frontend SDK\n *\n * The cipherText contains encrypted device fingerprint and optional location data.\n * This method decrypts and validates the data, returning device info, location,\n * and risk assessment.\n *\n * @param cipherText - The encrypted cipherText string from generateCipherText()\n * @param userId - User ID associated with this verification\n * @param eventType - Reason for verification (login, registration, etc.)\n * @param expectedIP - Optional expected IP address for additional validation\n * @param customerData - Optional customer data for risk profile creation (used when user is blocked)\n * @returns Validation result with device info, location, and risk assessment\n *\n * @example\n * ```typescript\n * // Validate cipherText during registration with customer data\n * const result = await client.validateCipherText(\n * cipherText,\n * \"user_123\",\n * \"registration\",\n * clientIP,\n * {\n * full_name: \"John Doe\",\n * email: \"john@example.com\",\n * country: \"US\",\n * state: \"CA\"\n * }\n * );\n *\n * if (!result.valid) {\n * console.log(\"CipherText validation failed:\", result.errors);\n * return;\n * }\n *\n * if (result.risk.is_blocked) {\n * console.log(\"Access blocked:\", result.risk.block_reasons);\n * // A risk profile with full customer data has been created for the alert\n * }\n * ```\n */\n async validateCipherText(\n cipherText: string,\n userId: string,\n eventType: CipherTextReason,\n expectedIP?: string,\n customerData?: CipherTextCustomerData,\n requestOptions?: RequestOptions\n ): Promise<ValidateCipherTextResponse> {\n if (!cipherText?.trim()) {\n throw new ValidationError('cipherText is required and must be a non-empty string', ['cipherText']);\n }\n if (!userId?.trim()) {\n throw new ValidationError('userId is required and must be a non-empty string', ['userId']);\n }\n\n const nonce = await this.resolveSignalsNonce(userId, eventType, requestOptions);\n\n const request: ValidateCipherTextRequest = {\n cipher_text: cipherText,\n user_id: userId,\n event_type: eventType,\n expected_ip: expectedIP,\n customer_data: customerData,\n nonce,\n };\n\n return this.requestWithRetry<ValidateCipherTextResponse>(\n '/api/v1/geo/validate-ciphertext',\n {\n method: 'POST',\n body: JSON.stringify(request),\n }, undefined, undefined, requestOptions\n );\n }\n\n /**\n * Validate cipherText and verify IP in a single call\n *\n * Combines cipherText validation with IP verification for complete\n * location and device verification in one request.\n *\n * @param cipherText - The encrypted cipherText string\n * @param ipAddress - Client IP address\n * @param userId - User ID\n * @param eventType - Event type (login, registration, etc.)\n * @returns Combined validation and verification result\n *\n * @example\n * ```typescript\n * const result = await client.validateAndVerify(\n * cipherText,\n * clientIP,\n * \"user_123\",\n * \"registration\"\n * );\n *\n * if (!result.ciphertext_valid) {\n * throw new Error(\"Device verification failed\");\n * }\n *\n * if (result.location.is_blocked) {\n * throw new Error(\"Location not allowed\");\n * }\n * ```\n */\n async validateAndVerify(\n cipherText: string,\n ipAddress: string,\n userId: string,\n eventType: CipherTextReason,\n requestOptions?: RequestOptions\n ): Promise<{\n ciphertext_valid: boolean;\n ciphertext_result: ValidateCipherTextResponse;\n location: LocationVerification;\n }> {\n // validate-ciphertext already performs full geo verification on the server\n // (IP lookup, risk scoring, alert triggering, device tracking). A separate\n // verifyIP call would create duplicate geolocation records and alerts.\n const cipherTextResult = await this.validateCipherText(\n cipherText,\n userId,\n eventType,\n ipAddress,\n undefined,\n requestOptions\n );\n\n // Build LocationVerification from the enriched ciphertext response.\n // If risk data is missing (partial response), fall back to verifyIP.\n const loc = cipherTextResult.location;\n const risk = cipherTextResult.risk;\n\n if (!risk) {\n const locationResult = await this.verifyIP({\n ip_address: ipAddress,\n user_id: userId,\n event_type: eventType,\n }, requestOptions);\n return {\n ciphertext_valid: cipherTextResult.valid,\n ciphertext_result: cipherTextResult,\n location: locationResult,\n };\n }\n\n const location: LocationVerification = {\n ip_address: cipherTextResult.ip_address,\n location: {\n country: loc?.country ?? '',\n country_iso: loc?.country_iso ?? '',\n city: loc?.city ?? '',\n region: loc?.region ?? '',\n postal_code: '',\n latitude: loc?.latitude ?? 0,\n longitude: loc?.longitude ?? 0,\n timezone: '',\n is_vpn: risk.is_vpn ?? false,\n is_proxy: risk.is_proxy ?? false,\n is_tor: risk.is_tor ?? false,\n is_hosting: risk.is_hosting ?? false,\n is_anonymizer: risk.is_vpn || risk.is_proxy || risk.is_tor,\n },\n is_compliant: cipherTextResult.is_compliant ?? !risk.is_blocked,\n is_blocked: risk.is_blocked ?? false,\n risk_level: risk.level ?? 'low',\n risk_score: risk.score ?? 0,\n risk_reasons: risk.is_blocked && risk.block_reasons\n ? risk.block_reasons\n : (risk.factors ?? []),\n risk_reasons_structured: risk.block_reasons_structured ?? [],\n jurisdiction: cipherTextResult.jurisdiction,\n geofence_evaluation: cipherTextResult.geofence_evaluation,\n record_id: cipherTextResult.record_id ?? '',\n gps_required: cipherTextResult.gps_required,\n };\n\n return {\n ciphertext_valid: cipherTextResult.valid,\n ciphertext_result: cipherTextResult,\n location,\n };\n }\n\n // ============================================================================\n // Location Request (Live Location Tracking)\n // ============================================================================\n\n /**\n * Create a location request to get customer's live location\n *\n * @param request - Location request details\n * @returns Location request result with share link\n *\n * @example\n * ```typescript\n * const result = await client.createLocationRequest({\n * user_id: \"customer_123\",\n * channel: \"sms\",\n * phone: \"+1234567890\",\n * reason: \"Verification for high-value transaction\"\n * });\n *\n * console.log(`Share link sent: ${result.share_link}`);\n * console.log(`Expires at: ${result.token_expiry}`);\n * ```\n */\n async createLocationRequest(\n request: CreateLocationRequestRequest,\n requestOptions?: RequestOptions\n ): Promise<LocationRequestResult> {\n return this.request<LocationRequestResult>('/api/v1/location-requests', {\n method: 'POST',\n body: JSON.stringify(request),\n }, undefined, requestOptions);\n }\n\n /**\n * Get a location request by ID\n *\n * @param requestId - Location request ID\n * @returns Location request details\n */\n async getLocationRequest(requestId: string, requestOptions?: RequestOptions): Promise<LocationRequest> {\n return this.request<LocationRequest>(`/api/v1/location-requests/${requestId}`, undefined, undefined, requestOptions);\n }\n\n /**\n * List location requests with filters and pagination\n *\n * @param filters - Optional filters\n * @param pagination - Optional pagination\n * @returns Paginated list of location requests\n *\n * @example\n * ```typescript\n * const requests = await client.listLocationRequests(\n * { status: \"completed\", user_id: \"customer_123\" },\n * { page: 1, limit: 20 }\n * );\n * ```\n */\n async listLocationRequests(\n filters?: LocationRequestFilters,\n pagination?: PaginationParams,\n requestOptions?: RequestOptions\n ): Promise<LocationRequestListResponse> {\n const params: Record<string, unknown> = {\n ...filters,\n ...pagination,\n };\n\n return this.request<LocationRequestListResponse>(\n `/api/v1/location-requests${this.buildQueryString(params)}`,\n undefined, undefined, requestOptions\n );\n }\n\n /**\n * Cancel a pending location request\n *\n * @param requestId - Location request ID\n */\n async cancelLocationRequest(requestId: string, requestOptions?: RequestOptions): Promise<void> {\n await this.request(`/api/v1/location-requests/${requestId}/cancel`, {\n method: 'POST',\n }, undefined, requestOptions);\n }\n\n /**\n * Resend notification for a location request\n *\n * @param requestId - Location request ID\n * @param contact - Email or phone to send to\n */\n async resendLocationRequest(\n requestId: string,\n contact: ResendLocationRequestRequest,\n requestOptions?: RequestOptions\n ): Promise<void> {\n await this.request(`/api/v1/location-requests/${requestId}/resend`, {\n method: 'POST',\n body: JSON.stringify(contact),\n }, undefined, requestOptions);\n }\n\n // ============================================================================\n // Location Share (Customer-facing - for SDK integration in customer apps)\n // ============================================================================\n\n /**\n * Get location share info (customer-facing)\n * This is called from the customer's device to get request details\n *\n * @param token - Secure token from share link\n * @returns Location share info\n */\n async getLocationShareInfo(token: string, requestOptions?: RequestOptions): Promise<LocationShareInfo> {\n return this.request<LocationShareInfo>(`/api/v1/location/share/${token}`, undefined, undefined, requestOptions);\n }\n\n /**\n * Submit location capture (customer-facing)\n * This is called from the customer's device to submit their location\n *\n * @param token - Secure token from share link\n * @param capture - Location capture data (GPS or WiFi)\n * @returns Capture response\n *\n * @example\n * ```typescript\n * // GPS (the web SDK is GPS + IP only; the server handles the IP fallback)\n * const result = await client.captureLocation(token, {\n * latitude: 37.7749,\n * longitude: -122.4194,\n * accuracy: 10\n * });\n * ```\n */\n async captureLocation(\n token: string,\n capture: LocationCaptureRequest,\n requestOptions?: RequestOptions\n ): Promise<LocationCaptureResponse> {\n return this.request<LocationCaptureResponse>(`/api/v1/location/share/${token}`, {\n method: 'POST',\n body: JSON.stringify(capture),\n }, undefined, requestOptions);\n }\n\n // ============================================================================\n // CipherText Generation\n // ============================================================================\n\n /**\n * Generate a device-signals envelope containing device and location data,\n * validated by the server.\n *\n * @param options - Options for envelope generation\n * @param gpsConfig - Optional GPS config (from getGPSConfig)\n * @returns The device-signals envelope result\n *\n * @example\n * ```typescript\n * const result = await client.generateCipherText({ reason: 'login' });\n * console.log(result.cipherText); // device-signals envelope\n * ```\n */\n async generateCipherText(\n options: Omit<CipherTextOptions, 'apiKey' | 'signingKey'>,\n gpsConfig?: GeolocationConfigResponse,\n ): Promise<CipherTextResult> {\n // The SDK never holds a signing key and never signs client-side — it just\n // collects the device-signals envelope (base64 JSON, not encrypted). The\n // server is the sole signer. GPS config is fetched to auto-enable location.\n const resolvedGpsConfig = gpsConfig ?? (await this.getGPSConfig());\n return generateCipherTextUtil(options, resolvedGpsConfig);\n }\n\n // ============================================================================\n // Utility Methods (inherited from BaseClient: healthCheck, updateConfig, getConfig, buildQueryString)\n // ============================================================================\n}\n","/**\n * RiskProfileClient - Customer Risk Profile Management\n *\n * Provides methods to create, retrieve, and manage customer risk profiles\n * in the Vesant Compliance Platform.\n */\n\nimport { BaseClient } from '../core/client';\nimport { VesantError } from '../core/errors';\nimport type { BaseClientConfig, RequestOptions } from '../core/config';\nimport type {\n CustomerProfile,\n CreateProfileRequest,\n UpdateProfileRequest,\n} from './types';\n\nexport class RiskProfileClient extends BaseClient {\n constructor(config: BaseClientConfig) {\n super(config);\n }\n\n // ============================================================================\n // Profile Management\n // ============================================================================\n\n /**\n * Create a new customer risk profile\n *\n * @param request - Profile creation data\n * @returns Created customer profile\n *\n * @example\n * ```typescript\n * const profile = await client.createProfile({\n * customer_id: 'CUST-12345',\n * entity_type: 'individual',\n * customer_status: 'active',\n * full_name: 'John Doe',\n * email_address: 'john@example.com',\n * date_of_birth: '1990-01-15',\n * country_of_residence: 'US'\n * });\n * ```\n */\n async createProfile(request: CreateProfileRequest, requestOptions?: RequestOptions): Promise<CustomerProfile> {\n return this.request<CustomerProfile>('/api/v1/profiles', {\n method: 'POST',\n body: JSON.stringify(request),\n }, undefined, requestOptions);\n }\n\n /**\n * Get customer profile by customer ID\n *\n * Note: This searches for the profile using the customer_id field.\n * Returns the first matching profile for the tenant.\n *\n * @param customerId - Customer ID to search for\n * @returns Customer profile\n *\n * @example\n * ```typescript\n * const profile = await client.getProfile('CUST-12345');\n * ```\n */\n async getProfile(customerId: string, requestOptions?: RequestOptions): Promise<CustomerProfile> {\n try {\n // Use the SDK-authenticated endpoint (API key auth)\n return await this.request<CustomerProfile>(\n `/api/v1/profiles?customer_id=${encodeURIComponent(customerId)}`,\n undefined, undefined, requestOptions\n );\n } catch (error) {\n // Normalize to NOT_FOUND for consistent error handling in getOrCreateProfile\n if (error instanceof VesantError && (error.statusCode === 404 || error.code === 'NOT_FOUND')) {\n throw new VesantError('Profile not found', 'NOT_FOUND', 404);\n }\n throw error;\n }\n }\n\n /**\n * Update customer profile\n *\n * @param profileId - Profile UUID\n * @param updates - Fields to update\n * @returns Updated customer profile\n *\n * @example\n * ```typescript\n * const updated = await client.updateProfile(profileId, {\n * location: 'New York, USA',\n * location_compliance: 'compliant',\n * last_recorded_activity: new Date().toISOString()\n * });\n * ```\n */\n async updateProfile(\n profileId: string,\n updates: UpdateProfileRequest,\n requestOptions?: RequestOptions\n ): Promise<CustomerProfile> {\n return this.request<CustomerProfile>(`/api/v1/profiles/${profileId}`, {\n method: 'PUT',\n body: JSON.stringify(updates),\n }, undefined, requestOptions);\n }\n\n /**\n * Get or create profile (idempotent operation)\n *\n * Attempts to get existing profile by customer_id, creates if not found.\n *\n * @param customerId - Customer ID\n * @param createRequest - Profile data to use if creating new profile\n * @returns Existing or newly created profile\n *\n * @example\n * ```typescript\n * const profile = await client.getOrCreateProfile('CUST-123', {\n * customer_id: 'CUST-123',\n * entity_type: 'individual',\n * full_name: 'John Doe',\n * email_address: 'john@example.com'\n * });\n * ```\n */\n async getOrCreateProfile(\n customerId: string,\n createRequest: CreateProfileRequest,\n requestOptions?: RequestOptions\n ): Promise<CustomerProfile> {\n try {\n return await this.getProfile(customerId, requestOptions);\n } catch (error) {\n // Only treat NOT_FOUND as \"profile doesn't exist\" — re-throw other errors\n if (error instanceof VesantError && error.code === 'NOT_FOUND') {\n return await this.createProfile(createRequest, requestOptions);\n }\n throw error;\n }\n }\n\n}\n","import type { BlockReason } from '../core/types';\n\nexport const sdkReasons = {\n // Jurisdiction\n jurisdictionBlocked: (country: string, countryISO: string): BlockReason => ({\n code: 'JURISDICTION_BLOCKED',\n message: 'Access from a blocked jurisdiction',\n metadata: { country, country_iso: countryISO },\n }),\n jurisdictionNonCompliant: (): BlockReason => ({\n code: 'JURISDICTION_NON_COMPLIANT',\n message: 'Location does not meet compliance requirements',\n }),\n jurisdictionRegistrationDenied: (): BlockReason => ({\n code: 'JURISDICTION_REGISTRATION_DENIED',\n message: 'Registration is not permitted in this jurisdiction',\n }),\n jurisdictionRestricted: (): BlockReason => ({\n code: 'JURISDICTION_RESTRICTED',\n message: 'Access from a restricted jurisdiction',\n }),\n\n // Risk\n riskCriticalLevel: (): BlockReason => ({\n code: 'RISK_CRITICAL_LEVEL',\n message: 'Risk assessment reached critical threshold',\n }),\n accountSuspended: (): BlockReason => ({\n code: 'RISK_ACCOUNT_SUSPENDED',\n message: 'Customer account is suspended',\n }),\n sanctionsMatch: (): BlockReason => ({\n code: 'RISK_SANCTIONS_MATCH',\n message: 'Customer profile matched against sanctions list',\n }),\n riskHighLocation: (): BlockReason => ({\n code: 'RISK_HIGH_LOCATION',\n message: 'High-risk geographic location',\n }),\n riskHighCustomer: (): BlockReason => ({\n code: 'RISK_HIGH_CUSTOMER',\n message: 'Customer flagged as high risk',\n }),\n\n // Device\n ciphertextInvalid: (): BlockReason => ({\n code: 'DEVICE_CIPHERTEXT_INVALID',\n message: 'Device verification payload failed validation',\n }),\n gpsIPMismatch: (): BlockReason => ({\n code: 'DEVICE_GPS_IP_MISMATCH',\n message: 'GPS location does not match IP-derived location',\n }),\n gpsRequired: (): BlockReason => ({\n code: 'DEVICE_GPS_REQUIRED',\n message: 'GPS verification is required but was not provided',\n }),\n\n // Transaction\n transactionHighAmount: (amount: number, currency: string, threshold: number): BlockReason => ({\n code: 'TRANSACTION_HIGH_AMOUNT',\n message: 'Transaction amount exceeds high-value threshold',\n metadata: { amount, currency, threshold },\n }),\n transactionElevatedAmount: (amount: number, currency: string, threshold: number): BlockReason => ({\n code: 'TRANSACTION_ELEVATED_AMOUNT',\n message: 'Transaction amount exceeds elevated-value threshold',\n metadata: { amount, currency, threshold },\n }),\n transactionJurisdictionLimit: (): BlockReason => ({\n code: 'TRANSACTION_JURISDICTION_LIMIT',\n message: 'Transaction amount exceeds jurisdiction limit',\n }),\n anonymizationDetected: (): BlockReason => ({\n code: 'NETWORK_ANONYMIZER_DETECTED',\n message: 'Anonymization tool detected',\n }),\n};\n","/**\n * Compliance orchestration types\n *\n * Types for unified compliance verification flows that combine\n * geolocation verification with customer risk profiling.\n */\n\nimport type { BlockReason } from '../core/types';\nimport type { LocationVerification, DeviceFingerprintRequest } from '../geolocation/types';\nimport type { ValidateCipherTextResponse } from '../geolocation/types';\nimport type { CustomerProfile, EntityType } from '../risk-profile/types';\n\n// ============================================================================\n// Registration Verification Types\n// ============================================================================\n\nexport interface RegistrationVerificationRequest {\n // Identity\n customerId: string;\n fullName: string;\n emailAddress: string;\n phoneNumber?: string;\n dateOfBirth?: string;\n address?: string;\n entityType?: EntityType;\n\n // Geolocation\n ipAddress: string;\n deviceFingerprint?: DeviceFingerprintRequest;\n cipherText?: string;\n\n // Additional data\n metadata?: Record<string, unknown>;\n}\n\nexport interface RegistrationVerificationResponse {\n allowed: boolean;\n geolocation: LocationVerification;\n profile: CustomerProfile | null;\n requiresKYC: boolean;\n requiresEDD: boolean;\n blockReasons: string[];\n blockReasonsStructured?: BlockReason[];\n processingTime: number;\n cipherTextValidation?: ValidateCipherTextResponse;\n}\n\n// ============================================================================\n// Login Verification Types\n// ============================================================================\n\nexport interface LoginVerificationRequest {\n customerId: string;\n ipAddress: string;\n deviceFingerprint?: DeviceFingerprintRequest;\n cipherText?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface LoginVerificationResponse {\n allowed: boolean;\n geolocation: LocationVerification;\n profile: CustomerProfile | null;\n requiresStepUp: boolean;\n blockReasons: string[];\n blockReasonsStructured?: BlockReason[];\n processingTime: number;\n cipherTextValidation?: ValidateCipherTextResponse;\n}\n\n// ============================================================================\n// Transaction Verification Types\n// ============================================================================\n\nexport interface TransactionVerificationRequest {\n customerId: string;\n ipAddress: string;\n amount: number;\n currency: string;\n transactionType?: 'deposit' | 'withdrawal' | 'bet' | 'transfer' | 'payout';\n deviceFingerprint?: DeviceFingerprintRequest;\n cipherText?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface TransactionVerificationResponse {\n allowed: boolean;\n geolocation: LocationVerification;\n profile: CustomerProfile | null;\n transactionRisk: TransactionRiskResult;\n requiresApproval: boolean;\n blockReasons: string[];\n blockReasonsStructured?: BlockReason[];\n processingTime: number;\n cipherTextValidation?: ValidateCipherTextResponse;\n}\n\nexport interface TransactionRiskResult {\n score: number;\n level: 'low' | 'medium' | 'high' | 'critical';\n factors: string[];\n factorsStructured?: BlockReason[];\n allowed: boolean;\n requiresManualReview: boolean;\n}\n\n// ============================================================================\n// Generic Event Verification Types\n// ============================================================================\n\nexport interface EventVerificationRequest {\n customerId: string;\n ipAddress: string;\n eventType: string;\n deviceFingerprint?: DeviceFingerprintRequest;\n cipherText?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface EventVerificationResponse {\n allowed: boolean;\n geolocation: LocationVerification;\n blockReasons: string[];\n blockReasonsStructured?: BlockReason[];\n processingTime: number;\n cipherTextValidation?: ValidateCipherTextResponse;\n}\n\n// ============================================================================\n// Currency Exchange Rates (for transaction risk calculation)\n// ============================================================================\n\nexport interface CurrencyRates {\n [currency: string]: number; // Rate to USD\n}\n\nexport const DEFAULT_CURRENCY_RATES: CurrencyRates = {\n USD: 1.0,\n EUR: 1.1,\n GBP: 1.27,\n CAD: 0.74,\n AUD: 0.66,\n JPY: 0.0067,\n CHF: 1.13,\n CNY: 0.14,\n INR: 0.012,\n BRL: 0.20,\n MXN: 0.058,\n ZAR: 0.055,\n};\n\n// ============================================================================\n// Location Request Types (re-exported from geolocation for convenience)\n// ============================================================================\n\nexport type {\n LocationRequest,\n LocationRequestStatus,\n LocationRequestChannel,\n CreateLocationRequestRequest,\n LocationRequestResult,\n LocationRequestFilters,\n LocationRequestListResponse,\n ResendLocationRequestRequest,\n LocationShareInfo,\n LocationCaptureRequest,\n LocationCaptureResponse,\n} from '../geolocation/types';\n\n// ============================================================================\n// Compliance-specific Location Request Types\n// ============================================================================\n\nexport interface ComplianceLocationRequestInput {\n /** Customer user ID to request location from */\n customerId: string;\n /** Notification channel to use */\n channel: 'sms' | 'email' | 'push';\n /** Reason for requesting location (for compliance/audit) */\n reason: string;\n /** Customer email (required for email channel) */\n email?: string;\n /** Customer phone (required for SMS channel) */\n phone?: string;\n /** Custom expiry time in hours (default: 24) */\n expiryHours?: number;\n}\n\nexport interface ComplianceLocationRequestResult {\n /** The created location request */\n request: import('../geolocation/types').LocationRequest;\n /** Shareable link for the customer */\n shareLink: string;\n /** Token expiration time */\n tokenExpiry: string;\n /** Customer profile (if available) */\n profile?: import('../risk-profile/types').CustomerProfile;\n}\n","/**\n * ComplianceClient - Unified Compliance Orchestration\n *\n * Main integration point for casino platforms. Orchestrates geolocation\n * verification with customer risk profiling for complete compliance coverage.\n *\n * SDK is the primary data injection point for compliance verification.\n */\n\nimport { GeolocationClient } from '../geolocation/client';\nimport { RiskProfileClient } from '../risk-profile/client';\nimport type { VesantConfig, Logger, RequestOptions, RequiredVesantConfig, RequestInterceptor } from '../core/config';\nimport type { BlockReason } from '../core/types';\nimport { ComplianceError, ValidationError, VesantError } from '../core/errors';\nimport { sdkReasons } from './block-reasons';\nimport { createConsoleLogger } from '../core/logger';\nimport type { JurisdictionConfig, LocationVerification, ValidateCipherTextResponse } from '../geolocation/types';\nimport type { CustomerProfile } from '../risk-profile/types';\nimport type {\n RegistrationVerificationRequest,\n RegistrationVerificationResponse,\n LoginVerificationRequest,\n LoginVerificationResponse,\n TransactionVerificationRequest,\n TransactionVerificationResponse,\n TransactionRiskResult,\n EventVerificationRequest,\n EventVerificationResponse,\n CurrencyRates,\n ComplianceLocationRequestInput,\n ComplianceLocationRequestResult,\n} from './types';\nimport { DEFAULT_CURRENCY_RATES } from './types';\nimport type {\n LocationRequest,\n LocationRequestFilters,\n LocationRequestListResponse,\n PaginationParams,\n} from '../geolocation/types';\n\nexport class ComplianceClient {\n private geoClient: GeolocationClient;\n private riskClient: RiskProfileClient;\n private config: RequiredVesantConfig;\n private logger: Logger;\n private currencyRates: CurrencyRates;\n private _currencyRatesCustomized: boolean = false;\n private _currencyRatesWarned: boolean = false;\n\n constructor(config: VesantConfig) {\n this.logger = config.logger || createConsoleLogger();\n const interceptors: RequestInterceptor[] = config.interceptors || [];\n this.config = {\n baseURL: config.baseURL,\n tenantId: config.tenantId,\n apiKey: config.apiKey || '',\n headers: config.headers || {},\n timeout: config.timeout || 10000,\n retries: config.retries || 3,\n debug: config.debug || false,\n autoCreateProfiles: config.autoCreateProfiles !== false, // default true\n syncMode: config.syncMode || 'sync',\n environment: config.environment,\n interceptors,\n logger: this.logger,\n };\n\n this.geoClient = new GeolocationClient({\n baseURL: this.config.baseURL,\n tenantId: this.config.tenantId,\n apiKey: this.config.apiKey,\n headers: this.config.headers,\n timeout: this.config.timeout,\n debug: this.config.debug,\n logger: this.logger,\n environment: this.config.environment,\n });\n\n this.riskClient = new RiskProfileClient({\n baseURL: this.config.baseURL,\n tenantId: this.config.tenantId,\n apiKey: this.config.apiKey,\n headers: this.config.headers,\n timeout: this.config.timeout,\n debug: this.config.debug,\n interceptors,\n logger: this.logger,\n environment: this.config.environment,\n });\n\n this.currencyRates = DEFAULT_CURRENCY_RATES;\n }\n\n // ============================================================================\n // Sub-Client Accessors\n // ============================================================================\n\n /** Get the underlying GeolocationClient for direct geolocation API access */\n getGeolocationClient(): GeolocationClient {\n return this.geoClient;\n }\n\n /** Get the underlying RiskProfileClient for direct risk profile API access */\n getRiskProfileClient(): RiskProfileClient {\n return this.riskClient;\n }\n\n // ============================================================================\n // Main Verification Methods\n // ============================================================================\n\n /**\n * Verify customer registration with automatic profile creation\n *\n * This is the primary integration point for new customer sign-ups.\n * Combines geolocation verification with customer risk profile creation.\n *\n * Important: Profile is only created if geolocation verification passes.\n * This prevents orphaned geolocation records when registration is blocked.\n *\n * @param request - Registration verification request\n * @returns Verification response with profile and compliance status\n *\n * @example\n * ```typescript\n * const result = await sdk.verifyAtRegistration({\n * customerId: 'CUST-12345',\n * fullName: 'John Doe',\n * emailAddress: 'john@example.com',\n * ipAddress: req.ip,\n * deviceFingerprint: getDeviceFingerprint()\n * });\n *\n * if (result.allowed) {\n * // Create account\n * console.log('Profile created:', result.profile);\n * if (result.requiresKYC) {\n * // Redirect to KYC flow\n * }\n * } else {\n * // Block registration\n * console.log('Blocked:', result.blockReasons);\n * }\n * ```\n */\n async verifyAtRegistration(\n request: RegistrationVerificationRequest,\n requestOptions?: RequestOptions\n ): Promise<RegistrationVerificationResponse> {\n const startTime = Date.now();\n\n // Validate required fields before making any API calls\n this.validateRegistrationRequest(request);\n\n let geoVerification: LocationVerification | null = null;\n let cipherTextResult: ValidateCipherTextResponse | undefined;\n\n try {\n if (this.config.debug) {\n this.logger.debug('Starting registration verification', { customerId: request.customerId });\n }\n\n // When cipherText is present, validate-ciphertext performs full geo verification\n // server-side. Calling verifyIP separately would create duplicate records/alerts.\n if (request.cipherText) {\n cipherTextResult = await this.executeCipherTextValidation(\n request.cipherText,\n request.customerId,\n 'registration',\n request.ipAddress,\n {\n full_name: request.fullName,\n email: request.emailAddress,\n phone: request.phoneNumber,\n date_of_birth: request.dateOfBirth,\n },\n requestOptions\n );\n geoVerification = (cipherTextResult && this.buildLocationFromCipherText(cipherTextResult, request.ipAddress))\n ?? await this.geoClient.verifyIP({\n ip_address: request.ipAddress,\n user_id: request.customerId,\n event_type: 'registration',\n device_fingerprint: request.deviceFingerprint,\n }, requestOptions);\n } else {\n geoVerification = await this.geoClient.verifyIP({\n ip_address: request.ipAddress,\n user_id: request.customerId,\n event_type: 'registration',\n device_fingerprint: request.deviceFingerprint,\n }, requestOptions);\n }\n\n // Step 2: Check if registration should be blocked BEFORE creating profile\n // This prevents orphaned geo records and ensures atomic behavior\n const structuredBlockReasons = this.evaluateRegistrationBlock(geoVerification, cipherTextResult);\n\n if (structuredBlockReasons.length > 0) {\n if (this.config.debug) {\n this.logger.debug('Registration blocked at geo stage', { blockReasons: structuredBlockReasons });\n }\n\n // Return early without creating profile - prevents orphaned records\n return {\n allowed: false,\n geolocation: geoVerification,\n profile: null,\n requiresKYC: false,\n requiresEDD: false,\n ...this.buildReasonTail(structuredBlockReasons, startTime, cipherTextResult),\n };\n }\n\n // Step 3: Create customer risk profile (only if geo passed)\n const profile = await this.riskClient.createProfile({\n customer_id: request.customerId,\n entity_type: request.entityType || 'individual',\n customer_status: 'active',\n full_name: request.fullName,\n email_address: request.emailAddress,\n primary_phone_number: request.phoneNumber,\n date_of_birth: request.dateOfBirth,\n residential_address: request.address,\n country_of_residence: geoVerification.location.country_iso,\n\n // Geolocation data\n location: `${geoVerification.location.city}, ${geoVerification.location.country}`,\n location_compliance: geoVerification.is_compliant ? 'compliant' : 'non-compliant',\n\n // Initial KYC status\n kyc_status: 'pending',\n }, requestOptions);\n\n // Step 4: Determine final status and requirements\n const requiresKYC = geoVerification.jurisdiction?.require_kyc || false;\n const requiresEDD = geoVerification.jurisdiction?.require_enhanced_verification || false;\n\n if (this.config.debug) {\n this.logger.debug('Registration verification complete', {\n allowed: true,\n requiresKYC,\n requiresEDD,\n });\n }\n\n return {\n allowed: true,\n geolocation: geoVerification,\n profile: profile,\n requiresKYC: requiresKYC,\n requiresEDD: requiresEDD,\n ...this.buildReasonTail([], startTime, cipherTextResult),\n };\n } catch (error) {\n if (this.config.debug) {\n this.logger.error('Registration verification failed', {\n code: error instanceof VesantError ? error.code : undefined,\n message: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n\n // Preserve DUPLICATE_PROFILE errors so callers can distinguish\n // duplicate registrations from other failures\n if (error instanceof VesantError && error.code === 'DUPLICATE_PROFILE') {\n throw error;\n }\n\n throw new ComplianceError(\n 'Registration verification failed',\n error instanceof Error ? error.message : undefined,\n geoVerification ? 'PROFILE_CREATION_FAILED' : 'GEO_VERIFICATION_FAILED'\n );\n }\n }\n\n /**\n * Evaluate if registration should be blocked based on geolocation verification\n *\n * Checks:\n * 1. General compliance status (is_compliant)\n * 2. Explicit block flag (is_blocked)\n * 3. Jurisdiction-specific registration allowance (allow_registration)\n * 4. Risk level thresholds\n *\n * @param geoVerification - Geolocation verification result\n * @returns Array of block reasons (empty if allowed)\n */\n private evaluateRegistrationBlock(\n geoVerification: LocationVerification,\n cipherTextResult?: ValidateCipherTextResponse\n ): BlockReason[] {\n const blockReasons: BlockReason[] = [];\n\n // Check if explicitly blocked — read from the structured parallel field\n if (geoVerification.is_blocked) {\n blockReasons.push(...(geoVerification.risk_reasons_structured ?? []));\n }\n\n // Check general compliance\n if (!geoVerification.is_compliant) {\n if (!blockReasons.some(r => r.code === 'JURISDICTION_NON_COMPLIANT')) {\n blockReasons.push(sdkReasons.jurisdictionNonCompliant());\n }\n }\n\n // CRITICAL: Check if registration is specifically allowed in this jurisdiction\n // Some jurisdictions may allow login but not new registrations\n const jurisdiction = geoVerification.jurisdiction;\n if (jurisdiction) {\n if (jurisdiction.allow_registration === false) {\n blockReasons.push(sdkReasons.jurisdictionRegistrationDenied());\n }\n\n // Check jurisdiction status for registration-specific blocks\n if (jurisdiction.status === 'blocked' || jurisdiction.status === 'sanctioned') {\n if (!blockReasons.some(r => r.code === 'JURISDICTION_BLOCKED')) {\n blockReasons.push(sdkReasons.jurisdictionBlocked(jurisdiction.country_name ?? '', jurisdiction.country_iso ?? ''));\n }\n }\n\n // Restricted jurisdictions need explicit registration permission\n if (jurisdiction.status === 'restricted' && jurisdiction.allow_registration === false) {\n if (!blockReasons.some(r => r.code === 'JURISDICTION_RESTRICTED')) {\n blockReasons.push(sdkReasons.jurisdictionRestricted());\n }\n }\n }\n\n // Check geofence rule evaluation — reasons is now string[], wrap each into a BlockReason\n if (geoVerification.geofence_evaluation?.blocked) {\n blockReasons.push(\n ...(geoVerification.geofence_evaluation.reasons ?? []).map(m => ({\n code: 'JURISDICTION_GEOFENCE_VIOLATION',\n message: m,\n }))\n );\n }\n\n // Critical risk level should block registration\n if (geoVerification.risk_level === 'critical') {\n if (!blockReasons.some(r => r.code === 'RISK_CRITICAL_LEVEL')) {\n blockReasons.push(sdkReasons.riskCriticalLevel());\n }\n }\n\n // CipherText-based blocks (only when cipherText was provided)\n if (cipherTextResult) {\n if (!cipherTextResult.valid) {\n blockReasons.push(sdkReasons.ciphertextInvalid());\n }\n if (cipherTextResult.risk?.is_blocked) {\n blockReasons.push(...(cipherTextResult.risk.block_reasons_structured ?? []));\n }\n // Note: risk.location_mismatch is intentionally NOT a hard block. The server\n // treats a GPS-vs-IP distance over its threshold as a risk factor only —\n // GeoIP city-level inaccuracies (e.g. ISP gateway geolocation) would otherwise\n // block legitimate registrations. Blocks follow the server's is_blocked.\n }\n\n // GPS required but no cipherText provided — block\n if (geoVerification.gps_required && !cipherTextResult) {\n blockReasons.push(sdkReasons.gpsRequired());\n }\n\n const seen = new Set<string>();\n return blockReasons.filter(r => {\n if (seen.has(r.code)) return false;\n seen.add(r.code);\n return true;\n });\n }\n\n /**\n * Validate registration request has all required fields\n *\n * @param request - Registration request to validate\n * @throws ValidationError if required fields are missing or invalid\n */\n private validateRegistrationRequest(request: RegistrationVerificationRequest): void {\n const errors: string[] = [];\n\n if (!request.customerId?.trim()) {\n errors.push('customerId is required');\n }\n\n if (!request.ipAddress?.trim()) {\n errors.push('ipAddress is required');\n } else if (!this.isValidIP(request.ipAddress)) {\n errors.push('ipAddress format is invalid');\n }\n\n if (!request.emailAddress?.trim()) {\n errors.push('emailAddress is required');\n } else if (!this.isValidEmail(request.emailAddress)) {\n errors.push('emailAddress format is invalid');\n }\n\n if (!request.fullName?.trim()) {\n errors.push('fullName is required');\n }\n\n if (errors.length > 0) {\n throw new ValidationError(`Invalid registration request: ${errors.join(', ')}`, errors);\n }\n }\n\n /**\n * Validate IP address format (IPv4 or IPv6)\n */\n private isValidIP(ip: string): boolean {\n // IPv4 pattern\n const ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;\n // Simplified IPv6 pattern (covers most common cases)\n const ipv6Regex = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|^::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,7}:$|^(?:[0-9a-fA-F]{1,4}:){0,6}::(?:[0-9a-fA-F]{1,4}:){0,5}[0-9a-fA-F]{1,4}$/;\n\n return ipv4Regex.test(ip) || ipv6Regex.test(ip);\n }\n\n /**\n * Validate email address format\n */\n private isValidEmail(email: string): boolean {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return emailRegex.test(email);\n }\n\n private validateLoginRequest(request: LoginVerificationRequest): void {\n const errors: string[] = [];\n\n if (!request.customerId?.trim()) {\n errors.push('customerId is required');\n }\n\n if (!request.ipAddress?.trim()) {\n errors.push('ipAddress is required');\n } else if (!this.isValidIP(request.ipAddress)) {\n errors.push('ipAddress format is invalid');\n }\n\n if (errors.length > 0) {\n throw new ValidationError(`Invalid login request: ${errors.join(', ')}`, errors);\n }\n }\n\n private validateTransactionRequest(request: TransactionVerificationRequest): void {\n const errors: string[] = [];\n\n if (!request.customerId?.trim()) {\n errors.push('customerId is required');\n }\n\n if (!request.ipAddress?.trim()) {\n errors.push('ipAddress is required');\n } else if (!this.isValidIP(request.ipAddress)) {\n errors.push('ipAddress format is invalid');\n }\n\n if (request.amount <= 0) {\n errors.push('amount must be greater than 0');\n }\n\n if (!request.currency?.trim()) {\n errors.push('currency is required');\n }\n\n if (errors.length > 0) {\n throw new ValidationError(`Invalid transaction request: ${errors.join(', ')}`, errors);\n }\n }\n\n private validateEventRequest(request: EventVerificationRequest): void {\n const errors: string[] = [];\n\n if (!request.customerId?.trim()) {\n errors.push('customerId is required');\n }\n\n if (!request.ipAddress?.trim()) {\n errors.push('ipAddress is required');\n } else if (!this.isValidIP(request.ipAddress)) {\n errors.push('ipAddress format is invalid');\n }\n\n if (!request.eventType?.trim()) {\n errors.push('eventType is required');\n }\n\n if (errors.length > 0) {\n throw new ValidationError(`Invalid event request: ${errors.join(', ')}`, errors);\n }\n }\n\n /**\n * Verify customer login with profile activity update\n *\n * Verifies geolocation and updates customer profile with latest activity.\n *\n * @param request - Login verification request\n * @returns Verification response with compliance status\n *\n * @example\n * ```typescript\n * const result = await sdk.verifyAtLogin({\n * customerId: 'CUST-12345',\n * ipAddress: req.ip,\n * deviceFingerprint: getDeviceFingerprint()\n * });\n *\n * if (result.allowed) {\n * // Allow login\n * if (result.requiresStepUp) {\n * // Trigger MFA or additional verification\n * }\n * } else {\n * // Block login\n * console.log('Blocked:', result.blockReasons);\n * }\n * ```\n */\n async verifyAtLogin(\n request: LoginVerificationRequest,\n requestOptions?: RequestOptions\n ): Promise<LoginVerificationResponse> {\n const startTime = Date.now();\n\n this.validateLoginRequest(request);\n\n try {\n if (this.config.debug) {\n this.logger.debug('Starting login verification', { customerId: request.customerId });\n }\n\n // Step 1: Verify geolocation, cipherText, and fetch profile in parallel.\n // When cipherText is present, validate-ciphertext performs full geo verification\n // server-side — calling verifyIP separately would create duplicate records/alerts.\n let cipherTextResult: ValidateCipherTextResponse | undefined;\n let geoVerification: LocationVerification;\n let profileResult: CustomerProfile | null;\n\n if (request.cipherText) {\n [cipherTextResult, profileResult] = await Promise.all([\n this.executeCipherTextValidation(\n request.cipherText, request.customerId, 'login', request.ipAddress,\n undefined, requestOptions\n ),\n this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null),\n ]);\n geoVerification = (cipherTextResult && this.buildLocationFromCipherText(cipherTextResult, request.ipAddress))\n ?? await this.geoClient.verifyIP({\n ip_address: request.ipAddress,\n user_id: request.customerId,\n event_type: 'login',\n device_fingerprint: request.deviceFingerprint,\n }, requestOptions);\n } else {\n [, geoVerification, profileResult] = await Promise.all([\n Promise.resolve(undefined),\n this.geoClient.verifyIP({\n ip_address: request.ipAddress,\n user_id: request.customerId,\n event_type: 'login',\n device_fingerprint: request.deviceFingerprint,\n }, requestOptions),\n this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null),\n ]);\n }\n\n // Step 2: Check if login should be blocked BEFORE creating/updating profile\n const loginBlockReasons = this.getBlockReasons(geoVerification, profileResult, cipherTextResult);\n const isBlocked =\n !geoVerification.is_compliant ||\n geoVerification.is_blocked ||\n !!(cipherTextResult?.risk?.is_blocked) ||\n cipherTextResult?.valid === false ||\n (geoVerification.gps_required && !cipherTextResult);\n\n if (isBlocked && !profileResult) {\n // Blocked and no existing profile — return without creating one\n return {\n allowed: false,\n geolocation: geoVerification,\n profile: null,\n requiresStepUp: false,\n ...this.buildReasonTail(loginBlockReasons, startTime, cipherTextResult),\n };\n }\n\n // Step 3: Get or create profile (only reached if not blocked, or profile already exists)\n let profile: CustomerProfile;\n if (profileResult) {\n profile = profileResult;\n\n // Update last activity and location\n if (!isBlocked && this.shouldUpdateProfile(profile, geoVerification.location.city)) {\n profile = await this.riskClient.updateProfile(profile.id, {\n last_recorded_activity: new Date().toISOString(),\n location: `${geoVerification.location.city}, ${geoVerification.location.country}`,\n location_compliance: geoVerification.is_compliant ? 'compliant' : 'non-compliant',\n }, requestOptions);\n }\n } else {\n // Profile doesn't exist - this shouldn't happen for login\n if (this.config.autoCreateProfiles && this.config.debug) {\n this.logger.warn('Profile not found for login, creating...');\n }\n profile = await this.createProfileFromGeo(request.customerId, geoVerification);\n }\n\n const requiresStepUp =\n geoVerification.risk_level === 'high' ||\n geoVerification.risk_level === 'critical' ||\n (cipherTextResult?.risk?.location_mismatch === true);\n\n const loginFinalStructured = isBlocked || profile.customer_status === 'suspended'\n ? this.getBlockReasons(geoVerification, profile, cipherTextResult)\n : [];\n return {\n allowed: !isBlocked && profile.customer_status !== 'suspended',\n geolocation: geoVerification,\n profile: profile,\n requiresStepUp: requiresStepUp,\n ...this.buildReasonTail(loginFinalStructured, startTime, cipherTextResult),\n };\n } catch (error) {\n throw new ComplianceError('Login verification failed', error instanceof Error ? error.message : undefined);\n }\n }\n\n /**\n * Verify transaction with amount-based risk assessment\n *\n * Combines geolocation verification with transaction amount analysis\n * and customer risk profile for comprehensive transaction screening.\n *\n * @param request - Transaction verification request\n * @returns Verification response with transaction risk assessment\n *\n * @example\n * ```typescript\n * const result = await sdk.verifyAtTransaction({\n * customerId: 'CUST-12345',\n * ipAddress: req.ip,\n * amount: 5000,\n * currency: 'USD',\n * transactionType: 'withdrawal',\n * deviceFingerprint: getDeviceFingerprint()\n * });\n *\n * if (result.allowed) {\n * // Process transaction\n * } else if (result.requiresApproval) {\n * // Queue for manual review\n * } else {\n * // Block transaction\n * console.log('Blocked:', result.blockReasons);\n * }\n * ```\n */\n async verifyAtTransaction(\n request: TransactionVerificationRequest,\n requestOptions?: RequestOptions\n ): Promise<TransactionVerificationResponse> {\n const startTime = Date.now();\n\n this.validateTransactionRequest(request);\n\n try {\n if (this.config.debug) {\n this.logger.debug('Starting transaction verification', {\n customerId: request.customerId,\n amount: request.amount,\n currency: request.currency,\n });\n }\n\n // Step 1: Verify geolocation, cipherText, and fetch profile in parallel.\n // When cipherText is present, validate-ciphertext performs full geo verification\n // server-side — calling verifyIP separately would create duplicate records/alerts.\n let cipherTextResult: ValidateCipherTextResponse | undefined;\n let geoVerification: LocationVerification;\n let profileResult: CustomerProfile | null;\n\n if (request.cipherText) {\n [cipherTextResult, profileResult] = await Promise.all([\n this.executeCipherTextValidation(\n request.cipherText, request.customerId, 'transaction', request.ipAddress,\n undefined, requestOptions\n ),\n this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null),\n ]);\n geoVerification = (cipherTextResult && this.buildLocationFromCipherText(cipherTextResult, request.ipAddress))\n ?? await this.geoClient.verifyIP({\n ip_address: request.ipAddress,\n user_id: request.customerId,\n event_type: 'transaction',\n device_fingerprint: request.deviceFingerprint,\n }, requestOptions);\n } else {\n [, geoVerification, profileResult] = await Promise.all([\n Promise.resolve(undefined),\n this.geoClient.verifyIP({\n ip_address: request.ipAddress,\n user_id: request.customerId,\n event_type: 'transaction',\n device_fingerprint: request.deviceFingerprint,\n }, requestOptions),\n this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null),\n ]);\n }\n\n // Step 2: Check if blocked before proceeding with risk calculation\n const geoBlocked =\n !geoVerification.is_compliant ||\n geoVerification.is_blocked ||\n !!(cipherTextResult?.risk?.is_blocked) ||\n cipherTextResult?.valid === false ||\n (geoVerification.gps_required && !cipherTextResult);\n\n if (geoBlocked && !profileResult) {\n // Blocked and no profile — return early without risk calculation\n const earlyStructured = this.getTransactionBlockReasons(\n geoVerification,\n { score: 0, level: 'low', factors: [], allowed: false, requiresManualReview: false },\n true,\n cipherTextResult\n );\n return {\n allowed: false,\n geolocation: geoVerification,\n profile: null,\n transactionRisk: { score: 0, level: 'low' as const, factors: [], allowed: false, requiresManualReview: false },\n requiresApproval: false,\n ...this.buildReasonTail(earlyStructured, startTime, cipherTextResult),\n };\n }\n\n if (!profileResult) {\n throw new ComplianceError('Customer profile not found', request.customerId);\n }\n const profile = profileResult;\n\n // Step 3: Calculate transaction risk\n const transactionRisk = this.calculateTransactionRisk(\n request.amount,\n request.currency,\n geoVerification,\n profile,\n cipherTextResult\n );\n\n // Step 4: Check jurisdiction limits\n const jurisdictionAllowed = this.checkJurisdictionLimits(\n request.amount,\n request.currency,\n geoVerification.jurisdiction\n );\n\n // Step 5: Determine if transaction is allowed\n const isAllowed =\n !geoBlocked &&\n jurisdictionAllowed &&\n transactionRisk.allowed &&\n profile.customer_status !== 'suspended';\n\n const txStructured = this.getTransactionBlockReasons(\n geoVerification, transactionRisk, jurisdictionAllowed, cipherTextResult\n );\n return {\n allowed: isAllowed,\n geolocation: geoVerification,\n profile: profile,\n transactionRisk: transactionRisk,\n requiresApproval: transactionRisk.requiresManualReview,\n ...this.buildReasonTail(txStructured, startTime, cipherTextResult),\n };\n } catch (error) {\n throw new ComplianceError('Transaction verification failed', error instanceof Error ? error.message : undefined);\n }\n }\n\n /**\n * Generic event verification (for other touchpoints)\n *\n * @param request - Event verification request\n * @returns Verification response\n */\n async verifyEvent(request: EventVerificationRequest, requestOptions?: RequestOptions): Promise<EventVerificationResponse> {\n const startTime = Date.now();\n\n this.validateEventRequest(request);\n\n // When cipherText is present, validate-ciphertext performs full geo verification\n // server-side — calling verifyIP separately would create duplicate records/alerts.\n let cipherTextResult: ValidateCipherTextResponse | undefined;\n let geoVerification: LocationVerification;\n\n if (request.cipherText) {\n cipherTextResult = await this.executeCipherTextValidation(\n request.cipherText, request.customerId, request.eventType, request.ipAddress,\n undefined, requestOptions\n );\n geoVerification = (cipherTextResult && this.buildLocationFromCipherText(cipherTextResult, request.ipAddress))\n ?? await this.geoClient.verifyIP({\n ip_address: request.ipAddress,\n user_id: request.customerId,\n event_type: request.eventType,\n device_fingerprint: request.deviceFingerprint,\n }, requestOptions);\n } else {\n geoVerification = await this.geoClient.verifyIP({\n ip_address: request.ipAddress,\n user_id: request.customerId,\n event_type: request.eventType,\n device_fingerprint: request.deviceFingerprint,\n }, requestOptions);\n }\n\n // Optionally update profile activity\n if (this.config.autoCreateProfiles) {\n try {\n const profile = await this.riskClient.getProfile(request.customerId, requestOptions);\n await this.riskClient.updateProfile(profile.id, {\n last_recorded_activity: new Date().toISOString(),\n }, requestOptions);\n } catch (error) {\n // Profile doesn't exist, ignore or create based on config\n if (this.config.debug) {\n this.logger.warn('Profile not found for event');\n }\n }\n }\n\n const cipherTextBlocked = cipherTextResult\n ? (!cipherTextResult.valid || cipherTextResult.risk?.is_blocked === true)\n : false;\n\n // Build structured block reasons from the structured parallel fields\n const structuredEventReasons: BlockReason[] = [...(geoVerification.risk_reasons_structured ?? [])];\n if (cipherTextResult) {\n if (!cipherTextResult.valid) {\n structuredEventReasons.push(sdkReasons.ciphertextInvalid());\n }\n if (cipherTextResult.risk?.is_blocked) {\n structuredEventReasons.push(...(cipherTextResult.risk.block_reasons_structured ?? []));\n }\n }\n\n // GPS required but no cipherText provided — block\n const gpsBlocked = geoVerification.gps_required && !cipherTextResult;\n if (gpsBlocked) {\n structuredEventReasons.push(sdkReasons.gpsRequired());\n }\n\n const seen = new Set<string>();\n const dedupedStructured = structuredEventReasons.filter(r => {\n if (seen.has(r.code)) return false;\n seen.add(r.code);\n return true;\n });\n\n return {\n allowed: geoVerification.is_compliant && !geoVerification.is_blocked && !cipherTextBlocked && !gpsBlocked,\n geolocation: geoVerification,\n ...this.buildReasonTail(dedupedStructured, startTime, cipherTextResult),\n };\n }\n\n // ============================================================================\n // Helper Methods\n // ============================================================================\n\n private buildReasonTail(\n structured: BlockReason[],\n startTime: number,\n cipherTextResult: ValidateCipherTextResponse | undefined,\n ) {\n return {\n blockReasons: structured.map(r => r.message),\n blockReasonsStructured: structured,\n processingTime: Date.now() - startTime,\n cipherTextValidation: cipherTextResult,\n };\n }\n\n private shouldUpdateProfile(profile: CustomerProfile, newCity: string): boolean {\n // Update if location changed significantly\n return !profile.location || !profile.location.includes(newCity);\n }\n\n private async createProfileFromGeo(\n customerId: string,\n geoVerification: LocationVerification,\n customerData?: {\n fullName?: string;\n email?: string;\n phone?: string;\n dateOfBirth?: string;\n }\n ): Promise<CustomerProfile> {\n // Warn if creating profile without proper customer data\n if (!customerData?.email || !customerData?.fullName) {\n this.logger.warn(\n 'Creating profile with incomplete data. ' +\n 'Profiles should be created during registration with complete customer information.'\n );\n }\n\n return this.riskClient.createProfile({\n customer_id: customerId,\n entity_type: 'individual',\n customer_status: 'active',\n full_name: customerData?.fullName || undefined,\n email_address: customerData?.email || '',\n primary_phone_number: customerData?.phone || undefined,\n date_of_birth: customerData?.dateOfBirth || undefined,\n location: `${geoVerification.location.city}, ${geoVerification.location.country}`,\n location_compliance: geoVerification.is_compliant ? 'compliant' : 'non-compliant',\n country_of_residence: geoVerification.location.country_iso,\n kyc_status: 'pending',\n });\n }\n\n /**\n * Execute cipherText validation with graceful degradation.\n * Returns undefined if cipherText is not provided or validation fails.\n */\n private async executeCipherTextValidation(\n cipherText: string | undefined,\n userId: string,\n eventType: 'registration' | 'login' | 'transaction' | string,\n ipAddress: string,\n customerData?: {\n full_name?: string;\n email?: string;\n phone?: string;\n date_of_birth?: string;\n },\n requestOptions?: RequestOptions\n ): Promise<ValidateCipherTextResponse | undefined> {\n if (!cipherText) return undefined;\n\n try {\n return await this.geoClient.validateCipherText(\n cipherText,\n userId,\n eventType as any,\n ipAddress,\n customerData,\n requestOptions\n );\n } catch (err) {\n this.logger.warn('CipherText validation failed, proceeding with IP-only', {\n error: err instanceof Error ? err.message : 'Unknown error',\n });\n return undefined;\n }\n }\n\n /**\n * Build a LocationVerification from a ValidateCipherTextResponse.\n * The validate-ciphertext endpoint now returns the full geo-verification data\n * (is_compliant, jurisdiction, geofence_evaluation, record_id, gps_required),\n * so a separate verifyIP call is unnecessary.\n */\n private buildLocationFromCipherText(ct: ValidateCipherTextResponse, ipAddress: string): LocationVerification | null {\n const loc = ct.location;\n const risk = ct.risk;\n if (!risk) return null;\n\n return {\n ip_address: ct.ip_address || ipAddress,\n location: {\n country: loc?.country ?? '',\n country_iso: loc?.country_iso ?? '',\n city: loc?.city ?? '',\n region: loc?.region ?? '',\n postal_code: '',\n latitude: loc?.latitude ?? 0,\n longitude: loc?.longitude ?? 0,\n timezone: '',\n is_vpn: risk.is_vpn,\n is_proxy: risk.is_proxy,\n is_tor: risk.is_tor,\n is_hosting: risk.is_hosting ?? false,\n is_anonymizer: risk.is_vpn || risk.is_proxy || risk.is_tor,\n },\n is_compliant: ct.is_compliant ?? !risk.is_blocked,\n is_blocked: risk.is_blocked,\n risk_level: risk.level,\n risk_score: risk.score,\n risk_reasons: [],\n risk_reasons_structured: risk.is_blocked && risk.block_reasons_structured\n ? risk.block_reasons_structured\n : [],\n jurisdiction: ct.jurisdiction,\n geofence_evaluation: ct.geofence_evaluation,\n record_id: ct.record_id ?? '',\n gps_required: ct.gps_required,\n };\n }\n\n private calculateTransactionRisk(\n amount: number,\n currency: string,\n geoVerification: LocationVerification,\n profile: CustomerProfile,\n cipherTextResult?: ValidateCipherTextResponse\n ): TransactionRiskResult {\n if (!this._currencyRatesCustomized && !this._currencyRatesWarned) {\n this._currencyRatesWarned = true;\n this.logger.warn(\n 'Using default currency exchange rates. ' +\n 'Call updateCurrencyRates() or fetchCurrencyRates() for accurate transaction risk calculation.'\n );\n }\n\n let riskScore = 0;\n const structuredFactors: BlockReason[] = [];\n\n // Amount-based risk (normalized to USD)\n const normalizedAmount = this.normalizeToUSD(amount, currency);\n if (normalizedAmount > 10000) {\n riskScore += 30;\n structuredFactors.push(sdkReasons.transactionHighAmount(normalizedAmount, currency, 10000));\n } else if (normalizedAmount > 5000) {\n riskScore += 15;\n structuredFactors.push(sdkReasons.transactionElevatedAmount(normalizedAmount, currency, 5000));\n }\n\n // Geo risk\n riskScore += geoVerification.risk_score * 0.4;\n if (geoVerification.risk_level === 'high' || geoVerification.risk_level === 'critical') {\n structuredFactors.push(sdkReasons.riskHighLocation());\n }\n\n // Profile risk\n riskScore += profile.risk_score * 0.3;\n if (profile.risk_category === 'high' || profile.risk_category === 'critical') {\n structuredFactors.push(sdkReasons.riskHighCustomer());\n }\n\n // VPN/anonymizer during transaction\n if (geoVerification.location.is_vpn || geoVerification.location.is_proxy) {\n riskScore += 20;\n structuredFactors.push(sdkReasons.anonymizationDetected());\n }\n\n // Suspended account\n if (profile.customer_status === 'suspended') {\n riskScore += 50;\n structuredFactors.push(sdkReasons.accountSuspended());\n }\n\n // CipherText risk factors\n if (cipherTextResult) {\n if (cipherTextResult.risk?.location_mismatch) {\n riskScore += 20;\n structuredFactors.push(sdkReasons.gpsIPMismatch());\n }\n if (cipherTextResult.risk?.score) {\n riskScore += cipherTextResult.risk.score * 0.2;\n }\n }\n\n return {\n score: Math.min(riskScore, 100),\n level: this.getRiskLevel(riskScore),\n factors: structuredFactors.map(r => r.message),\n factorsStructured: structuredFactors,\n allowed: riskScore < 70,\n requiresManualReview: riskScore >= 60 && riskScore < 70,\n };\n }\n\n private checkJurisdictionLimits(\n amount: number,\n currency: string,\n jurisdiction?: JurisdictionConfig\n ): boolean {\n if (!jurisdiction || !jurisdiction.max_transaction_amount) {\n return true;\n }\n\n const normalizedAmount = this.normalizeToUSD(amount, currency);\n return normalizedAmount <= jurisdiction.max_transaction_amount;\n }\n\n private normalizeToUSD(amount: number, currency: string): number {\n const rate = this.currencyRates[currency.toUpperCase()] || 1;\n return amount * rate;\n }\n\n private getRiskLevel(score: number): 'low' | 'medium' | 'high' | 'critical' {\n if (score >= 80) return 'critical';\n if (score >= 60) return 'high';\n if (score >= 40) return 'medium';\n return 'low';\n }\n\n private getBlockReasons(\n geoVerification: LocationVerification,\n profile: CustomerProfile | null,\n cipherTextResult?: ValidateCipherTextResponse\n ): BlockReason[] {\n const reasons: BlockReason[] = [];\n\n if (geoVerification.is_blocked) {\n reasons.push(...(geoVerification.risk_reasons_structured ?? []));\n }\n\n if (profile) {\n if (profile.customer_status === 'suspended') {\n reasons.push(sdkReasons.accountSuspended());\n }\n\n if (profile.has_sanctions) {\n reasons.push(sdkReasons.sanctionsMatch());\n }\n }\n\n if (cipherTextResult) {\n if (!cipherTextResult.valid) {\n reasons.push(sdkReasons.ciphertextInvalid());\n }\n if (cipherTextResult.risk?.is_blocked) {\n reasons.push(...(cipherTextResult.risk.block_reasons_structured ?? []));\n }\n }\n\n // GPS required but no cipherText provided — block\n if (geoVerification.gps_required && !cipherTextResult) {\n reasons.push(sdkReasons.gpsRequired());\n }\n\n const seen = new Set<string>();\n return reasons.filter(r => {\n if (seen.has(r.code)) return false;\n seen.add(r.code);\n return true;\n });\n }\n\n private getTransactionBlockReasons(\n geoVerification: LocationVerification,\n transactionRisk: TransactionRiskResult,\n jurisdictionAllowed: boolean,\n cipherTextResult?: ValidateCipherTextResponse\n ): BlockReason[] {\n const reasons: BlockReason[] = [];\n\n if (!geoVerification.is_compliant) {\n reasons.push(sdkReasons.jurisdictionNonCompliant());\n }\n\n if (!jurisdictionAllowed) {\n reasons.push(sdkReasons.transactionJurisdictionLimit());\n }\n\n if (!transactionRisk.allowed) {\n reasons.push(...(transactionRisk.factorsStructured ?? []));\n }\n\n if (cipherTextResult) {\n if (!cipherTextResult.valid) {\n reasons.push(sdkReasons.ciphertextInvalid());\n }\n if (cipherTextResult.risk?.is_blocked) {\n reasons.push(...(cipherTextResult.risk.block_reasons_structured ?? []));\n }\n }\n\n // GPS required but no cipherText provided — block\n if (geoVerification.gps_required && !cipherTextResult) {\n reasons.push(sdkReasons.gpsRequired());\n }\n\n const seen = new Set<string>();\n return reasons.filter(r => {\n if (seen.has(r.code)) return false;\n seen.add(r.code);\n return true;\n });\n }\n\n // ============================================================================\n // Location Request Methods\n // ============================================================================\n\n /**\n * Request live location from a customer\n *\n * Creates a location request and sends a notification to the customer\n * via the specified channel (SMS, email, or push). The customer receives\n * a link to share their location.\n *\n * @param input - Location request details\n * @returns Location request result with share link\n *\n * @example\n * ```typescript\n * // Request location via SMS for transaction verification\n * const result = await sdk.requestCustomerLocation({\n * customerId: 'CUST-12345',\n * channel: 'sms',\n * phone: '+1234567890',\n * reason: 'Verification required for high-value transaction'\n * });\n *\n * console.log('Share link sent:', result.shareLink);\n * console.log('Expires at:', result.tokenExpiry);\n *\n * // Request location via email\n * const emailResult = await sdk.requestCustomerLocation({\n * customerId: 'CUST-12345',\n * channel: 'email',\n * email: 'customer@example.com',\n * reason: 'Account verification',\n * expiryHours: 48\n * });\n * ```\n */\n async requestCustomerLocation(\n input: ComplianceLocationRequestInput,\n requestOptions?: RequestOptions\n ): Promise<ComplianceLocationRequestResult> {\n if (this.config.debug) {\n this.logger.debug('Creating location request for customer', { customerId: input.customerId });\n }\n\n // Validate input\n this.validateLocationRequestInput(input);\n\n // Get customer profile if available\n let profile: CustomerProfile | undefined;\n try {\n profile = await this.riskClient.getProfile(input.customerId, requestOptions);\n } catch (error) {\n if (this.config.debug) {\n this.logger.warn('Customer profile not found', { customerId: input.customerId });\n }\n }\n\n // Use profile data if contact info not provided\n const phone = input.phone || profile?.primary_phone_number;\n const email = input.email || profile?.email_address;\n\n // Create the location request\n const result = await this.geoClient.createLocationRequest({\n user_id: input.customerId,\n channel: input.channel,\n reason: input.reason,\n phone: phone,\n email: email,\n expiry_hours: input.expiryHours,\n }, requestOptions);\n\n if (this.config.debug) {\n this.logger.debug('Location request created', {\n requestId: result.request.id,\n channel: input.channel,\n expiresAt: result.token_expiry,\n });\n }\n\n return {\n request: result.request,\n shareLink: result.share_link,\n tokenExpiry: result.token_expiry,\n profile: profile,\n };\n }\n\n /**\n * Get a specific location request by ID\n *\n * @param requestId - Location request ID\n * @returns Location request details\n *\n * @example\n * ```typescript\n * const request = await sdk.getLocationRequest('req_abc123');\n * console.log('Status:', request.status);\n * if (request.latitude && request.longitude) {\n * console.log('Location captured:', request.latitude, request.longitude);\n * }\n * ```\n */\n async getLocationRequest(requestId: string, requestOptions?: RequestOptions): Promise<LocationRequest> {\n return this.geoClient.getLocationRequest(requestId, requestOptions);\n }\n\n /**\n * List location requests with filters and pagination\n *\n * @param filters - Optional filters\n * @param pagination - Optional pagination\n * @returns Paginated list of location requests\n *\n * @example\n * ```typescript\n * // Get pending requests for a customer\n * const pending = await sdk.listLocationRequests(\n * { status: 'pending', user_id: 'CUST-12345' },\n * { page: 1, limit: 20 }\n * );\n *\n * // Get all completed requests from last week\n * const completed = await sdk.listLocationRequests({\n * status: 'completed',\n * date_from: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString()\n * });\n * ```\n */\n async listLocationRequests(\n filters?: LocationRequestFilters,\n pagination?: PaginationParams,\n requestOptions?: RequestOptions\n ): Promise<LocationRequestListResponse> {\n return this.geoClient.listLocationRequests(filters, pagination, requestOptions);\n }\n\n /**\n * Cancel a pending location request\n *\n * @param requestId - Location request ID\n *\n * @example\n * ```typescript\n * await sdk.cancelLocationRequest('req_abc123');\n * ```\n */\n async cancelLocationRequest(requestId: string, requestOptions?: RequestOptions): Promise<void> {\n if (this.config.debug) {\n this.logger.debug('Cancelling location request', { requestId });\n }\n await this.geoClient.cancelLocationRequest(requestId, requestOptions);\n }\n\n /**\n * Resend notification for a location request\n *\n * @param requestId - Location request ID\n * @param contact - Contact details (email or phone)\n *\n * @example\n * ```typescript\n * // Resend to a different phone number\n * await sdk.resendLocationRequest('req_abc123', { phone: '+0987654321' });\n *\n * // Resend to email\n * await sdk.resendLocationRequest('req_abc123', { email: 'new@example.com' });\n * ```\n */\n async resendLocationRequest(\n requestId: string,\n contact: { email?: string; phone?: string },\n requestOptions?: RequestOptions\n ): Promise<void> {\n if (this.config.debug) {\n this.logger.debug('Resending location request', { requestId });\n }\n await this.geoClient.resendLocationRequest(requestId, contact, requestOptions);\n }\n\n /**\n * Validate location request input\n */\n private validateLocationRequestInput(input: ComplianceLocationRequestInput): void {\n const errors: string[] = [];\n\n if (!input.customerId?.trim()) {\n errors.push('customerId is required');\n }\n\n if (!input.channel) {\n errors.push('channel is required');\n }\n\n if (!input.reason?.trim()) {\n errors.push('reason is required for compliance/audit purposes');\n }\n\n // Channel-specific validation\n if (input.channel === 'sms' && !input.phone) {\n errors.push('phone is required for SMS channel');\n }\n\n if (input.channel === 'email' && !input.email) {\n errors.push('email is required for email channel');\n }\n\n if (errors.length > 0) {\n throw new ValidationError(`Invalid location request: ${errors.join(', ')}`, errors);\n }\n }\n\n // ============================================================================\n // Configuration\n // ============================================================================\n\n /**\n * Update currency exchange rates\n *\n * Use this to keep currency rates current for accurate transaction risk\n * calculation. Rates should be updated regularly (e.g., daily).\n *\n * @param rates - Currency to USD exchange rates\n *\n * @example\n * ```typescript\n * // Update specific rates\n * sdk.updateCurrencyRates({\n * EUR: 1.08,\n * GBP: 1.25,\n * BTC: 42000, // For crypto support\n * });\n *\n * // Or fetch from external service\n * const rates = await fetchExchangeRates();\n * sdk.updateCurrencyRates(rates);\n * ```\n */\n updateCurrencyRates(rates: CurrencyRates): void {\n this.currencyRates = { ...this.currencyRates, ...rates };\n this._currencyRatesCustomized = true;\n }\n\n /**\n * Get current currency rates\n *\n * @returns Current currency to USD exchange rates\n */\n getCurrencyRates(): Readonly<CurrencyRates> {\n return { ...this.currencyRates };\n }\n\n}\n","/**\n * KycClient - TypeScript SDK for Vesant KYC (Know Your Customer) Service\n *\n * Provides type-safe methods to interact with the KYC service API.\n * Extends BaseClient for consistent retry logic, timeout handling, and error management.\n */\n\nimport { BaseClient } from '../core/client';\nimport { ValidationError } from '../core/errors';\nimport type { BaseClientConfig, RequestOptions } from '../core/config';\nimport type {\n KycClientConfig,\n KycRequest,\n KycRequestFilters,\n KycRequestListResponse,\n DocumentVerificationRequest,\n DocumentVerificationResponse,\n UpdateKycStatusRequest,\n RequestAdditionalDocumentsRequest,\n RequestKycSubmitLinkRequest,\n RequestKycSubmitLinkResponse,\n CheckKycStatusRequest,\n CheckKycStatusResponse,\n ProofDownloadURL,\n KycOverview,\n KycAlert,\n KycAlertFilters,\n KycAlertListResponse,\n UpdateKycAlertRequest,\n KycPreferences,\n UpdateKycPreferencesRequest,\n PaginationParams,\n CustomerProfile,\n CustomerProfileFilters,\n CustomerProfileListResponse,\n CreateCustomerProfileRequest,\n CreateEventBasedFaceVerificationSessionRequest,\n CreateEventBasedFaceVerificationSessionResponse,\n SubmitEventBasedFaceVerificationSessionRequest,\n EventBasedFaceVerificationCallback,\n KycHandoffSession,\n} from './types';\n\n/** Helper to add filter value to params, joining arrays with commas */\nfunction addFilterParam(\n params: Record<string, unknown>,\n key: string,\n value: string | string[] | undefined\n): void {\n if (value !== undefined) {\n params[key] = Array.isArray(value) ? value.join(',') : value;\n }\n}\n\n/** Helper to add simple filter values to params */\nfunction addSimpleParams(\n params: Record<string, unknown>,\n source: Record<string, unknown>,\n keys: string[]\n): void {\n for (const key of keys) {\n if (source[key] !== undefined) {\n params[key] = source[key];\n }\n }\n}\n\n/**\n * KycClient extends BaseClient for:\n * - Consistent retry logic with exponential backoff\n * - Unified error handling (VesantError, NetworkError, TimeoutError, etc.)\n * - Automatic timeout management\n * - Debug logging\n *\n * Read calls use requestWithRetry() to ride out transient failures.\n * Calls that create or bill something (submit link, document submit,\n * face session, face submit, hosted journey retry) are made exactly once.\n */\nexport class KycClient extends BaseClient {\n private userId?: string;\n private readonly riskProfileBaseURL?: string;\n\n constructor(config: KycClientConfig) {\n // Convert KycClientConfig to BaseClientConfig\n const baseConfig: BaseClientConfig = {\n baseURL: config.baseURL,\n tenantId: config.tenantId,\n apiKey: config.apiKey,\n headers: config.headers,\n timeout: config.timeout,\n retries: 3, // Default retry count for KYC calls\n debug: config.debug,\n environment: config.environment,\n };\n super(baseConfig);\n this.userId = config.userId;\n this.riskProfileBaseURL = config.riskProfileBaseURL;\n }\n\n /**\n * Set the user ID for operations requiring user context\n */\n setUserId(userId: string): void {\n this.userId = userId;\n }\n\n /**\n * Get current user ID\n */\n getUserId(): string | undefined {\n return this.userId;\n }\n\n /**\n * Build headers including user ID if available\n */\n private getUserHeaders(): Record<string, string> {\n const headers: Record<string, string> = {};\n if (this.userId) {\n headers['X-User-ID'] = this.userId;\n }\n return headers;\n }\n\n // ============================================================================\n // Document Verification\n // ============================================================================\n\n /**\n * Request a KYC submission redirect URL for a user\n *\n * Generates a link that the user can visit to submit their KYC documents.\n *\n * Pass the `trigger_event` that matches the user action so the tenant's\n * trigger preferences decide whether verification is required; inspect\n * `kyc_required` and `reason` on the response before redirecting.\n *\n * Optionally pass the customer's registered identity data as\n * `customer_data` (same shape as the geolocation `customer_data` block).\n * It seeds the customer's risk profile so document verification can\n * cross-check the submitted document against trusted reference data;\n * fields never overwrite data already on the profile.\n *\n * The call is made once and is not retried: each request creates a new\n * KYC record and link, so a retry after a timeout would leave duplicates.\n *\n * @param request - Request containing the user ID, trigger event, optional redirect URL, optional callback URL (receives POST requests), and optional customer identity data\n * @returns Response containing the redirect link, KYC ID, `kyc_required`, `can_skip` and `reason`\n *\n * @example\n * ```typescript\n * const result = await client.requestKycSubmitLink({\n * user_id: \"user_123\",\n * trigger_event: \"onboarding\",\n * redirect_url: \"https://merchant.com/kyc-complete\", // optional\n * callback_url: \"https://merchant.com/api/kyc-webhook\", // optional - receives POST requests on status change\n * customer_data: { // optional - seeds the risk profile for document cross-checks\n * full_name: \"John Doe\",\n * date_of_birth: \"1999-06-02\", // ISO 8601\n * email: \"john@example.com\",\n * phone: \"+94771234567\",\n * address: \"12 Main St, Colombo\", // used for address verification\n * country: \"LK\"\n * }\n * });\n *\n * if (!result.kyc_required) return proceed();\n * console.log(`Redirect user to: ${result.link}`);\n * console.log(`KYC ID: ${result.kyc_id}`);\n * ```\n */\n async requestKycSubmitLink(\n request: RequestKycSubmitLinkRequest,\n requestOptions?: RequestOptions\n ): Promise<RequestKycSubmitLinkResponse> {\n // One-shot: creating a submit link inserts a KYC row and issues a link\n // on every call, and the platform does not replay this route from an\n // idempotency key, so an automatic retry would create duplicates.\n return this.request<RequestKycSubmitLinkResponse>('/api/v1/kyc/request', {\n method: 'POST',\n body: JSON.stringify(request),\n headers: this.getUserHeaders(),\n }, undefined, requestOptions);\n }\n\n /**\n * Create a Event-Based Face Verification session.\n *\n * Inspect the response before showing UI:\n * - `is_required === false` → skip face verification; `reason` explains why.\n * - `verification_url` present → embed the hosted journey and poll status.\n * - `verification_url` absent → use the local camera / QR fallback.\n *\n * @param request - Reference, customer_id, event, amount (for threshold events), optional URLs.\n */\n async createEventBasedFaceVerificationSession(request: CreateEventBasedFaceVerificationSessionRequest): Promise<CreateEventBasedFaceVerificationSessionResponse> {\n // One-shot: do NOT use requestWithRetry. Creating a session is a\n // non-idempotent POST that allocates server-side state (DB row + Redis\n // handoff). Retrying on timeout would create duplicate sessions and\n // burn provider references on the follow-up submit.\n return this.request<CreateEventBasedFaceVerificationSessionResponse>('/api/v1/kyc/face/session', {\n method: 'POST',\n body: JSON.stringify(request),\n headers: this.getUserHeaders(),\n });\n }\n\n /**\n * Submit a real-time face capture for an active Event-Based Face Verification session.\n *\n * Works from any device: the platform does not inspect the User-Agent.\n * `FaceCaptureModal` decides between direct capture and the QR handoff\n * on the client; custom UIs may submit from desktop or mobile alike.\n *\n * The `data` field on the response carries `retries_remaining`,\n * `retry_limit_exceeded`, and the reaction flags (`enforce_logout`,\n * `freeze_account`, etc.) so the tenant app can act on a final failure.\n *\n * @param request - Token from `createEventBasedFaceVerificationSession`, plus the base64 selfie.\n */\n async submitEventBasedFaceVerificationSession(request: SubmitEventBasedFaceVerificationSessionRequest, requestOptions?: RequestOptions): Promise<EventBasedFaceVerificationCallback> {\n // One-shot: do NOT use requestWithRetry. Submitting a selfie is a\n // non-idempotent POST — every call uploads the image, calls the\n // provider (billable), and increments the `attempts` counter on the\n // session row. Retries on transient errors would burn attempts and\n // produce multiple provider responses for one user action. Manual retries\n // (user clicks \"Try again\" in the modal) re-call this method\n // explicitly, which is the right surface for the retry decision.\n return this.request<EventBasedFaceVerificationCallback>('/api/v1/kyc/face/submit', {\n method: 'POST',\n body: JSON.stringify(request),\n headers: this.getUserHeaders(),\n }, undefined, requestOptions);\n }\n\n /**\n * Look up the current state of a Event-Based Face Verification session by its\n * session token. Useful for desktop pollers waiting on the mobile handoff.\n *\n * The lookup is scoped by the unguessable, server-issued session token (not\n * the enumerable forward reference): the endpoint is public/unauthenticated,\n * and scoping by the token is what prevents cross-tenant status reads.\n *\n * @param token - The session token returned by `createEventBasedFaceVerificationSession`.\n */\n async getEventBasedFaceVerificationSessionStatus(token: string): Promise<EventBasedFaceVerificationCallback> {\n return this.requestWithRetry<EventBasedFaceVerificationCallback>(`/api/v1/kyc/face/verify/${encodeURIComponent(token)}`, {\n method: 'GET',\n headers: this.getUserHeaders(),\n });\n }\n\n /**\n * Mint a fresh hosted verification journey for the next attempt on an\n * active session whose previous hosted-journey attempt was declined.\n * Only valid while the session is active and attempts remain; the\n * response carries the new `verification_url` to embed. Used internally\n * by `FaceCaptureModal`'s Try Again flow in hosted-journey mode.\n *\n * @param token - The session token returned by `createEventBasedFaceVerificationSession`.\n */\n async retryEventBasedFaceVerificationJourney(token: string): Promise<CreateEventBasedFaceVerificationSessionResponse> {\n return this.request<CreateEventBasedFaceVerificationSessionResponse>('/api/v1/kyc/face/onsite/journey', {\n method: 'POST',\n body: JSON.stringify({ token }),\n headers: this.getUserHeaders(),\n });\n }\n\n /**\n * Fetch the Redis-backed handoff session for a token. Same backing\n * store as normal KYC (`kyc:session:<token>`, 15-minute TTL). The\n * Event-Based Face Verification database session still expires after\n * 10 minutes. Desktop callers poll `mobile_connected` to detect when a\n * mobile device has scanned the QR and attached.\n *\n * @param token - The session token returned by `createEventBasedFaceVerificationSession`.\n */\n async getHandoffSession(token: string): Promise<KycHandoffSession> {\n return this.request<KycHandoffSession>(\n `/api/v1/kyc/session${this.buildQueryString({ token })}`,\n { headers: this.getUserHeaders() }\n );\n }\n\n /**\n * Attach a mobile device to a desktop-initiated session. The mobile\n * client calls this after scanning the QR code. The desktop poller\n * sees `mobile_connected: true` on the next `getHandoffSession`.\n *\n * @param token - The session token transferred via the QR payload.\n * @param isDisconnect - Pass true to release the session (default false).\n */\n async connectMobileSession(token: string, isDisconnect = false): Promise<{ mobile_connected: boolean }> {\n return this.request<{ mobile_connected: boolean }>('/api/v1/kyc/session/connect', {\n method: 'PUT',\n body: JSON.stringify({ token, is_disconnect: isDisconnect }),\n headers: this.getUserHeaders(),\n });\n }\n /**\n * Check KYC status for a user\n *\n * Returns the current KYC status:\n * - \"accepted\" / \"review.pending\" → verified (limited access while under review)\n * - \"pending\" → documents submitted, verification running: keep polling\n * - \"awaiting_kyc\" → nothing submitted yet; check `link_expired` before\n * re-surfacing or re-requesting the link. Never treat as in progress.\n * - \"declined\" → show `additional_data.declined_reasons` (fallback\n * `declined_reason`) with a retry option\n *\n * @param request - Request containing user_id and kyc_id\n * @returns Response with status, verification flags and, once terminal, the full record in `additional_data`\n *\n * @example\n * ```typescript\n * const result = await client.checkKycStatus({\n * user_id: \"user_123\",\n * kyc_id: \"550e8400-e29b-41d4-a716-446655440000\"\n * });\n *\n * if (result.status === 'accepted' || result.status === 'review.pending') {\n * // Grant access\n * } else if (result.status === 'declined') {\n * const reasons = result.additional_data?.declined_reasons;\n * // Show error + retry option\n * } else if (result.status === 'awaiting_kyc') {\n * // Prompt to verify; request a new link when result.link_expired is true\n * } else {\n * // Keep polling\n * }\n * ```\n */\n async checkKycStatus(\n request: CheckKycStatusRequest\n ): Promise<CheckKycStatusResponse> {\n const params = {\n user_id: request.user_id,\n kyc_id: request.kyc_id,\n };\n\n return this.requestWithRetry<CheckKycStatusResponse>(\n `/api/v1/kyc/request/status${this.buildQueryString(params)}`,\n {\n method: 'GET',\n headers: this.getUserHeaders(),\n }\n );\n }\n\n /**\n * Submit a document verification request with OCR\n *\n * The call is made once and is not retried: every submission is processed\n * and billed, and the platform does not replay this route from an\n * idempotency key. Retry explicitly if the request fails.\n *\n * @param request - Document verification request with documents and customer info\n * @returns Verification response with status and reference\n *\n * @example\n * ```typescript\n * const result = await client.submitVerification({\n * reference: \"4d2aff34-ab86-422d-992e-50b1234a5b67\",\n * email: \"customer@example.com\",\n * country: \"US\",\n * document: {\n * proof: base64EncodedImage,\n * selected_type: [\"id_card\", \"passport\"],\n * name: { first_name: \"John\", last_name: \"Doe\" },\n * dob: \"1990-01-15\"\n * },\n * face: {\n * proof: base64EncodedSelfie\n * }\n * });\n *\n * console.log(`Verification submitted: ${result.reference}`);\n * ```\n */\n async submitVerification(\n request: DocumentVerificationRequest,\n requestOptions?: RequestOptions\n ): Promise<DocumentVerificationResponse> {\n // One-shot: a document submission is billable and non-idempotent.\n return this.request<DocumentVerificationResponse>('/api/v1/kyc/submit', {\n method: 'POST',\n body: JSON.stringify(request),\n headers: this.getUserHeaders(),\n }, undefined, requestOptions);\n }\n\n /**\n * Get a KYC request by ID\n *\n * @param id - KYC request ID\n * @returns KYC request details including proofs and alerts\n *\n * @example\n * ```typescript\n * const kyc = await client.getKycRequest(\"550e8400-e29b-41d4-a716-446655440000\");\n * console.log(`Status: ${kyc.status}, ID Verified: ${kyc.id_verified}`);\n * ```\n */\n async getKycRequest(id: string): Promise<KycRequest> {\n return this.request<KycRequest>(`/api/v1/kyc/requests/${id}`);\n }\n\n /**\n * List KYC requests with filters and pagination\n *\n * @param filters - Optional filters (status, search, date range)\n * @param pagination - Optional pagination (page, page_size)\n * @returns Paginated list of KYC requests\n *\n * @example\n * ```typescript\n * const requests = await client.listKycRequests(\n * { status: \"pending\", search: \"john\" },\n * { page: 1, page_size: 20 }\n * );\n * console.log(`Found ${requests.total} pending requests`);\n * ```\n */\n async listKycRequests(\n filters?: KycRequestFilters,\n pagination?: PaginationParams\n ): Promise<KycRequestListResponse> {\n const params: Record<string, unknown> = {};\n\n if (filters) {\n addFilterParam(params, 'status', filters.status);\n addSimpleParams(params, filters as unknown as Record<string, unknown>, ['search', 'fromDate', 'toDate', 'sortBy', 'order']);\n }\n\n if (pagination) {\n if (pagination.page) params.page = pagination.page;\n if (pagination.page_size) params.limit = pagination.page_size;\n }\n\n return this.request<KycRequestListResponse>(\n `/api/v1/kyc/requests${this.buildQueryString(params)}`,\n { headers: this.getUserHeaders() }\n );\n }\n\n /**\n * Update KYC request status (accept/decline)\n *\n * @param request - Status update request with reference, status, and reason\n *\n * @example\n * ```typescript\n * // Accept a KYC request\n * await client.updateKycStatus({\n * reference: \"kyc-ref-123\",\n * status: \"accepted\",\n * reason: \"All documents verified successfully\"\n * });\n *\n * // Decline a KYC request\n * await client.updateKycStatus({\n * reference: \"kyc-ref-456\",\n * status: \"declined\",\n * reason: \"Document expired\"\n * });\n * ```\n */\n async updateKycStatus(request: UpdateKycStatusRequest): Promise<void> {\n await this.request('/api/v1/kyc/status', {\n method: 'PUT',\n body: JSON.stringify(request),\n headers: this.getUserHeaders(),\n });\n }\n\n /**\n * Request additional documents from customer\n *\n * @deprecated The platform does not expose this operation; the call always\n * fails. Request additional documents from the Vesant console instead.\n * This method will be removed in a future release.\n *\n * @param request - Request with KYC ID and document types needed\n *\n * @example\n * ```typescript\n * await client.requestAdditionalDocuments({\n * id: \"550e8400-e29b-41d4-a716-446655440000\",\n * document_types: [\"address\", \"document_two\"],\n * message: \"Please provide proof of address and secondary ID\"\n * });\n * ```\n */\n async requestAdditionalDocuments(\n request: RequestAdditionalDocumentsRequest\n ): Promise<void> {\n await this.request('/api/v1/kyc/requests', {\n method: 'PUT',\n body: JSON.stringify(request),\n headers: this.getUserHeaders(),\n });\n }\n\n /**\n * Get downloadable URLs for KYC proofs/documents\n *\n * @param kycId - KYC request ID\n * @returns Array of proof download URLs with expiration\n *\n * @example\n * ```typescript\n * const proofs = await client.getProofDownloadURLs(\"550e8400-e29b-41d4-a716-446655440000\");\n * proofs.forEach(proof => {\n * console.log(`${proof.type}: ${proof.url} (expires: ${proof.expires_at})`);\n * });\n * ```\n */\n async getProofDownloadURLs(kycId: string): Promise<ProofDownloadURL[]> {\n return this.request<ProofDownloadURL[]>(\n `/api/v1/kyc/proofs/${kycId}`,\n { headers: this.getUserHeaders() }\n );\n }\n\n // ============================================================================\n // KYC Overview & Statistics\n // ============================================================================\n\n /**\n * Get KYC overview statistics\n *\n * @param fromDate - Optional start date (ISO 8601)\n * @param toDate - Optional end date (ISO 8601)\n * @returns KYC statistics including counts by status\n *\n * @example\n * ```typescript\n * const overview = await client.getOverview(\n * \"2024-01-01T00:00:00Z\",\n * \"2024-12-31T23:59:59Z\"\n * );\n * console.log(`Total: ${overview.total}, Pending: ${overview.pending}`);\n * console.log(`Approved: ${overview.approved}, Rejected: ${overview.rejected}`);\n * ```\n */\n async getOverview(fromDate?: string, toDate?: string): Promise<KycOverview> {\n const params: Record<string, unknown> = {};\n if (fromDate) params.fromDate = fromDate;\n if (toDate) params.toDate = toDate;\n\n return this.request<KycOverview>(\n `/api/v1/kyc/overview${this.buildQueryString(params)}`\n );\n }\n\n // ============================================================================\n // Alert Management\n // ============================================================================\n\n /**\n * Get a KYC alert by ID\n *\n * @param alertId - Alert ID\n * @returns Alert details\n */\n async getAlert(alertId: string): Promise<KycAlert> {\n return this.request<KycAlert>(`/api/v1/kyc/alerts/${alertId}`);\n }\n\n /**\n * List KYC alerts with filters and pagination\n *\n * @param filters - Optional filters (status, risk, alert_type, assigned_for, etc.)\n * @param pagination - Optional pagination (page, page_size)\n * @returns Paginated list of alerts\n *\n * @example\n * ```typescript\n * const alerts = await client.listAlerts(\n * {\n * status: [\"pending\", \"in_progress\"],\n * risk: \"critical\",\n * alert_type: \"kyc\"\n * },\n * { page: 1, page_size: 20 }\n * );\n * console.log(`Found ${alerts.total} alerts`);\n * ```\n */\n async listAlerts(\n filters?: KycAlertFilters,\n pagination?: PaginationParams\n ): Promise<KycAlertListResponse> {\n const params: Record<string, unknown> = {};\n\n if (filters) {\n // Array filters that need comma joining\n addFilterParam(params, 'kyc_id', filters.kyc_id);\n addFilterParam(params, 'alert_type', filters.alert_type);\n addFilterParam(params, 'assigned_for', filters.assigned_for);\n addFilterParam(params, 'status', filters.status);\n addFilterParam(params, 'risk', filters.risk);\n // Simple filters\n addSimpleParams(params, filters as unknown as Record<string, unknown>, ['search', 'fromDate', 'toDate', 'sort_by', 'order']);\n }\n\n if (pagination) {\n if (pagination.page) params.page = pagination.page;\n if (pagination.page_size) params.limit = pagination.page_size;\n }\n\n return this.request<KycAlertListResponse>(\n `/api/v1/kyc/alerts${this.buildQueryString(params)}`\n );\n }\n\n /**\n * Update a KYC alert\n *\n * @param alertId - Alert ID\n * @param update - Fields to update (status, assigned_for, reason, alert_type)\n *\n * @example\n * ```typescript\n * // Assign an alert\n * await client.updateAlert(\"alert_123\", {\n * assigned_for: \"analyst_user_id\",\n * status: \"in_progress\"\n * });\n *\n * // Resolve an alert\n * await client.updateAlert(\"alert_123\", {\n * status: \"resolved\",\n * reason: \"Customer verified via phone call\"\n * });\n *\n * // Escalate an alert\n * await client.updateAlert(\"alert_123\", {\n * status: \"escalated\",\n * assigned_for: \"manager_user_id\",\n * reason: \"Requires senior review - suspicious documents\"\n * });\n * ```\n */\n async updateAlert(alertId: string, update: UpdateKycAlertRequest): Promise<void> {\n await this.request(`/api/v1/kyc/alerts/${alertId}`, {\n method: 'PUT',\n body: JSON.stringify(update),\n headers: this.getUserHeaders(),\n });\n }\n\n // ============================================================================\n // KYC Preferences\n // ============================================================================\n\n /**\n * Get KYC preferences for the tenant\n *\n * @returns KYC preferences configuration\n *\n * @example\n * ```typescript\n * const prefs = await client.getPreferences();\n * console.log(`Face verification required: ${prefs.is_face_verification_required}`);\n * console.log(`Required documents: ${prefs.required_document_count}`);\n * ```\n */\n async getPreferences(): Promise<KycPreferences> {\n return this.request<KycPreferences>('/api/v1/kyc/preferences');\n }\n\n /**\n * Update KYC preferences for the tenant\n *\n * @deprecated KYC preferences are managed in the Vesant console; the\n * platform exposes no update operation to the SDK, so this call always\n * fails. Use `getPreferences()` to read them. This method will be removed\n * in a future release.\n *\n * @param update - Fields to update\n * @returns Updated preferences\n *\n * @example\n * ```typescript\n * await client.updatePreferences({\n * is_face_verification_required: true,\n * is_address_verification_required: true,\n * required_document_count: 2,\n * reasons: [\n * \"Documents verified\",\n * \"Identity confirmed\",\n * \"Address matched\"\n * ]\n * });\n * ```\n */\n async updatePreferences(\n update: UpdateKycPreferencesRequest\n ): Promise<KycPreferences> {\n return this.request<KycPreferences>('/api/v1/kyc/preferences', {\n method: 'PUT',\n body: JSON.stringify(update),\n });\n }\n\n // ============================================================================\n // Customer Profile Management (Risk Profile Service)\n // ============================================================================\n\n /**\n * Make a request to the Risk Profile Service\n * Uses riskProfileBaseURL if configured, otherwise falls back to baseURL\n */\n private async riskProfileRequest<T>(\n path: string,\n options: RequestInit = {}\n ): Promise<T> {\n if (!this.riskProfileBaseURL) {\n throw new ValidationError(\n 'Risk Profile Service URL not configured. Please provide riskProfileBaseURL in KycClientConfig.',\n ['riskProfileBaseURL']\n );\n }\n\n return this.request<T>(path, {\n ...options,\n headers: {\n ...this.getUserHeaders(),\n ...(options.headers as Record<string, string>),\n },\n }, this.riskProfileBaseURL);\n }\n\n /**\n * List customer profiles for the tenant\n *\n * @param filters - Optional filters (risk_category, entity_type, status, search, etc.)\n * @param pagination - Optional pagination (limit, offset)\n * @returns Paginated list of customer profiles\n *\n * @example\n * ```typescript\n * const profiles = await client.listCustomerProfiles(\n * { risk_category: 'high', entity_type: 'individual' },\n * { limit: 20, offset: 0 }\n * );\n * console.log(`Found ${profiles.total} profiles`);\n * profiles.profiles.forEach(p => console.log(p.customer_id, p.full_name));\n * ```\n */\n async listCustomerProfiles(\n filters?: CustomerProfileFilters,\n pagination?: { limit?: number; offset?: number }\n ): Promise<CustomerProfileListResponse> {\n const params: Record<string, unknown> = {};\n\n if (filters) {\n // Array filters (keep as arrays for this API)\n if (filters.risk_category) {\n params.risk_category = Array.isArray(filters.risk_category)\n ? filters.risk_category\n : [filters.risk_category];\n }\n if (filters.entity_type) {\n params.entity_type = Array.isArray(filters.entity_type)\n ? filters.entity_type\n : [filters.entity_type];\n }\n if (filters.status) {\n params.status = Array.isArray(filters.status)\n ? filters.status\n : [filters.status];\n }\n // Simple filters\n addSimpleParams(params, filters as unknown as Record<string, unknown>, [\n 'search', 'is_pep', 'has_sanctions', 'requires_edd', 'sort_by', 'sort_order'\n ]);\n }\n\n if (pagination) {\n addSimpleParams(params, pagination, ['limit', 'offset']);\n }\n\n return this.riskProfileRequest<CustomerProfileListResponse>(\n `/api/v1/risk-dashboard/profiles${this.buildQueryString(params)}`\n );\n }\n\n /**\n * Get a customer profile by ID\n *\n * @param profileId - The profile UUID\n * @returns Customer profile details\n *\n * @example\n * ```typescript\n * const profile = await client.getCustomerProfile('uuid-here');\n * console.log(`Customer: ${profile.full_name}, Risk: ${profile.risk_category}`);\n * ```\n */\n async getCustomerProfile(profileId: string): Promise<CustomerProfile> {\n return this.riskProfileRequest<CustomerProfile>(\n `/api/v1/risk-dashboard/profiles/${profileId}`\n );\n }\n\n /**\n * Create a new customer profile\n *\n * A customer profile must exist before submitting KYC verification.\n * The customer_id field will be used as the 'reference' in KYC submissions.\n *\n * @param profile - Customer profile data\n * @returns Created customer profile\n *\n * @example\n * ```typescript\n * const profile = await client.createCustomerProfile({\n * customer_id: 'cust_123',\n * entity_type: 'individual',\n * full_name: 'John Doe',\n * email_address: 'john@example.com',\n * country_of_residence: 'US'\n * });\n * console.log(`Created profile: ${profile.id}`);\n *\n * // Now you can submit KYC using the customer_id as reference\n * await client.submitVerification({\n * reference: profile.customer_id, // 'cust_123'\n * email: 'john@example.com',\n * // ... other fields\n * });\n * ```\n */\n async createCustomerProfile(\n profile: CreateCustomerProfileRequest\n ): Promise<CustomerProfile> {\n return this.riskProfileRequest<CustomerProfile>('/api/v1/profiles', {\n method: 'POST',\n body: JSON.stringify(profile),\n });\n }\n\n // ============================================================================\n // Utility Methods (inherited from BaseClient: healthCheck, updateConfig, getConfig, buildQueryString)\n // ============================================================================\n}\n","/**\n * TypeScript type definitions for Vesant KYC Service API\n *\n * These types match the Go API structures in:\n * - services/kyc-service/internal/domain/\n * - services/kyc-service/internal/service/\n * - services/kyc-service/internal/handler/\n */\n\nimport type { PaginationParams, RiskLevel, Reason } from '../core/types';\n\n// Re-export commonly used types from core\nexport type { PaginationParams, RiskLevel };\n\n// ============================================================================\n// KYC Status & Enumerations\n// ============================================================================\n\nexport type KycStatus =\n /** Submit link issued but the customer has not submitted documents yet — not \"in progress\". */\n | 'awaiting_kyc'\n /** Documents submitted, verification in progress. */\n | 'pending'\n | 'accepted'\n | 'declined'\n | 'review.pending'\n | 'unknown';\n\nexport type KycDeclinedCode =\n | 'KYC_DOCUMENT_EXPIRED'\n | 'KYC_DOCUMENT_INVALID'\n | 'KYC_FACE_MISMATCH'\n | 'KYC_AGE_REQUIREMENT'\n | 'KYC_DUPLICATE_IDENTITY'\n | 'KYC_ADDRESS_MISMATCH'\n | 'KYC_NAME_MISMATCH'\n | 'KYC_PROVIDER_REJECTED'\n | 'KYC_DECLINED';\n\nexport const KYC_DECLINED_DESCRIPTIONS: Record<KycDeclinedCode, string> = {\n KYC_DOCUMENT_EXPIRED: 'The submitted document has expired',\n KYC_DOCUMENT_INVALID: 'The submitted document could not be verified',\n KYC_FACE_MISMATCH: 'Face verification did not match the identity document',\n KYC_AGE_REQUIREMENT: 'Age requirement not met',\n KYC_DUPLICATE_IDENTITY: 'This identity has already been verified under another account',\n KYC_ADDRESS_MISMATCH: 'Address verification failed',\n KYC_NAME_MISMATCH: 'Name on document does not match the registered name',\n KYC_PROVIDER_REJECTED: 'Identity verification was rejected by the verification provider',\n KYC_DECLINED: 'Identity verification was declined',\n};\n\nexport type KycAlertStatus = 'pending' | 'in_progress' | 'resolved' | 'closed' | 'escalated';\n\nexport type KycAlertType = 'kyc' | 'fraud';\n\nexport type DocumentType = 'id_card' | 'driving_license' | 'passport';\n\nexport type ProofType =\n | 'document'\n | 'document_two'\n | 'face'\n | 'address'\n | 'additional_document';\n\nexport type SupportedDocumentType = 'id_card' | 'passport' | 'driving_license';\n\n/** Document types a tenant can accept as proof of address. */\nexport type SupportedAddressDocumentType =\n | 'id_card'\n | 'passport'\n | 'driving_license'\n | 'utility_bill'\n | 'bank_statement'\n | 'rent_agreement'\n | 'employer_letter'\n | 'insurance_agreement'\n | 'tax_bill'\n | 'envelope'\n | 'cpr_smart_card_reader_copy'\n | 'property_tax'\n | 'lease_agreement'\n | 'insurance_card'\n | 'permanent_residence_permit'\n | 'credit_card_statement'\n | 'insurance_policy'\n | 'e_commerce_receipt'\n | 'bank_letter_receipt'\n | 'birth_certificate'\n | 'salary_slip';\n\n// ============================================================================\n// KYC Request Types\n// ============================================================================\n\nexport interface KycRequest {\n id: string;\n reference: string;\n forward_reference?: string;\n tenant_id: string;\n first_name: string;\n middle_name?: string;\n last_name: string;\n dob?: string;\n full_address?: string;\n email?: string;\n\n // Details extracted from the primary document (present once verification has run)\n gender?: string;\n height?: string;\n country?: string;\n country_code?: string;\n nationality?: string;\n authority?: string;\n document_type?: string;\n document_number?: string;\n personal_number?: string;\n place_of_birth?: string;\n issue_date?: string;\n expiry_date?: string;\n age?: number;\n\n // Details extracted from the secondary document, when one was required\n document_two_type?: string;\n document_two_number?: string;\n document_two_first_name?: string;\n document_two_middle_name?: string;\n document_two_last_name?: string;\n document_two_dob?: string;\n document_two_gender?: string;\n document_two_height?: string;\n document_two_country?: string;\n document_two_country_code?: string;\n document_two_nationality?: string;\n document_two_authority?: string;\n document_two_personal_number?: string;\n document_two_place_of_birth?: string;\n document_two_issue_date?: string;\n document_two_expiry_date?: string;\n\n // Verification Status Flags\n id_verified: boolean;\n address_verified: boolean;\n face_verified: boolean;\n age_verified: boolean;\n\n // Overall Status\n status: KycStatus;\n location?: string;\n identity_hash?: string;\n /** True when verification could not run because of an internal failure. */\n is_internal_error?: boolean;\n /** The `trigger_event` the submit link was requested with. */\n event?: string;\n\n // Preferences at time of submission\n required_document_count: number;\n supported_document_types?: SupportedDocumentType[];\n supported_address_document_types?: SupportedAddressDocumentType[];\n is_id_verification_required: boolean;\n is_face_verification_required: boolean;\n is_address_verification_required: boolean;\n is_age_verification_required: boolean;\n\n // URLs\n callback_url: string;\n redirect_url?: string;\n\n // Reasons & Warnings\n /** Structured decline reasons. Present when status is `declined`. */\n declined_reasons?: Reason[];\n /** Structured, non-blocking warnings. */\n warning_reasons?: Reason[];\n /** @deprecated Use {@link declined_reasons}. Comma-joined message text. */\n declined_reason?: string;\n /** @deprecated Use the `code` on {@link declined_reasons}. */\n declined_code?: KycDeclinedCode;\n accepted_reason?: string;\n other_reason?: string;\n /** @deprecated Use {@link warning_reasons}. */\n warnings?: Record<string, Record<string, string>>;\n\n // Block Action\n /**\n * Tenant app should block onboarding/the action when true. Set when a\n * failed verification matches a per-event KYC alert rule with the `block`\n * reaction; sticky once set (a later non-blocking update won't clear it).\n */\n block: boolean;\n /**\n * Names the configured verification that triggered the block (e.g.\n * `document_verification`, `face_verification`, `address_verification`,\n * `age_verification`). Empty when {@link block} is false.\n */\n block_reason?: string;\n\n // Relationships\n proofs?: Proof[];\n alerts?: KycAlert[];\n risk_profile?: KycCustomerProfile;\n\n created_at: string;\n updated_at: string;\n}\n\nexport interface Proof {\n id: string;\n kyc_id: string;\n type: ProofType;\n document: string;\n document_number?: string;\n created_at: string;\n}\n\nexport interface ProofDownloadURL {\n type: ProofType;\n url: string;\n expires_at: string;\n}\n\n// ============================================================================\n// KYC Customer Profile (Risk Profile Reference)\n// ============================================================================\n\nexport interface KycCustomerProfile {\n id: string;\n tenant_id: string;\n customer_id: string;\n first_name?: string;\n last_name?: string;\n email?: string;\n risk_score: number;\n risk_level: RiskLevel;\n kyc_status?: string;\n pep_status?: boolean;\n sanctions_status?: boolean;\n created_at: string;\n updated_at: string;\n}\n\n// ============================================================================\n// KYC Alert Types\n// ============================================================================\n\nexport interface KycAlert {\n id: string;\n kyc_id: string;\n tenant_id: string;\n alert_type: KycAlertType;\n alert_text: string;\n risk: RiskLevel;\n assigned_for?: string;\n reason?: string;\n status: KycAlertStatus;\n created_at: string;\n updated_at: string;\n}\n\nexport interface KycAlertFilters {\n kyc_id?: string | string[];\n alert_type?: KycAlertType | KycAlertType[];\n assigned_for?: string | string[];\n status?: KycAlertStatus | KycAlertStatus[];\n risk?: RiskLevel | RiskLevel[];\n search?: string;\n fromDate?: string;\n toDate?: string;\n sort_by?: string;\n order?: 'ASC' | 'DESC';\n}\n\nexport interface KycAlertListResponse {\n alerts: KycAlert[];\n pagination: KycPagination;\n}\n\nexport interface UpdateKycAlertRequest {\n assigned_for?: string;\n reason?: string;\n alert_type?: KycAlertType;\n status?: KycAlertStatus;\n}\n\n// ============================================================================\n// KYC Preferences Types\n// ============================================================================\n\n/**\n * Threshold-gated trigger for transaction events. Each rule is\n * self-contained — there is no umbrella flag.\n *\n * - `enabled=false` → event blocked.\n * - `enabled=true`, `threshold=0` (or null/omitted) → every event of this\n * type triggers Event-Based Face Verification, regardless of amount.\n * - `enabled=true`, `threshold>0` → only amounts `>= threshold` trigger.\n */\nexport interface EventBasedFaceVerificationThresholdTrigger {\n enabled: boolean;\n /** USD threshold; 0 / null / omitted means \"any amount\". */\n threshold: number;\n}\n\n/**\n * Rate-of-occurrence trigger (used by `high_frequency_betting`). The\n * tenant tells the server how many events have happened over how many\n * minutes via the request body (`event_count`, `event_window_minutes`);\n * the server triggers when `event_count >= count` AND\n * `event_window_minutes <= window_minutes`. Either bound of 0 means\n * \"don't enforce that bound\".\n */\nexport interface EventBasedFaceVerificationFrequencyTrigger {\n enabled: boolean;\n /** Minimum number of events; 0 / null / omitted means \"any count\". */\n count: number;\n /** Maximum lookback window in minutes; 0 / null / omitted means \"any window\". */\n window_minutes: number;\n}\n\n/** Events that can trigger Event-Based Face Verification for a tenant. */\nexport interface EventBasedFaceVerificationTriggers {\n // Account-sensitive events\n login: boolean;\n password_change: boolean;\n name_change: boolean;\n phone_number_change: boolean;\n two_factor_auth_change: boolean;\n new_device_or_location: boolean;\n device_fingerprint_change: boolean;\n payment_method_change: boolean;\n\n // Transaction events — each rule is self-contained; there is no\n // umbrella flag. To enable a transaction event, set its `enabled`\n // field to true (and configure the relevant threshold / count /\n // window). To disable, set `enabled` to false.\n deposit: EventBasedFaceVerificationThresholdTrigger;\n withdrawal: EventBasedFaceVerificationThresholdTrigger;\n large_bet_placement: EventBasedFaceVerificationThresholdTrigger;\n high_frequency_betting: EventBasedFaceVerificationFrequencyTrigger;\n account_balance_transfer: boolean;\n}\n\n/**\n * Retry budget for Event-Based Face Verification. This is the only field the\n * platform stores here; the reactions taken when the budget is exhausted\n * (`trigger_alert`, `enforce_logout`, `freeze_account`, `block`,\n * `freeze_duration_minutes`) come from the tenant's per-event KYC alert\n * configuration and are reported on\n * {@link EventBasedFaceVerificationReactionResult}.\n */\nexport interface EventBasedFaceVerificationReactions {\n /** Retries after the first attempt; total submissions = this + 1. */\n max_retry_attempts: number;\n /** @deprecated Never populated; read `data.trigger_alert` on the callback instead. */\n trigger_alert?: boolean;\n /** @deprecated Never populated; read `data.enforce_logout` on the callback instead. */\n enforce_logout?: boolean;\n /** @deprecated Never populated; read `data.freeze_account` on the callback instead. */\n freeze_account?: boolean;\n /** @deprecated Never populated; read `data.freeze_duration_minutes` on the callback instead. */\n freeze_duration_minutes?: number;\n}\n\n/** Per-event toggles that decide when a submit-link request requires KYC. */\nexport interface KycVerificationTriggers {\n onboarding: boolean;\n first_withdrawal: boolean;\n first_purchase: boolean;\n /** Re-trigger verification once the customer's identity document has expired. */\n auto_trigger_on_id_expiration: boolean;\n}\n\nexport interface KycSkipOptions {\n /** Let a `manual` trigger be skipped (`can_skip` on the submit-link response). */\n allow_skip_on_manual: boolean;\n}\n\n/** Tenant-defined reasons available to reviewers for a given resource. */\nexport interface KycOtherReason {\n resource: string;\n reasons: string[];\n}\n\n/** Disclosure text shown to the customer on the hosted submission page. */\nexport interface KycDisclosureConsent {\n data_collected: string[];\n data_usage: string[];\n data_sharing: {\n third_party_providers: boolean;\n regulatory_authorities: boolean;\n internal_systems: boolean;\n provider_names?: string[];\n };\n data_retention_period: string;\n customer_rights: {\n can_access: boolean;\n can_correct: boolean;\n can_delete: boolean;\n contact_info?: string;\n };\n}\n\nexport interface KycPreferences {\n id: string;\n tenant_id: string;\n approve_kyc_reasons: string[];\n other_reasons?: KycOtherReason[];\n is_document_verification_required: boolean;\n is_face_verification_required: boolean;\n is_address_verification_required: boolean;\n is_age_verification_required: boolean;\n is_duplicate_verification_required?: boolean;\n /** Master switch for the Event-Based Face Verification feature. */\n is_reuse_kyc_enabled?: boolean;\n min_age: number;\n max_age: number;\n required_document_count: number;\n critical_risk_score: number;\n high_risk_score: number;\n medium_risk_score: number;\n supported_document_types: SupportedDocumentType[];\n supported_address_document_types?: SupportedAddressDocumentType[];\n /** Tenant-level callback URL used when a submit-link request passes none. */\n callback_url?: string;\n address_fuzzy_match?: boolean;\n document_fuzzy_match?: boolean;\n document_translate?: boolean;\n decline_on_single_step?: boolean;\n allow_warnings?: boolean;\n backside_proof_required?: boolean;\n document_two_backside_proof_required?: boolean;\n verification_mode?: string;\n document_upload_option?: boolean;\n disclosure_consent?: KycDisclosureConsent;\n /** Per-event toggles for document verification (`requestKycSubmitLink`). */\n kyc_triggers?: KycVerificationTriggers;\n kyc_skip_options?: KycSkipOptions;\n /** Per-event triggers for Event-Based Face Verification. */\n reuse_kyc_triggers?: EventBasedFaceVerificationTriggers;\n /** Retry budget for Event-Based Face Verification. */\n reuse_kyc_reactions?: EventBasedFaceVerificationReactions;\n created_at: string;\n updated_at: string;\n}\n\n/**\n * @deprecated KYC preferences are managed in the Vesant console; the platform\n * exposes no update operation to the SDK, so `updatePreferences` always fails.\n * This type will be removed in a future release.\n */\nexport interface UpdateKycPreferencesRequest {\n reasons?: string[];\n is_document_verification_required?: boolean;\n is_face_verification_required?: boolean;\n is_address_verification_required?: boolean;\n is_age_verification_required?: boolean;\n is_reuse_kyc_enabled?: boolean;\n min_age?: number;\n max_age?: number;\n required_document_count?: number;\n critical_risk_score?: number;\n high_risk_score?: number;\n medium_risk_score?: number;\n supported_document_types?: SupportedDocumentType[];\n /** Partial update — only the events present here are changed. */\n reuse_kyc_triggers?: Partial<EventBasedFaceVerificationTriggers>;\n /** Partial update — only the keys present here are changed. */\n reuse_kyc_reactions?: Partial<EventBasedFaceVerificationReactions>;\n}\n\n// ============================================================================\n// Document Verification Request Types\n// ============================================================================\n\nexport interface Name {\n first_name?: string;\n middle_name?: string;\n last_name?: string;\n full_name?: string;\n}\n\nexport interface SubmittedDocument {\n /** Base64 encoded document image */\n proof: string;\n /** Base64 additional document image (back side, etc.) */\n additional_proof?: string;\n /** Document number for search/verification */\n document_number?: string;\n /** Document types to verify against */\n selected_type?: DocumentType[];\n /** Extracted/provided name */\n name?: Name;\n /** Date of birth (YYYY-MM-DD) */\n dob?: string;\n /** Issue date (YYYY-MM-DD) */\n issue_date?: string;\n /** Expiry date (YYYY-MM-DD) */\n expiry_date?: string;\n /** Gender */\n gender?: string;\n}\n\nexport interface FaceProof {\n /** Base64 encoded face image or selfie */\n proof: string;\n}\n\nexport interface DocumentVerificationRequest {\n /** Customer reference ID */\n reference: string;\n /** Callback URL for async verification results */\n callback_url: string;\n /** Customer email */\n email: string;\n /** Country code (ISO 3166-1 alpha-2) */\n country: string;\n /** Language code */\n language: string;\n /** Full address for verification */\n full_address?: string;\n /** Base64 encoded address proof document */\n address_proof?: string;\n /** Primary document */\n document: SubmittedDocument;\n /** Secondary document (optional) */\n document_two?: SubmittedDocument;\n /** Face verification proof (optional) */\n face?: FaceProof;\n /** Additional metadata */\n token?: string;\n}\n\nexport interface DocumentVerificationResponse {\n id: string;\n reference: string;\n status: KycStatus;\n verification_url?: string;\n message?: string;\n}\n\n// ============================================================================\n// KYC Status Update Types\n// ============================================================================\n\nexport interface UpdateKycStatusRequest {\n /** Provider reference or KYC ID */\n reference: string;\n /** Target status */\n status: KycStatus;\n /** Acceptance/decline reason */\n reason?: string;\n /** Provider warnings data */\n warnings?: Record<string, Record<string, string>>;\n}\n\n// ============================================================================\n// KYC Submit Link Request Types\n// ============================================================================\n\n/**\n * Events that can trigger a KYC request. Each maps to a per-event toggle in\n * the tenant's KYC verification trigger preferences, except `manual` (always\n * required) and `login` (only for an expired identity document).\n */\nexport type KycTriggerEvent =\n | 'onboarding'\n | 'first_withdrawal'\n | 'first_purchase'\n /** Aliases of `first_withdrawal` / `first_purchase` — same tenant toggles. */\n | 'withdrawal'\n | 'purchase'\n | 'manual'\n /**\n * The customer is signing in. Answers for any state: never verified (asked,\n * not skippable, per the tenant's onboarding policy), document expired\n * (asked, skippable — \"Remind me later\"), or verified with a valid document\n * (not asked). One call covers every customer.\n */\n | 'login';\n\n/**\n * Why verification is — or is not — being asked for. Codes are stable;\n * `message` is display-ready text you can show the customer as-is.\n */\nexport interface KycRequestReason {\n code: KycRequestReasonCode | (string & Record<string, never>);\n message: string;\n}\n\n/**\n * Reason codes returned by `requestKycSubmitLink`. Treat unrecognised codes\n * as \"verification required\" and fall back to `message` for display.\n */\nexport type KycRequestReasonCode =\n /** Required to complete registration. */\n | 'KYC_REQUIRED_ONBOARDING'\n /** Required before the customer's first withdrawal. */\n | 'KYC_REQUIRED_FIRST_WITHDRAWAL'\n /** Required before the customer's first purchase. */\n | 'KYC_REQUIRED_FIRST_PURCHASE'\n /** The customer's identity document has expired and must be re-verified. */\n | 'KYC_REQUIRED_ID_EXPIRED'\n /** Verification was explicitly requested by the tenant. */\n | 'KYC_REQUIRED_MANUAL'\n /** Not required — the customer already has an accepted verification. */\n | 'KYC_NOT_REQUIRED_ALREADY_VERIFIED'\n /** Not required — the tenant has this trigger event switched off. */\n | 'KYC_NOT_REQUIRED_TRIGGER_DISABLED';\n\nexport interface RequestKycSubmitLinkRequest {\n /** User ID to generate KYC submission link for */\n user_id: string;\n /** URL to redirect user after KYC submission (optional) */\n redirect_url?: string;\n /** URL to receive callback notifications via POST request when KYC status changes (optional) */\n callback_url?: string;\n /**\n * Event that triggered the KYC request. The tenant's KYC verification\n * trigger preferences decide, per event, whether KYC is required\n * (`kyc_required` in the response). \"manual\" always requires KYC and\n * honors the tenant's allow-skip-on-manual option (`can_skip`). \"login\"\n * answers for any customer state — never verified (asked, not skippable),\n * document expired (asked, skippable so you can offer \"Remind me later\"),\n * or verified and valid (not asked) — so a platform that gates entry on KYC\n * needs only this one call at sign-in. The same expired document is *not*\n * skippable on withdrawal / purchase events: it is enforced on\n * \"first_withdrawal\", \"withdrawal\", \"first_purchase\" and \"purchase\" alike,\n * so keep sending whichever of those you already send.\n * Omitted or unknown values default to KYC required with no skip.\n */\n trigger_event?: KycTriggerEvent | (string & Record<string, never>);\n /**\n * Registered customer identity data (optional). Seeds the customer's risk\n * profile so document verification can cross-check the submitted document\n * against trusted reference data (name/DOB match, address verification).\n * Fields never overwrite data already on the profile.\n */\n customer_data?: KycCustomerData;\n}\n\n/**\n * Customer identity data supplied by your platform on a submit-link request.\n * Mirrors the geolocation `customer_data` contract. Every field is optional\n * and never overwrites data already on the customer's risk profile.\n */\nexport interface KycCustomerData {\n /**\n * Customer's registered full name. Used to match the OCR-extracted name\n * on the submitted document.\n */\n full_name?: string;\n /**\n * Customer's registered date of birth. ISO 8601 date (\"1999-06-02\") or an\n * RFC 3339 timestamp (\"1986-09-06T18:30:00.000+00:00\", as produced by\n * `Date.prototype.toISOString()`) — for timestamps the date portion is\n * used. Used for DOB matching against the submitted document.\n */\n date_of_birth?: string;\n /** Customer's email address */\n email?: string;\n /** Customer's phone number */\n phone?: string;\n /** Customer's residential address. Used for address verification. */\n address?: string;\n /** Customer's country of residence */\n country?: string;\n}\n\n/**\n * Trigger events that can request Event-Based Face Verification.\n *\n * Account-sensitive: any sensitive change to the account profile.\n * Transaction events: covered by the per-event rules in\n * `EventBasedFaceVerificationTriggers` (`deposit`, `withdrawal`, `large_bet_placement`,\n * `high_frequency_betting`, `account_balance_transfer`).\n */\nexport type EventBasedFaceVerificationEvent =\n | 'login'\n | 'password_change'\n | 'name_change'\n | 'phone_number_change'\n | 'two_factor_auth_change'\n | 'new_device_or_location'\n | 'device_fingerprint_change'\n | 'payment_method_change'\n | 'deposit'\n | 'withdrawal'\n | 'large_bet_placement'\n | 'high_frequency_betting'\n | 'account_balance_transfer';\n\nexport interface CreateEventBasedFaceVerificationSessionRequest {\n /** Unique reference for the KYC session (e.g., customer ID or transaction ID) */\n reference: string;\n /** Customer ID to associate with the KYC session */\n customer_id: string;\n /**\n * The triggering event. One of the `EventBasedFaceVerificationEvent` union members.\n * Required — when empty, the server falls through to the unknown-event\n * passthrough and allows the request silently.\n */\n event: EventBasedFaceVerificationEvent;\n /**\n * USD amount associated with the event. Required for threshold-gated\n * events (`deposit`, `withdrawal`, `large_bet_placement`); ignored for\n * everything else. Missing/zero with a non-zero threshold blocks the\n * session.\n */\n amount?: number;\n /**\n * Number of qualifying events the customer has performed in the\n * window described by `event_window_minutes`. Required for\n * frequency-gated events (`high_frequency_betting`); ignored for\n * everything else.\n */\n event_count?: number;\n /**\n * Lookback window (in minutes) the tenant counted `event_count` over.\n * Required for frequency-gated events alongside `event_count`. A\n * window larger than the tenant's configured `window_minutes`\n * implies a slower rate than \"high frequency\" and blocks the session.\n */\n event_window_minutes?: number;\n /** URL to redirect user after validate the facial submission (optional) */\n redirect_url?: string;\n /** URL to receive callback notifications via POST request when Event-Based Face Verification status changes (optional) */\n callback_url?: string;\n}\n\nexport interface SubmitEventBasedFaceVerificationSessionRequest {\n /** Event-Based Face Verification session token generated from createEventBasedFaceVerificationSession */\n token: string;\n /** Base64 encoded face image or selfie for verification */\n proof: string;\n /** Unique reference for the KYC session (e.g., customer ID or transaction ID) */\n reference?: string;\n /**\n * Optional capture telemetry (JSON string): the face-detection\n * bounding-box samples recorded in the moments before capture. Attached\n * automatically by `FaceCaptureModal` when in-modal detection is active;\n * omit when building a custom capture UI without detection. Stored\n * verbatim server-side for audit/review — a weak presence signal, not\n * certified anti-spoofing.\n */\n liveness_artifact?: string;\n}\n\nexport interface RequestKycSubmitLinkResponse {\n /** Generated KYC submission redirect URL */\n link: string;\n /** KYC request ID */\n kyc_id: string;\n /**\n * Whether KYC is required for the reported `trigger_event`, per the\n * tenant's verification trigger preferences. `false` when the trigger\n * is disabled for the tenant, or when the customer is already verified\n * (in that case `link` and `kyc_id` are empty).\n */\n kyc_required: boolean;\n /**\n * Whether the user may skip verification. `true` for\n * `trigger_event: \"manual\"` when the tenant enables allow-skip-on-manual,\n * for `\"login\"` when an expired identity document triggered the request\n * (offer \"Remind me later\"), and when the customer is already verified.\n * Always `false` at `\"withdrawal\"` / `\"purchase\"` — that is where a\n * postponed re-verification becomes mandatory.\n */\n can_skip: boolean;\n /**\n * Why verification is — or is not — being asked for. Use `reason.code` to\n * branch (for example `KYC_REQUIRED_ID_EXPIRED` warrants a different prompt\n * than a first-time verification) and `reason.message` for display.\n */\n reason?: KycRequestReason;\n}\n\n/**\n * Body POSTed to your `callback_url` when a customer's identity document\n * passes its expiry date. Signed with `X-Webhook-Signature: sha256=<hex>`\n * (HMAC-SHA256 of the raw body), like every other Vesant callback.\n *\n * An expiry happens on a **date**, not on a customer action, so this webhook\n * is the only signal for it — nothing the customer does triggers it. Delivered\n * once per customer, when the document first becomes expired.\n *\n * It is sent regardless of the tenant's auto-trigger-on-ID-expiration setting:\n * that setting governs whether verification is *enforced*, not whether you are\n * *told*.\n */\nexport interface KycDocumentExpiredCallbackEvent {\n /** Always `\"kyc_document_expired\"` — dispatch on this. */\n event: 'kyc_document_expired';\n /** Your customer identifier (the `user_id` you supplied). */\n reference: string;\n /** The customer's risk-profile ID. */\n resource_id: string;\n /**\n * Always `\"expired\"`. Describes the document — not the customer's KYC\n * status, which remains `accepted` until they re-verify.\n */\n status: 'expired';\n data: {\n customer_id: string;\n /** The document's expiry date (ISO 8601 `YYYY-MM-DD`). */\n id_expiry_date: string;\n };\n}\n\n/**\n * Type guard for the identity-document expiry webhook. Narrows an already\n * signature-verified, parsed payload to {@link KycDocumentExpiredCallbackEvent}.\n */\nexport function isKycDocumentExpiredCallbackEvent(\n value: unknown\n): value is KycDocumentExpiredCallbackEvent {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { event?: unknown }).event === 'kyc_document_expired'\n );\n}\n\n/** Device class detected by the SDK (purely client-side — server doesn't care). */\nexport type EventBasedFaceVerificationDeviceType = 'mobile' | 'desktop';\n\nexport interface CreateEventBasedFaceVerificationSessionResponse {\n /** Event-Based Face Verification session reference (echo of the request reference) */\n reference: string;\n /** Generated Event-Based Face Verification session token, valid 10 minutes */\n token: string;\n /**\n * Empty string when Event-Based Face Verification is required. When `is_required` is\n * false, this contains the human-readable reason (e.g. feature\n * disabled, threshold not met, customer has no prior KYC).\n */\n reason: string;\n /** Whether the caller must complete the face capture before proceeding */\n is_required: boolean;\n /**\n * Public HTTPS handoff URL the SDK encodes into a QR code on desktop.\n * The mobile device scans it, lands on the tenant frontend's\n * /reuse-kyc-submit page, and completes the face capture there. Empty\n * when the server has no `BASE_URL_FRONTEND` configured — the SDK\n * falls back to building its own URL in that case.\n */\n link: string;\n /** Failed face-capture attempts so far on this session. 0 on a fresh session. */\n attempts: number;\n /**\n * Total submissions permitted before reactions fire\n * (`reuse_kyc_reactions.max_retry_attempts + 1`).\n */\n max_attempts: number;\n /**\n * Hosted verification journey URL. When present, the capture runs on a\n * hosted page (embedded by `FaceCaptureModal` in an iframe) instead of the\n * SDK's local camera; the verdict is read via the session status poll.\n * Absent when the platform runs the local-capture flow.\n */\n verification_url?: string;\n}\n\n/**\n * Reaction outcome returned on every face-submit callback. Tenant apps\n * use this to decide whether to allow another retry, end the session,\n * or freeze the account. Reaction flags are only populated when\n * `retry_limit_exceeded` is true.\n */\nexport interface EventBasedFaceVerificationReactionResult {\n /** Submissions the customer still has before the retry limit fires. */\n retries_remaining: number;\n /** True once the latest failed attempt exhausts the retry policy. */\n retry_limit_exceeded: boolean;\n trigger_alert: boolean;\n enforce_logout: boolean;\n freeze_account: boolean;\n /** Tenant app should block the action/account when true. */\n block: boolean;\n freeze_duration_minutes: number;\n /** Set when an alert was raised on the dashboard. */\n alert_id?: string;\n}\n\n/**\n * Shape of the webhook body POSTed to `callback_url` after a Event-Based Face Verification\n * submission completes (also returned synchronously from\n * `submitEventBasedFaceVerificationSession`).\n */\nexport interface EventBasedFaceVerificationCallback {\n event: 'reuse_kyc';\n reference: string;\n resource_id: string;\n status: KycStatus;\n /**\n * True when the tenant app should block the action/account. Mirrors the\n * `block` reaction on {@link data} at the top level of the callback so\n * consumers can branch without inspecting `data`. Omitted when false.\n */\n block?: boolean;\n /** Names the event/verification that triggered the block. Omitted when not blocked. */\n block_reason?: string;\n /**\n * Structured decline reasons. Returned by\n * `getEventBasedFaceVerificationSessionStatus`; the submit response and the\n * webhook carry {@link declined_reason} only.\n */\n declined_reasons?: Reason[];\n /** Decline text. Present on the submit response, the webhook, and status lookups. */\n declined_reason?: string;\n /** @deprecated Use structured reasons. */\n warnings?: Record<string, Record<string, string>>;\n data: EventBasedFaceVerificationReactionResult;\n}\n\n/**\n * Server-side handoff state backed by the normal KYC Redis store (15-minute\n * cache TTL). Event-Based Face Verification remains valid for 10 minutes;\n * this cache does not extend that session. Desktop clients poll it to detect\n * when a mobile device has attached to the same token via QR.\n */\nexport interface KycHandoffSession {\n document: string;\n document_backside: string;\n document_two: string;\n document_two_backside: string;\n address: string;\n face: string;\n /** True after a mobile device hits PUT /api/v1/kyc/session/connect. */\n mobile_connected: boolean;\n /** True after the (normal-KYC) document submission completes; unused for Event-Based Face Verification. */\n is_submitted: boolean;\n}\n\n// ============================================================================\n// KYC Status Check Types\n// ============================================================================\n\nexport interface CheckKycStatusRequest {\n /** Customer identifier. Sent for context only — the lookup is by kyc_id. */\n user_id: string;\n /** The KYC request ID returned by requestKycSubmitLink; drives the status lookup. */\n kyc_id: string;\n}\n\n/**\n * Response from checkKycStatus. Always returns the same shape.\n *\n * `additional_data` is absent or `null` while `status` is `'awaiting_kyc'` or\n * `'pending'` — the key is omitted on a newly created record, so guard with a\n * truthiness check (`if (result.additional_data)`), never `!== null`.\n * Otherwise it contains the full KYC record including document details,\n * proofs, and the customer's risk profile.\n *\n * `status === 'awaiting_kyc'` means the submit link was issued but the\n * customer has not submitted documents — treat it as \"not started\", never as\n * \"in progress\". Check `link_expired`: `false` → re-surface the existing\n * link; `true` → request a fresh one via `requestKycSubmitLink`.\n */\nexport interface CheckKycStatusResponse {\n id: string;\n forward_reference: string;\n status: KycStatus;\n id_verified: boolean;\n address_verified: boolean;\n face_verified: boolean;\n age_verified: boolean;\n /**\n * Structured decline reasons. The platform currently returns these only on\n * the full record: read `additional_data.declined_reasons` and fall back to\n * {@link declined_reason}. This top-level field is reserved and not populated.\n */\n declined_reasons?: Reason[];\n /**\n * Structured, non-blocking warnings. Currently returned only as\n * `additional_data.warning_reasons`; this top-level field is not populated.\n */\n warning_reasons?: Reason[];\n /** Comma-joined decline text. Always present on a declined response. */\n declined_reason?: string;\n /** Legacy decline code; prefer the `code` on `additional_data.declined_reasons`. */\n declined_code?: KycDeclinedCode;\n other_reason?: string;\n accepted_reason?: string;\n /** Legacy warning map; prefer `additional_data.warning_reasons`. */\n warnings?: Record<string, Record<string, string>>;\n required_document_count: number;\n supported_document_types?: SupportedDocumentType[];\n supported_address_document_types?: SupportedAddressDocumentType[];\n is_id_verification_required: boolean;\n is_face_verification_required: boolean;\n is_address_verification_required: boolean;\n is_age_verification_required: boolean;\n created_at: string;\n /**\n * Full KYC record with document details, proofs, and risk profile. Absent or\n * `null` while status is 'awaiting_kyc' or 'pending': the key is omitted on\n * a newly created record, so check truthiness rather than comparing to null.\n */\n additional_data?: KycRequest | null;\n /** Present when status is 'awaiting_kyc': whether the submit link has expired (request a new one when true). */\n link_expired?: boolean;\n /** Present when status is 'awaiting_kyc': the submit link's expiry time (RFC 3339). */\n link_expires_at?: string;\n}\n\nexport interface RequestAdditionalDocumentsRequest {\n /** KYC request ID */\n id: string;\n /** Document types to request */\n document_types: ProofType[];\n /** Message to customer */\n message?: string;\n}\n\n// ============================================================================\n// KYC Overview & Statistics Types\n// ============================================================================\n\nexport interface KycOverview {\n total: number;\n pending: number;\n approved: number;\n high_risk: number;\n rejected: number;\n id_verified: number;\n address_verified: number;\n face_verified: number;\n rejections: number;\n total_alerts: number;\n pending_alerts: number;\n resolved_alerts: number;\n}\n\n// ============================================================================\n// KYC Request Listing Types\n// ============================================================================\n\nexport interface KycRequestFilters {\n status?: KycStatus | KycStatus[];\n search?: string;\n fromDate?: string;\n toDate?: string;\n sortBy?: string;\n order?: 'ASC' | 'DESC';\n}\n\nexport interface KycPagination {\n limit: number;\n page: number;\n total: number;\n totalPages: number;\n}\n\nexport interface KycRequestListResponse {\n data: KycRequest[];\n pagination: KycPagination;\n}\n\n// ============================================================================\n// Customer Profile Types (Re-exported from risk-profile module)\n// ============================================================================\n\n// Import types from risk-profile module for use in KYC client\nimport type {\n CustomerProfile as RiskProfileCustomerProfile,\n CreateProfileRequest,\n ProfileFilters,\n ProfileListResponse,\n} from '../risk-profile/types';\n\n// Export types for internal use in KYC client (aliased to avoid conflicts with main exports)\n// Users should import CustomerProfile, CreateProfileRequest, etc. from 'vesant-sdk/risk-profile'\nexport type {\n RiskProfileCustomerProfile as CustomerProfile,\n CreateProfileRequest as CreateCustomerProfileRequest,\n ProfileFilters as CustomerProfileFilters,\n ProfileListResponse as CustomerProfileListResponse,\n};\n\n// ============================================================================\n// SDK Configuration Types\n// ============================================================================\n\nexport interface KycClientConfig {\n /** Base URL of the KYC Service API (e.g., \"http://localhost:8088\") */\n baseURL: string;\n\n /** Base URL of the Customer Risk Profile Service API (e.g., \"http://localhost:8094\") */\n riskProfileBaseURL?: string;\n\n /** Tenant ID for multi-tenancy */\n tenantId: string;\n\n /** API key or JWT token for authentication */\n apiKey?: string;\n\n /** User ID for operations requiring user context */\n userId?: string;\n\n /** Custom headers to include in every request */\n headers?: Record<string, string>;\n\n /** Request timeout in milliseconds (default: 10000) */\n timeout?: number;\n\n /** Enable debug logging */\n debug?: boolean;\n\n /** Environment mode - 'sandbox' uses isolated sandbox data */\n environment?: 'production' | 'sandbox';\n}\n\n// ============================================================================\n// React Hook Types\n// ============================================================================\n\n/** Base hook state with loading and error */\ninterface BaseHookState {\n loading: boolean;\n error: Error | null;\n}\n\n/** Base options for hooks with auto-fetch capability */\ninterface BaseAutoFetchOptions {\n autoFetch?: boolean;\n}\n\n/** Base options for hooks with polling capability */\ninterface BasePollOptions extends BaseAutoFetchOptions {\n pollInterval?: number;\n}\n\n/** Base options for list hooks with filters and pagination */\ninterface BaseListOptions<TFilters> extends BasePollOptions {\n filters?: TFilters;\n pagination?: PaginationParams;\n}\n\nexport interface UseKycSubmissionOptions {\n onComplete?: (result: DocumentVerificationResponse) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UseKycSubmissionResult extends BaseHookState {\n submit: (request: DocumentVerificationRequest) => Promise<DocumentVerificationResponse>;\n submission: DocumentVerificationResponse | null;\n reset: () => void;\n}\n\nexport type UseKycRequestsOptions = BaseListOptions<KycRequestFilters>;\n\nexport interface UseKycRequestsResult extends BaseHookState {\n requests: KycRequest[];\n pagination: KycPagination | null;\n fetchRequests: (filters?: KycRequestFilters, pagination?: PaginationParams) => Promise<void>;\n getRequest: (id: string) => Promise<KycRequest>;\n updateStatus: (reference: string, status: KycStatus, reason?: string) => Promise<void>;\n refresh: () => Promise<void>;\n}\n\nexport type UseKycAlertsOptions = BaseListOptions<KycAlertFilters>;\n\nexport interface UseKycAlertsResult extends BaseHookState {\n alerts: KycAlert[];\n pagination: KycPagination | null;\n fetchAlerts: (filters?: KycAlertFilters, pagination?: PaginationParams) => Promise<void>;\n getAlert: (id: string) => Promise<KycAlert>;\n updateAlert: (id: string, update: UpdateKycAlertRequest) => Promise<void>;\n refresh: () => Promise<void>;\n}\n\nexport interface UseKycOverviewOptions extends BaseAutoFetchOptions {\n fromDate?: string;\n toDate?: string;\n}\n\nexport interface UseKycOverviewResult extends BaseHookState {\n overview: KycOverview | null;\n refresh: (fromDate?: string, toDate?: string) => Promise<void>;\n}\n\nexport interface UseKycPreferencesResult extends BaseHookState {\n preferences: KycPreferences | null;\n /** @deprecated The platform exposes no preference-update operation; this call always fails. */\n updatePreferences: (update: UpdateKycPreferencesRequest) => Promise<void>;\n refresh: () => Promise<void>;\n}\n","import { BaseClient } from '../core/client';\nimport type { BaseClientConfig, RequestOptions } from '../core/config';\nimport type {\n TaxClientConfig,\n CustomerTaxProfileRecord,\n CustomerTaxProfileDocuments,\n ReRequestTaxFormInput,\n EnableWithholdingInput,\n EnableWithholdingResponse,\n TINCheckResult,\n TaxRules,\n UpdateTaxRulesInput,\n TaxRuleVersion,\n RemindersRunResult,\n ComplianceStats,\n ComplianceStatsFilters,\n GlobalTaxRule,\n TreatyCountry,\n TreatyCountryListResponse,\n} from './types';\n\nexport class TaxClient extends BaseClient {\n constructor(config: TaxClientConfig) {\n const baseConfig: BaseClientConfig = {\n baseURL: config.baseURL,\n tenantId: config.tenantId,\n apiKey: config.apiKey,\n headers: config.headers,\n timeout: config.timeout,\n retries: 3,\n debug: config.debug,\n environment: config.environment,\n };\n super(baseConfig);\n }\n\n // ==========================================================================\n // P1 — Customer Tax Profile (core compliance flow)\n // ==========================================================================\n\n async getCustomerTaxProfileRecord(customerID: string): Promise<CustomerTaxProfileRecord> {\n return this.request<CustomerTaxProfileRecord>(\n `/api/v1/tax/customer-tax-profiles/${customerID}`\n );\n }\n\n async requestTaxForm(customerID: string): Promise<CustomerTaxProfileRecord> {\n return this.request<CustomerTaxProfileRecord>(\n `/api/v1/tax/customer-tax-profiles/${customerID}/request-form`,\n { method: 'POST' }\n );\n }\n\n async checkTINStatus(customerID: string, requestOptions?: RequestOptions): Promise<TINCheckResult> {\n return this.requestWithRetry<TINCheckResult>(\n `/api/v1/tax/customer-tax-profiles/${customerID}/check-tin`,\n { method: 'POST' },\n undefined,\n undefined,\n requestOptions\n );\n }\n\n async reRequestTaxForm(\n customerID: string,\n input: ReRequestTaxFormInput\n ): Promise<CustomerTaxProfileRecord> {\n return this.request<CustomerTaxProfileRecord>(\n `/api/v1/tax/customer-tax-profiles/${customerID}/re-request-form`,\n {\n method: 'POST',\n body: JSON.stringify(input),\n }\n );\n }\n\n async enableBackupWithholding(\n customerID: string,\n input: EnableWithholdingInput\n ): Promise<EnableWithholdingResponse> {\n return this.request<EnableWithholdingResponse>(\n `/api/v1/tax/customer-tax-profiles/${customerID}/enable-withholding`,\n {\n method: 'POST',\n body: JSON.stringify(input),\n }\n );\n }\n\n async getCustomerDocuments(customerID: string): Promise<CustomerTaxProfileDocuments> {\n return this.request<CustomerTaxProfileDocuments>(\n `/api/v1/tm/customer-tax-profiles/${customerID}/documents`\n );\n }\n\n async downloadTaxForm(\n customerID: string,\n requestOptions?: RequestOptions\n ): Promise<ArrayBuffer> {\n return this.request<ArrayBuffer>(\n `/api/v1/tax/customer-tax-profiles/${customerID}/download-form`,\n { method: 'GET' },\n undefined,\n { ...requestOptions, responseType: 'arraybuffer' }\n );\n }\n\n // ==========================================================================\n // P2 — Tenant Tax Rules\n // ==========================================================================\n\n async getTaxRules(): Promise<TaxRules> {\n const res = await this.request<{ rules: TaxRules }>('/api/v1/tax/rules');\n return res.rules;\n }\n\n async updateTaxRules(input: UpdateTaxRulesInput): Promise<TaxRuleVersion> {\n const res = await this.request<{ version: TaxRuleVersion }>('/api/v1/tax/rules', {\n method: 'PUT',\n body: JSON.stringify({ rules: input }),\n });\n return res.version;\n }\n\n async runReminders(): Promise<RemindersRunResult> {\n return this.request<RemindersRunResult>('/api/v1/tax/reminders/run', { method: 'POST' });\n }\n\n async getComplianceStats(filters?: ComplianceStatsFilters): Promise<ComplianceStats> {\n const params: Record<string, unknown> = {};\n if (filters?.time_range) params.time_range = filters.time_range;\n if (filters?.from_date) params.from_date = filters.from_date;\n if (filters?.to_date) params.to_date = filters.to_date;\n return this.request<ComplianceStats>(\n `/api/v1/tax/tenant/w-form-tenant-stats${this.buildQueryString(params)}`\n );\n }\n\n // ==========================================================================\n // P3 — Global Tax Rule & Treaty Countries\n // ==========================================================================\n\n async getCurrentGlobalTaxRule(): Promise<GlobalTaxRule> {\n const res = await this.request<{ success: boolean; message: string; data: GlobalTaxRule }>(\n '/api/v1/tm/tenant/global-tax-rules/current'\n );\n return res.data;\n }\n\n async listTreatyCountries(): Promise<TreatyCountryListResponse> {\n return this.request<TreatyCountryListResponse>('/api/v1/tax/treaty-countries');\n }\n\n async getTreatyCountry(code: string): Promise<TreatyCountry> {\n const res = await this.request<{ treaty_country: TreatyCountry }>(\n `/api/v1/tax/treaty-countries/${encodeURIComponent(code)}`\n );\n return res.treaty_country;\n }\n}\n","/**\n * Webhook event handler with signature verification and typed dispatch.\n */\n\nimport { verifyWebhookSignature } from '../core/webhook-utils';\nimport { ValidationError } from '../core/errors';\nimport { InMemoryDedupStore, type WebhookDedupStore } from '../core';\nimport type {\n WebhookEvent,\n WebhookEventType,\n WebhookEventHandler,\n WebhookAnyHandler,\n WebhookHandlerConfig,\n} from './types';\n\n/** Resolve the event id: the top-level `id`, or `notification.id` for the notification envelope. */\nfunction resolveEventId(event: WebhookEvent): string | undefined {\n if (event.id) {\n return event.id;\n }\n if (event.event_type === 'notification.created') {\n return event.notification?.id;\n }\n return undefined;\n}\n\nexport class WebhookHandler {\n private handlers = new Map<WebhookEventType, WebhookEventHandler[]>();\n private anyHandlers: WebhookAnyHandler[] = [];\n private readonly secret: string;\n private readonly tolerance: number;\n private readonly replayProtection: boolean;\n private readonly allowLegacySignature: boolean;\n private readonly dedupStore: WebhookDedupStore;\n\n constructor(config: WebhookHandlerConfig) {\n this.secret = config.secret;\n this.tolerance = config.tolerance ?? 300000; // 5 minutes\n this.replayProtection = config.replayProtection ?? true;\n this.allowLegacySignature = config.allowLegacySignature ?? true;\n this.dedupStore = config.dedupStore ?? new InMemoryDedupStore();\n }\n\n /**\n * Register a handler for a specific event type.\n */\n on<T extends WebhookEventType>(\n eventType: T,\n handler: WebhookEventHandler<T>\n ): this {\n const existing = this.handlers.get(eventType) || [];\n existing.push(handler as unknown as WebhookEventHandler);\n this.handlers.set(eventType, existing);\n return this;\n }\n\n /**\n * Register a catch-all handler for all event types.\n */\n onAny(handler: WebhookAnyHandler): this {\n this.anyHandlers.push(handler);\n return this;\n }\n\n /**\n * Verify signature and parse the webhook body.\n */\n async verifyAndParse(body: string, signature: string): Promise<WebhookEvent> {\n const isValid = await verifyWebhookSignature(body, signature, this.secret, {\n tolerance: this.tolerance,\n allowLegacy: this.allowLegacySignature,\n });\n if (!isValid) {\n throw new ValidationError('Invalid webhook signature', ['signature']);\n }\n\n return this.parseAndValidate(body);\n }\n\n /**\n * Verify signature, parse, and dispatch to registered handlers.\n */\n async handle(body: string, signature: string): Promise<void> {\n const event = await this.verifyAndParse(body, signature);\n await this.dispatch(event);\n }\n\n /**\n * Parse an event without signature verification (for testing).\n */\n async parseEvent(body: string): Promise<WebhookEvent> {\n return this.parseAndValidate(body);\n }\n\n private async parseAndValidate(body: string): Promise<WebhookEvent> {\n const event = JSON.parse(body) as WebhookEvent;\n const eventId = resolveEventId(event);\n\n if (!event.event_type || !eventId || !event.timestamp) {\n throw new ValidationError(\n 'Invalid webhook event: missing required fields (event_type, id, timestamp)',\n ['event_type', 'id', 'timestamp']\n );\n }\n\n // Timestamp tolerance check (defense in depth; the signed-timestamp scheme\n // also authenticates the timestamp in verifyWebhookSignature).\n if (this.tolerance > 0) {\n const eventTime = new Date(event.timestamp).getTime();\n if (Math.abs(Date.now() - eventTime) > this.tolerance) {\n throw new ValidationError(\n `Webhook event timestamp is outside tolerance window (${this.tolerance}ms)`,\n ['timestamp']\n );\n }\n }\n\n // Replay protection via the (pluggable) dedup store.\n if (this.replayProtection) {\n if (await this.dedupStore.seen(eventId)) {\n throw new ValidationError(\n `Duplicate webhook event: ${eventId} has already been processed`,\n ['id']\n );\n }\n await this.dedupStore.mark(eventId, this.tolerance);\n }\n\n return event;\n }\n\n private async dispatch(event: WebhookEvent): Promise<void> {\n const typeHandlers = this.handlers.get(event.event_type) || [];\n const allHandlers = [...typeHandlers, ...this.anyHandlers];\n\n for (const handler of allHandlers) {\n await (handler as WebhookAnyHandler)(event);\n }\n }\n}\n","/**\n * Framework middleware helpers for webhook handling.\n *\n * Provides pre-built integrations for Express/Connect and Next.js App Router.\n */\n\nimport { WebhookHandler } from './handler';\nimport type { WebhookHandlerConfig, WebhookEventType, WebhookEventHandler, WebhookAnyHandler } from './types';\n\nexport interface WebhookMiddlewareOptions extends WebhookHandlerConfig {\n /** Event handlers to register */\n handlers?: Partial<Record<WebhookEventType, WebhookEventHandler>>;\n /** Catch-all handler */\n onAny?: WebhookAnyHandler;\n}\n\n/**\n * Create an Express/Connect-compatible middleware for webhook handling.\n *\n * Expects the raw body to be available as `req.body` (string).\n * Use `express.raw({ type: 'application/json' })` or similar middleware upstream.\n */\nexport function createWebhookMiddleware(options: WebhookMiddlewareOptions) {\n const handler = buildHandler(options);\n const signatureHeader = options.signatureHeader || 'x-webhook-signature';\n\n return async (\n req: { body: string | Buffer; headers: Record<string, string | string[] | undefined> },\n res: { status(code: number): { json(body: unknown): void }; json?(body: unknown): void },\n next?: (err?: unknown) => void\n ) => {\n try {\n const body = typeof req.body === 'string' ? req.body : req.body.toString('utf-8');\n const signature = req.headers[signatureHeader];\n\n if (!signature || typeof signature !== 'string') {\n res.status(401).json({ error: 'Missing webhook signature' });\n return;\n }\n\n await handler.handle(body, signature);\n res.status(200).json({ received: true });\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Webhook processing failed';\n\n if (message.includes('signature')) {\n res.status(401).json({ error: message });\n } else if (message.includes('tolerance') || message.includes('timestamp')) {\n res.status(400).json({ error: message });\n } else if (message.includes('Duplicate')) {\n res.status(409).json({ error: message });\n } else if (next) {\n next(error);\n } else {\n res.status(500).json({ error: message });\n }\n }\n };\n}\n\n/**\n * Create a Next.js App Router-compatible webhook handler.\n *\n * Returns an async function `(request: Request) => Promise<Response>`.\n */\nexport function createNextWebhookHandler(\n options: WebhookMiddlewareOptions\n): (request: Request) => Promise<Response> {\n const handler = buildHandler(options);\n const signatureHeader = options.signatureHeader || 'x-webhook-signature';\n\n return async (request: Request): Promise<Response> => {\n try {\n const body = await request.text();\n const signature = request.headers.get(signatureHeader);\n\n if (!signature) {\n return new Response(JSON.stringify({ error: 'Missing webhook signature' }), {\n status: 401,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n await handler.handle(body, signature);\n\n return new Response(JSON.stringify({ received: true }), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Webhook processing failed';\n const status = message.includes('signature')\n ? 401\n : message.includes('tolerance') || message.includes('timestamp')\n ? 400\n : message.includes('Duplicate')\n ? 409\n : 500;\n\n return new Response(JSON.stringify({ error: message }), {\n status,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n };\n}\n\nfunction buildHandler(options: WebhookMiddlewareOptions): WebhookHandler {\n const handler = new WebhookHandler(options);\n\n if (options.handlers) {\n for (const [eventType, eventHandler] of Object.entries(options.handlers)) {\n if (eventHandler) {\n handler.on(eventType as WebhookEventType, eventHandler);\n }\n }\n }\n\n if (options.onAny) {\n handler.onAny(options.onAny);\n }\n\n return handler;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/auth.ts","../src/core/errors.ts","../src/core/circuit-breaker.ts","../src/core/rate-limiter.ts","../src/core/logger.ts","../src/core/version.ts","../src/shared/browser-utils.ts","../src/core/client.ts","../src/core/pagination.ts","../src/core/dedup.ts","../src/core/webhook-utils.ts","../src/geolocation/integrity.ts","../src/geolocation/ciphertext.ts","../src/geolocation/client.ts","../src/risk-profile/client.ts","../src/compliance/block-reasons.ts","../src/compliance/types.ts","../src/compliance/client.ts","../src/kyc/client.ts","../src/kyc/types.ts","../src/tax/client.ts","../src/webhooks/handler.ts","../src/webhooks/middleware.ts","../src/webhooks/types.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Pluggable authentication for BaseClient.\n *\n * A TokenProvider supplies the credential used for the Authorization header on\n * every request, resolved per-request (async) so callers can source short-lived\n * or rotating credentials (OAuth2 client-credentials, STS, Vault / Secrets\n * Manager) instead of a single static API key. The default StaticApiKeyProvider\n * preserves the original `apiKey` behavior with zero change for existing callers.\n */\n\nexport interface AuthCredential {\n /** Authorization scheme (e.g. 'Bearer'); defaults to 'Bearer' when omitted. */\n scheme?: string;\n /** The credential value (bearer token / API key). */\n token: string;\n}\n\nexport interface TokenProviderContext {\n tenantId: string;\n requestId: string;\n /** When true, bypass any cache and obtain a fresh credential (e.g. after a 401). */\n forceRefresh?: boolean;\n}\n\nexport interface TokenProvider {\n /** Resolve the credential for a request, or null to send no Authorization header. */\n getCredential(ctx: TokenProviderContext): Promise<AuthCredential | null>;\n /** Whether this provider can obtain a fresh credential on demand (drives 401 retry). */\n canRefresh?(): boolean;\n}\n\n/**\n * Default provider: wraps a static API key. Returns null when the key is empty\n * so the client sends no Authorization header, matching the pre-provider behavior.\n */\nexport class StaticApiKeyProvider implements TokenProvider {\n constructor(private readonly apiKey: string) {}\n\n async getCredential(): Promise<AuthCredential | null> {\n return this.apiKey ? { scheme: 'Bearer', token: this.apiKey } : null;\n }\n\n canRefresh(): boolean {\n return false;\n }\n}\n\ninterface CachedToken {\n token: string;\n expiresAt?: number;\n}\n\nexport interface RefreshingTokenProviderOptions {\n /** Fetches a fresh token. `expiresAt` is epoch milliseconds (optional). */\n fetchToken: () => Promise<CachedToken>;\n /** Refresh this many ms before expiry (default: 30_000). */\n skewMs?: number;\n /** Authorization scheme to emit (default: 'Bearer'). */\n scheme?: string;\n /** Observe each successful (re)fetch — for logging / metrics. */\n onRotate?: (meta: { expiresAt?: number }) => void;\n /** Injectable clock (default: Date.now). */\n now?: () => number;\n}\n\n/**\n * Caches a fetched token and refreshes it when it is within the skew window of\n * expiry or when `forceRefresh` is requested. Concurrent refreshes are de-duped\n * into a single in-flight fetch.\n */\nexport class RefreshingTokenProvider implements TokenProvider {\n private cached: CachedToken | null = null;\n private inFlight: Promise<CachedToken> | null = null;\n private readonly skewMs: number;\n private readonly scheme: string;\n private readonly now: () => number;\n\n constructor(private readonly opts: RefreshingTokenProviderOptions) {\n this.skewMs = opts.skewMs ?? 30_000;\n this.scheme = opts.scheme ?? 'Bearer';\n this.now = opts.now ?? (() => Date.now());\n }\n\n canRefresh(): boolean {\n return true;\n }\n\n async getCredential(ctx?: TokenProviderContext): Promise<AuthCredential | null> {\n const forceRefresh = ctx?.forceRefresh ?? false;\n if (!forceRefresh && this.cached && !this.isExpiring(this.cached)) {\n return { scheme: this.scheme, token: this.cached.token };\n }\n const fresh = await this.refresh();\n return { scheme: this.scheme, token: fresh.token };\n }\n\n private isExpiring(token: CachedToken): boolean {\n if (token.expiresAt === undefined) {\n return false;\n }\n return this.now() >= token.expiresAt - this.skewMs;\n }\n\n private refresh(): Promise<CachedToken> {\n if (this.inFlight) {\n return this.inFlight;\n }\n this.inFlight = (async () => {\n try {\n const fresh = await this.opts.fetchToken();\n this.cached = fresh;\n this.opts.onRotate?.({ expiresAt: fresh.expiresAt });\n return fresh;\n } finally {\n this.inFlight = null;\n }\n })();\n return this.inFlight;\n }\n}\n","/**\n * Error hierarchy for Vesant SDK\n *\n * Provides structured error handling with specific error types\n * for different failure scenarios.\n */\n\nexport class VesantError extends Error {\n public requestId?: string;\n\n constructor(\n message: string,\n public code: string,\n public statusCode?: number,\n public details?: Record<string, unknown>\n ) {\n super(message);\n this.name = 'VesantError';\n Object.setPrototypeOf(this, VesantError.prototype);\n }\n}\n\n/** @deprecated Use VesantError instead */\nexport const CGSError = VesantError;\n/** @deprecated Use VesantError instead */\nexport type CGSError = VesantError;\n\nexport class NetworkError extends VesantError {\n constructor(message: string, public originalError?: unknown) {\n super(message, 'NETWORK_ERROR');\n this.name = 'NetworkError';\n Object.setPrototypeOf(this, NetworkError.prototype);\n }\n}\n\nexport class ValidationError extends VesantError {\n constructor(message: string, fields?: string[]) {\n super(message, 'VALIDATION_ERROR', 400, { fields });\n this.name = 'ValidationError';\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\nexport class ServiceUnavailableError extends VesantError {\n constructor(message: string = 'Service unavailable') {\n super(message, 'SERVICE_UNAVAILABLE', 503);\n this.name = 'ServiceUnavailableError';\n Object.setPrototypeOf(this, ServiceUnavailableError.prototype);\n }\n}\n\nexport class ComplianceBlockedError extends VesantError {\n constructor(reasons: string[]) {\n super('Access blocked due to compliance rules', 'COMPLIANCE_BLOCKED', 403, { reasons });\n this.name = 'ComplianceBlockedError';\n Object.setPrototypeOf(this, ComplianceBlockedError.prototype);\n }\n}\n\nexport class AuthenticationError extends VesantError {\n constructor(message: string = 'Authentication failed') {\n super(message, 'AUTHENTICATION_ERROR', 401);\n this.name = 'AuthenticationError';\n Object.setPrototypeOf(this, AuthenticationError.prototype);\n }\n}\n\nexport class RateLimitError extends VesantError {\n constructor(public retryAfter?: number) {\n super('Rate limit exceeded', 'RATE_LIMIT_EXCEEDED', 429, { retryAfter });\n this.name = 'RateLimitError';\n Object.setPrototypeOf(this, RateLimitError.prototype);\n }\n}\n\nexport class TimeoutError extends VesantError {\n constructor(public timeout: number) {\n super(`Request timeout after ${timeout}ms`, 'TIMEOUT', 408, { timeout });\n this.name = 'TimeoutError';\n Object.setPrototypeOf(this, TimeoutError.prototype);\n }\n}\n\nexport class ComplianceError extends VesantError {\n constructor(\n message: string,\n public originalError?: unknown,\n code: string = 'COMPLIANCE_ERROR'\n ) {\n super(message, code);\n this.name = 'ComplianceError';\n Object.setPrototypeOf(this, ComplianceError.prototype);\n }\n}\n\nexport class CircuitBreakerOpenError extends VesantError {\n constructor() {\n super('Circuit breaker is open — requests are temporarily blocked', 'CIRCUIT_BREAKER_OPEN', 503);\n this.name = 'CircuitBreakerOpenError';\n Object.setPrototypeOf(this, CircuitBreakerOpenError.prototype);\n }\n}\n","/**\n * Circuit breaker pattern for resilient HTTP requests.\n *\n * States: closed (normal) -> open (failing) -> half-open (testing) -> closed\n */\n\nexport type CircuitBreakerState = 'closed' | 'open' | 'half-open';\n\nexport interface CircuitBreakerConfig {\n /** Number of consecutive failures before opening the circuit (default: 5) */\n failureThreshold?: number;\n /** Time in ms to wait before transitioning from open to half-open (default: 30000) */\n resetTimeout?: number;\n /** Number of successes in half-open state before closing (default: 1) */\n successThreshold?: number;\n}\n\nexport interface CircuitBreakerStatus {\n state: CircuitBreakerState;\n failures: number;\n successes: number;\n lastFailureTime: number | null;\n nextRetryTime: number | null;\n}\n\nexport class CircuitBreaker {\n private state: CircuitBreakerState = 'closed';\n private failures = 0;\n private successes = 0;\n private lastFailureTime: number | null = null;\n\n private readonly failureThreshold: number;\n private readonly resetTimeout: number;\n private readonly successThreshold: number;\n\n constructor(config: CircuitBreakerConfig = {}) {\n this.failureThreshold = config.failureThreshold ?? 5;\n this.resetTimeout = config.resetTimeout ?? 30000;\n this.successThreshold = config.successThreshold ?? 1;\n }\n\n /**\n * Check if a request can proceed through the circuit breaker.\n */\n canExecute(): boolean {\n if (this.state === 'closed') {\n return true;\n }\n\n if (this.state === 'open') {\n const now = Date.now();\n if (this.lastFailureTime && now - this.lastFailureTime >= this.resetTimeout) {\n this.state = 'half-open';\n this.successes = 0;\n return true;\n }\n return false;\n }\n\n // half-open: allow requests through for testing\n return true;\n }\n\n /**\n * Record a successful request.\n */\n onSuccess(): void {\n if (this.state === 'half-open') {\n this.successes++;\n if (this.successes >= this.successThreshold) {\n this.state = 'closed';\n this.failures = 0;\n this.successes = 0;\n this.lastFailureTime = null;\n }\n } else if (this.state === 'closed') {\n this.failures = 0;\n }\n }\n\n /**\n * Record a failed request.\n */\n onFailure(): void {\n this.failures++;\n this.lastFailureTime = Date.now();\n\n if (this.state === 'half-open') {\n this.state = 'open';\n this.successes = 0;\n } else if (this.state === 'closed' && this.failures >= this.failureThreshold) {\n this.state = 'open';\n }\n }\n\n /**\n * Get current circuit breaker status.\n */\n getStatus(): CircuitBreakerStatus {\n return {\n state: this.state,\n failures: this.failures,\n successes: this.successes,\n lastFailureTime: this.lastFailureTime,\n nextRetryTime:\n this.state === 'open' && this.lastFailureTime\n ? this.lastFailureTime + this.resetTimeout\n : null,\n };\n }\n\n /**\n * Reset the circuit breaker to its initial closed state.\n */\n reset(): void {\n this.state = 'closed';\n this.failures = 0;\n this.successes = 0;\n this.lastFailureTime = null;\n }\n}\n","/**\n * Rate limit tracking from API response headers.\n *\n * Tracks X-RateLimit-* headers to enable pre-flight checks\n * before making requests.\n */\n\nexport interface RateLimitStatus {\n /** Maximum requests allowed in the window */\n limit: number | null;\n /** Remaining requests in the current window */\n remaining: number | null;\n /** Unix timestamp (seconds) when the rate limit resets */\n reset: number | null;\n /** Seconds until the rate limit resets */\n retryAfter: number | null;\n}\n\nexport class RateLimitTracker {\n private limit: number | null = null;\n private remaining: number | null = null;\n private reset: number | null = null;\n private retryAfter: number | null = null;\n\n /**\n * Extract rate limit information from response headers.\n */\n updateFromHeaders(headers: Headers): void {\n const limit = headers.get('x-ratelimit-limit');\n const remaining = headers.get('x-ratelimit-remaining');\n const reset = headers.get('x-ratelimit-reset');\n const retryAfter = headers.get('retry-after');\n\n if (limit !== null) this.limit = parseInt(limit, 10);\n if (remaining !== null) this.remaining = parseInt(remaining, 10);\n if (reset !== null) this.reset = parseInt(reset, 10);\n if (retryAfter !== null) this.retryAfter = parseInt(retryAfter, 10);\n }\n\n /**\n * Check if the rate limit has been exceeded based on tracked headers.\n */\n isLimitExceeded(): boolean {\n if (this.remaining !== null && this.remaining <= 0) {\n // Check if the reset time has passed\n if (this.reset !== null) {\n const now = Math.floor(Date.now() / 1000);\n if (now >= this.reset) {\n // Reset window has passed, allow requests\n this.remaining = null;\n this.reset = null;\n this.retryAfter = null;\n return false;\n }\n }\n return true;\n }\n return false;\n }\n\n /**\n * Get current rate limit status.\n */\n getStatus(): RateLimitStatus {\n return {\n limit: this.limit,\n remaining: this.remaining,\n reset: this.reset,\n retryAfter: this.retryAfter,\n };\n }\n}\n","import type { Logger } from './config';\n\nexport function createConsoleLogger(): Logger {\n return {\n debug(message: string, meta?: Record<string, unknown>) {\n console.log(`[Vesant SDK] ${message}`, meta !== undefined ? meta : '');\n },\n info(message: string, meta?: Record<string, unknown>) {\n console.info(`[Vesant SDK] ${message}`, meta !== undefined ? meta : '');\n },\n warn(message: string, meta?: Record<string, unknown>) {\n console.warn(`[Vesant SDK] ${message}`, meta !== undefined ? meta : '');\n },\n error(message: string, meta?: Record<string, unknown>) {\n console.error(`[Vesant SDK] ${message}`, meta !== undefined ? meta : '');\n },\n };\n}\n\nexport const noopLogger: Logger = {\n debug() {},\n info() {},\n warn() {},\n error() {},\n};\n","/**\n * Single source of truth for the SDK version.\n */\nexport const SDK_VERSION = '1.8.0';\n","/**\n * Shared browser utility functions.\n *\n * Extracted from ciphertext.ts and hooks.ts to avoid duplication.\n * All functions include SSR guards for safe server-side rendering.\n */\n\n/**\n * Generate a UUID v4\n */\nexport function generateUUID(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n // Fallback for older browsers\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n/**\n * Generate a unique device ID that persists across sessions.\n * Falls back to a random UUID when localStorage is unavailable (SSR).\n */\nexport function generateDeviceId(): string {\n if (typeof window === 'undefined' || typeof localStorage === 'undefined') {\n return generateUUID();\n }\n\n const storageKey = 'vesant_device_id';\n let deviceId = localStorage.getItem(storageKey);\n\n if (!deviceId) {\n deviceId = generateUUID();\n localStorage.setItem(storageKey, deviceId);\n }\n\n return deviceId;\n}\n\n/**\n * Detect browser information from user agent.\n * Returns safe defaults when running server-side.\n */\nexport function getBrowserInfo(): {\n browser: string;\n browser_version: string;\n os: string;\n os_version: string;\n} {\n if (typeof navigator === 'undefined') {\n return { browser: 'unknown', browser_version: '', os: 'unknown', os_version: '' };\n }\n\n const ua = navigator.userAgent;\n let browser = 'unknown';\n let browserVersion = '';\n let os = 'unknown';\n let osVersion = '';\n\n // Detect browser\n if (ua.includes('Firefox/')) {\n browser = 'Firefox';\n browserVersion = ua.match(/Firefox\\/([\\d.]+)/)?.[1] || '';\n } else if (ua.includes('Edg/')) {\n browser = 'Edge';\n browserVersion = ua.match(/Edg\\/([\\d.]+)/)?.[1] || '';\n } else if (ua.includes('Chrome/')) {\n browser = 'Chrome';\n browserVersion = ua.match(/Chrome\\/([\\d.]+)/)?.[1] || '';\n } else if (ua.includes('Safari/') && !ua.includes('Chrome')) {\n browser = 'Safari';\n browserVersion = ua.match(/Version\\/([\\d.]+)/)?.[1] || '';\n } else if (ua.includes('Opera') || ua.includes('OPR/')) {\n browser = 'Opera';\n browserVersion = ua.match(/(?:Opera|OPR)\\/([\\d.]+)/)?.[1] || '';\n }\n\n // Detect OS\n if (ua.includes('Windows')) {\n os = 'Windows';\n if (ua.includes('Windows NT 10.0')) osVersion = '10';\n else if (ua.includes('Windows NT 6.3')) osVersion = '8.1';\n else if (ua.includes('Windows NT 6.2')) osVersion = '8';\n else if (ua.includes('Windows NT 6.1')) osVersion = '7';\n } else if (ua.includes('Mac OS X')) {\n os = 'macOS';\n osVersion = ua.match(/Mac OS X ([\\d_]+)/)?.[1]?.replace(/_/g, '.') || '';\n } else if (ua.includes('Linux')) {\n os = 'Linux';\n } else if (ua.includes('Android')) {\n os = 'Android';\n osVersion = ua.match(/Android ([\\d.]+)/)?.[1] || '';\n } else if (ua.includes('iOS') || ua.includes('iPhone') || ua.includes('iPad')) {\n os = 'iOS';\n osVersion = ua.match(/OS ([\\d_]+)/)?.[1]?.replace(/_/g, '.') || '';\n }\n\n return { browser, browser_version: browserVersion, os, os_version: osVersion };\n}\n","/**\n * Base HTTP client for all Vesant SDK clients\n *\n * Provides common functionality:\n * - Request/response handling\n * - Error handling\n * - Retry logic with exponential backoff\n * - Timeout management\n * - Debug logging\n */\n\nimport type { BaseClientConfig, Logger, RequestInterceptor, RequestOptions } from './config';\nimport { type TokenProvider, StaticApiKeyProvider } from './auth';\nimport {\n VesantError,\n NetworkError,\n TimeoutError,\n AuthenticationError,\n RateLimitError,\n ServiceUnavailableError,\n ValidationError,\n CircuitBreakerOpenError,\n} from './errors';\nimport { CircuitBreaker, type CircuitBreakerStatus } from './circuit-breaker';\nimport { RateLimitTracker, type RateLimitStatus } from './rate-limiter';\nimport { createConsoleLogger } from './logger';\nimport { SDK_VERSION } from './version';\nimport { generateUUID } from '../shared/browser-utils';\n\nexport abstract class BaseClient {\n protected config: BaseClientConfig & { timeout: number; retries: number };\n protected logger: Logger;\n private interceptors: RequestInterceptor[];\n private circuitBreaker: CircuitBreaker | null = null;\n private rateLimitTracker: RateLimitTracker | null = null;\n private authProvider: TokenProvider | undefined;\n\n constructor(config: BaseClientConfig) {\n if (!config.baseURL?.trim()) {\n throw new ValidationError('baseURL is required and must be a non-empty string', ['baseURL']);\n }\n if (!config.tenantId?.trim()) {\n throw new ValidationError('tenantId is required and must be a non-empty string', ['tenantId']);\n }\n\n // The SDK relies on a global fetch (Node.js >= 18). Fail fast with a clear\n // message rather than a later \"fetch is not defined\" ReferenceError.\n if (typeof fetch === 'undefined') {\n throw new VesantError(\n 'The Vesant SDK requires a global fetch (Node.js >= 18). Upgrade Node or provide a fetch polyfill.',\n 'RUNTIME_UNSUPPORTED'\n );\n }\n\n this.interceptors = config.interceptors || [];\n this.logger = config.logger || createConsoleLogger();\n\n // Auto-detect environment from API key prefix\n let environment = config.environment;\n const apiKey = config.apiKey || '';\n if (apiKey.startsWith('pk_test_')) {\n if (environment === 'production') {\n this.logger.warn('Sandbox API key (pk_test_*) used with environment: \"production\" — overriding to \"sandbox\"');\n }\n environment = 'sandbox';\n } else if (apiKey.startsWith('pk_live_') && environment === 'sandbox') {\n this.logger.warn('Production API key (pk_live_*) used with environment: \"sandbox\" — sandbox isolation will still be applied for backward compatibility');\n }\n\n this.config = {\n ...config,\n apiKey,\n environment,\n headers: config.headers || {},\n timeout: config.timeout || 10000,\n retries: config.retries ?? 3,\n debug: config.debug || false,\n interceptors: this.interceptors,\n logger: this.logger,\n };\n\n // Default to a static-apiKey provider so the apiKey path is unchanged; an\n // explicit authProvider (OAuth2 / rotating secrets) takes precedence.\n this.authProvider = config.authProvider ?? (apiKey ? new StaticApiKeyProvider(apiKey) : undefined);\n\n if (config.circuitBreaker) {\n this.circuitBreaker = new CircuitBreaker(config.circuitBreaker);\n }\n if (config.enableRateLimitTracking) {\n this.rateLimitTracker = new RateLimitTracker();\n }\n }\n\n /**\n * Resolve the Idempotency-Key for a request. Mutating methods (POST/PUT/PATCH)\n * get the caller-supplied key or a freshly minted UUID; non-mutating methods get\n * none. requestWithRetry resolves this once and injects it so every retry reuses\n * one key (letting the server dedup replays); a direct request() resolves per call.\n */\n private resolveIdempotencyKey(method: string, requestOptions?: RequestOptions): string | undefined {\n const isMutating = ['POST', 'PUT', 'PATCH'].includes((method || 'GET').toUpperCase());\n if (!isMutating) {\n return undefined;\n }\n return requestOptions?.idempotencyKey ?? generateUUID();\n }\n\n /**\n * Make an HTTP request with timeout and error handling\n */\n protected async request<T>(\n endpoint: string,\n options: RequestInit = {},\n serviceURL?: string,\n requestOptions?: RequestOptions\n ): Promise<T> {\n const requestId = generateUUID();\n\n // Circuit breaker check\n if (this.circuitBreaker && !this.circuitBreaker.canExecute()) {\n const error = new CircuitBreakerOpenError();\n error.requestId = requestId;\n throw error;\n }\n\n // Rate limit pre-check\n if (this.rateLimitTracker && this.rateLimitTracker.isLimitExceeded()) {\n const status = this.rateLimitTracker.getStatus();\n const error = new RateLimitError(status.retryAfter ?? undefined);\n error.requestId = requestId;\n throw error;\n }\n\n const url = `${serviceURL || this.config.baseURL}${endpoint}`;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-Tenant-ID': this.config.tenantId,\n 'X-SDK-Version': `vesant-sdk-ts/${SDK_VERSION}`,\n 'X-Request-ID': requestId,\n ...this.config.headers,\n ...((options.headers as Record<string, string>) || {}),\n };\n\n // Resolve the auth credential per-request via the token provider (async, so a\n // provider can fetch/refresh short-lived credentials). No credential = no header.\n const credential = await this.authProvider?.getCredential({\n tenantId: this.config.tenantId,\n requestId,\n });\n if (credential) {\n headers['Authorization'] = `${credential.scheme ?? 'Bearer'} ${credential.token}`;\n }\n\n // Sandbox header\n if (this.config.environment === 'sandbox') {\n headers['X-Sandbox'] = 'true';\n }\n\n // Idempotency key for mutating methods. Via requestWithRetry the key arrives\n // pre-resolved in requestOptions so all attempts share one; a direct request()\n // falls back to minting one here.\n const method = (options.method || 'GET').toUpperCase();\n const idempotencyKey = this.resolveIdempotencyKey(method, requestOptions);\n if (idempotencyKey) {\n headers['Idempotency-Key'] = idempotencyKey;\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n // Link consumer AbortSignal to internal controller\n if (requestOptions?.signal) {\n if (requestOptions.signal.aborted) {\n controller.abort();\n } else {\n requestOptions.signal.addEventListener('abort', () => controller.abort(), { once: true });\n }\n }\n\n try {\n // Run onRequest interceptors\n let finalOptions: RequestInit = { ...options, headers };\n for (const interceptor of this.interceptors) {\n if (interceptor.onRequest) {\n finalOptions = await interceptor.onRequest(url, finalOptions);\n }\n }\n\n if (this.config.debug) {\n this.logger.debug(`${finalOptions.method || 'GET'} ${endpoint}`);\n }\n\n let response = await fetch(url, {\n ...finalOptions,\n signal: controller.signal,\n });\n\n // Single-shot 401 re-auth: if the provider can refresh, a 401 forces one\n // credential refresh and retry, reusing the same headers (incl. the\n // Idempotency-Key) so a mutating request is not double-submitted.\n if (response.status === 401 && this.authProvider?.canRefresh?.()) {\n const refreshed = await this.authProvider.getCredential({\n tenantId: this.config.tenantId,\n requestId,\n forceRefresh: true,\n });\n if (refreshed) {\n this.config.onCredentialRotated?.({ reason: 'unauthorized' });\n finalOptions = {\n ...finalOptions,\n headers: {\n ...(finalOptions.headers as Record<string, string>),\n Authorization: `${refreshed.scheme ?? 'Bearer'} ${refreshed.token}`,\n },\n };\n response = await fetch(url, { ...finalOptions, signal: controller.signal });\n }\n }\n\n clearTimeout(timeoutId);\n\n // Track rate limit headers\n if (this.rateLimitTracker) {\n this.rateLimitTracker.updateFromHeaders(response.headers);\n }\n\n // Binary download path\n if (requestOptions?.responseType === 'arraybuffer') {\n if (!response.ok) {\n let errData: Record<string, unknown> = {};\n try { errData = await response.json(); } catch { /* ignore */ }\n this.handleErrorResponse(response.status, errData, requestId);\n }\n this.circuitBreaker?.onSuccess();\n const buffer = await response.arrayBuffer();\n return buffer as unknown as T;\n }\n\n let data: Record<string, unknown> | undefined;\n try {\n data = await response.json();\n } catch {\n // Non-JSON response (HTML error pages, 204 No Content, etc.)\n if (!response.ok) {\n this.handleErrorResponse(response.status, {\n error: `HTTP ${response.status}`,\n message: response.statusText,\n }, requestId);\n }\n // OK response but no JSON body (e.g., 204)\n this.circuitBreaker?.onSuccess();\n return undefined as unknown as T;\n }\n\n if (!response.ok) {\n this.handleErrorResponse(response.status, data || {}, requestId);\n }\n\n // Record success for circuit breaker\n this.circuitBreaker?.onSuccess();\n\n // Run onResponse interceptors\n let result: unknown = data;\n for (const interceptor of this.interceptors) {\n if (interceptor.onResponse) {\n result = await interceptor.onResponse(url, result);\n }\n }\n\n if (this.config.debug) {\n this.logger.debug(`Response: ${response.status}`);\n }\n\n return result as T;\n } catch (error) {\n clearTimeout(timeoutId);\n\n // Record failure for circuit breaker (skip for client errors)\n if (\n error instanceof VesantError &&\n error.statusCode &&\n error.statusCode >= 500\n ) {\n this.circuitBreaker?.onFailure();\n } else if (error instanceof NetworkError || error instanceof TimeoutError) {\n this.circuitBreaker?.onFailure();\n }\n\n // Attach requestId to VesantError instances\n if (error instanceof VesantError && !error.requestId) {\n error.requestId = requestId;\n }\n\n // Run onError interceptors\n if (error instanceof Error) {\n for (const interceptor of this.interceptors) {\n if (interceptor.onError) {\n await interceptor.onError(url, error);\n }\n }\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n // Distinguish consumer abort from timeout\n if (requestOptions?.signal?.aborted) {\n const abortError = new VesantError('Request aborted', 'REQUEST_ABORTED');\n abortError.requestId = requestId;\n throw abortError;\n }\n this.circuitBreaker?.onFailure();\n const timeoutError = new TimeoutError(this.config.timeout);\n timeoutError.requestId = requestId;\n throw timeoutError;\n }\n if (error instanceof VesantError) {\n throw error;\n }\n }\n\n const networkError = new NetworkError('Network request failed', error);\n networkError.requestId = requestId;\n this.circuitBreaker?.onFailure();\n throw networkError;\n }\n }\n\n /**\n * Make an HTTP request with retry logic\n */\n protected async requestWithRetry<T>(\n endpoint: string,\n options: RequestInit = {},\n serviceURL?: string,\n retries: number = this.config.retries,\n requestOptions?: RequestOptions\n ): Promise<T> {\n let lastError: Error | undefined;\n\n // Resolve the idempotency key once so every retry attempt reuses it, letting\n // the server dedup replays instead of re-processing (and re-billing) each try.\n const idempotencyKey = this.resolveIdempotencyKey(options.method || 'GET', requestOptions);\n const attemptOptions: RequestOptions | undefined = idempotencyKey\n ? { ...requestOptions, idempotencyKey }\n : requestOptions;\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n return await this.request<T>(endpoint, options, serviceURL, attemptOptions);\n } catch (error) {\n lastError = error instanceof Error ? error : new Error('Unknown error');\n\n // Don't retry on consumer abort\n if (requestOptions?.signal?.aborted) {\n throw lastError;\n }\n\n // Don't retry on client errors (4xx), except 429 (rate limit)\n if (\n lastError instanceof VesantError &&\n lastError.statusCode &&\n lastError.statusCode >= 400 &&\n lastError.statusCode < 500 &&\n lastError.statusCode !== 429\n ) {\n throw lastError;\n }\n\n // Don't retry on last attempt\n if (attempt === retries) {\n break;\n }\n\n // Use Retry-After for 429, otherwise exponential backoff with jitter\n let delay: number;\n if (lastError instanceof RateLimitError && lastError.retryAfter) {\n delay = lastError.retryAfter * 1000;\n } else {\n delay = Math.min(1000 * Math.pow(2, attempt) + Math.random() * 1000, 10000);\n }\n await new Promise((resolve) => setTimeout(resolve, delay));\n\n if (this.config.debug) {\n this.logger.debug(`Retry attempt ${attempt + 1}/${retries} after ${delay.toFixed(0)}ms`);\n }\n }\n }\n\n throw new NetworkError(`Request failed after ${retries} retries`, lastError);\n }\n\n /**\n * Handle error responses from API\n */\n protected handleErrorResponse(status: number, data: Record<string, unknown>, requestId?: string): never {\n const message = (data.error as string) || (data.message as string) || `HTTP ${status}`;\n\n const createError = (): VesantError => {\n switch (status) {\n case 400:\n return new VesantError(message, 'BAD_REQUEST', 400);\n case 401:\n return new AuthenticationError(message);\n case 403:\n return new VesantError(message, 'FORBIDDEN', 403);\n case 404:\n return new VesantError(message, 'NOT_FOUND', 404);\n case 409:\n return new VesantError(message, 'DUPLICATE_PROFILE', 409);\n case 429: {\n const retryAfter = (data.retry_after as number | undefined) || (data.retryAfter as number | undefined);\n return new RateLimitError(retryAfter);\n }\n case 500:\n case 502:\n case 503:\n case 504:\n return new ServiceUnavailableError(message);\n default:\n return new VesantError(message, 'UNKNOWN_ERROR', status);\n }\n };\n\n const error = createError();\n if (requestId) {\n error.requestId = requestId;\n }\n throw error;\n }\n\n /**\n * Build query string from parameters\n */\n protected buildQueryString(params: Record<string, unknown>): string {\n const query = new URLSearchParams();\n\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n if (Array.isArray(value)) {\n value.forEach((item) => query.append(key, String(item)));\n } else {\n query.append(key, String(value));\n }\n }\n });\n\n const queryString = query.toString();\n return queryString ? `?${queryString}` : '';\n }\n\n /**\n * Update client configuration\n */\n updateConfig(config: Partial<BaseClientConfig>): void {\n this.config = {\n ...this.config,\n ...config,\n headers: {\n ...this.config.headers,\n ...(config.headers || {}),\n },\n };\n if (config.logger) {\n this.logger = config.logger;\n }\n if (config.interceptors) {\n this.interceptors = config.interceptors;\n }\n // Rebuild the auth provider when auth-related config changes so a rotated key\n // or a swapped provider takes effect on subsequent requests.\n if (config.authProvider !== undefined || config.apiKey !== undefined) {\n this.authProvider =\n this.config.authProvider ??\n (this.config.apiKey ? new StaticApiKeyProvider(this.config.apiKey) : undefined);\n }\n }\n\n /**\n * Get current configuration (readonly)\n */\n getConfig(): Readonly<BaseClientConfig> {\n return { ...this.config };\n }\n\n /**\n * Get rate limit status from tracked response headers.\n */\n getRateLimitStatus(): RateLimitStatus | null {\n return this.rateLimitTracker?.getStatus() ?? null;\n }\n\n /**\n * Get circuit breaker status.\n */\n getCircuitBreakerStatus(): CircuitBreakerStatus | null {\n return this.circuitBreaker?.getStatus() ?? null;\n }\n\n /**\n * Health check endpoint\n */\n async healthCheck(): Promise<{ status: string; timestamp: string }> {\n return this.request('/api/v1/health');\n }\n}\n","import type { PaginatedResponse } from './types';\n\n/**\n * Lazily walk every item across all pages of a paginated endpoint. `fetchPage`\n * is called with a 1-based page number and must return a PaginatedResponse.\n * Iteration advances until `total_pages` is reached, and stops early if a page\n * returns no items (a guard against a runaway loop on an over-reported\n * total_pages). Pages are fetched on demand as the consumer iterates.\n *\n * @example\n * for await (const profile of paginate((page) => client.listProfiles({ page }))) {\n * // ...\n * }\n */\nexport async function* paginate<T>(\n fetchPage: (page: number) => Promise<PaginatedResponse<T>>\n): AsyncGenerator<T, void, void> {\n let page = 1;\n let totalPages: number;\n do {\n const response = await fetchPage(page);\n const items = response.data ?? [];\n for (const item of items) {\n yield item;\n }\n totalPages = response.total_pages ?? page;\n if (items.length === 0) {\n break;\n }\n page += 1;\n } while (page <= totalPages);\n}\n\n/** Collect every item from a paginated endpoint into a single array. */\nexport async function collectAll<T>(\n fetchPage: (page: number) => Promise<PaginatedResponse<T>>\n): Promise<T[]> {\n const items: T[] = [];\n for await (const item of paginate(fetchPage)) {\n items.push(item);\n }\n return items;\n}\n","/**\n * Pluggable dedup store for webhook replay protection.\n *\n * The default InMemoryDedupStore is process-local — correct for a single\n * long-lived process, but useless across replicas / serverless invocations where\n * the backend's at-least-once retries land on different instances. Supply a\n * shared implementation (e.g. Redis with SETNX + TTL) via WebhookHandlerConfig\n * to dedup reliably in those deployments.\n */\n\nexport interface WebhookDedupStore {\n /** Has this event id already been processed? */\n seen(id: string): Promise<boolean>;\n /** Record this event id as processed, retained for at least ttlMs. */\n mark(id: string, ttlMs: number): Promise<void>;\n}\n\nexport interface InMemoryDedupStoreOptions {\n /** Purge expired entries once the map grows past this size (default: 1000). */\n maxEntries?: number;\n /** Injectable clock (default: Date.now). */\n now?: () => number;\n}\n\nexport class InMemoryDedupStore implements WebhookDedupStore {\n private readonly expiryById = new Map<string, number>();\n private readonly maxEntries: number;\n private readonly now: () => number;\n\n constructor(opts: InMemoryDedupStoreOptions = {}) {\n this.maxEntries = opts.maxEntries ?? 1000;\n this.now = opts.now ?? (() => Date.now());\n }\n\n async seen(id: string): Promise<boolean> {\n return this.expiryById.has(id);\n }\n\n async mark(id: string, ttlMs: number): Promise<void> {\n const now = this.now();\n this.expiryById.set(id, now + ttlMs);\n\n // Bounded memory: purge expired entries once the map grows too large.\n if (this.expiryById.size > this.maxEntries) {\n for (const [key, expiresAt] of this.expiryById) {\n if (now > expiresAt) {\n this.expiryById.delete(key);\n }\n }\n }\n }\n}\n","/**\n * Webhook signature verification utilities.\n *\n * Supports both Web Crypto API (browsers, Deno, Cloudflare Workers)\n * and Node.js crypto module with automatic runtime detection.\n * Uses constant-time comparison to prevent timing attacks.\n */\n\nimport { VesantError } from './errors';\n\nexport interface VerifyWebhookSignatureOptions {\n /** Max allowed clock skew in ms for the signed-timestamp scheme (default: 300000). */\n tolerance?: number;\n /** Clock source for the tolerance check (default: Date.now). */\n now?: () => number;\n /** Accept the legacy body-only `sha256=<hex>` format (default: true, for migration). */\n allowLegacy?: boolean;\n}\n\n/**\n * Verify an HMAC-SHA256 webhook signature.\n *\n * Supports two schemes:\n * - Signed-timestamp (preferred): `t=<unix>,v1=<hex>` where the HMAC is computed\n * over `${t}.${payload}`. The timestamp is inside the signed material, so a\n * replayed body is rejected once `|now - t|` exceeds the tolerance — the check\n * is done BEFORE the HMAC compare and authenticates the timestamp.\n * - Legacy (body-only): `sha256=<hex>` (or raw hex) over the payload alone. Kept\n * for the migration window; disable via `allowLegacy: false`.\n *\n * @returns true if the signature is valid\n */\nexport async function verifyWebhookSignature(\n payload: string,\n signature: string,\n secret: string,\n opts: VerifyWebhookSignatureOptions = {}\n): Promise<boolean> {\n const signed = parseSignedTimestamp(signature);\n if (signed) {\n const tolerance = opts.tolerance ?? 300000;\n const now = opts.now?.() ?? Date.now();\n // Authenticate the timestamp first — reject replays before any HMAC compare.\n if (tolerance > 0 && Math.abs(now - signed.t * 1000) > tolerance) {\n return false;\n }\n const expected = await computeHmacSha256(`${signed.t}.${payload}`, secret);\n return constantTimeEqual(signed.v1, expected);\n }\n\n if (opts.allowLegacy === false) {\n return false;\n }\n\n const hexDigest = await computeHmacSha256(payload, secret);\n // Backend sends \"sha256=<hex>\" format — support both prefixed and raw signatures\n const expectedPrefixed = `sha256=${hexDigest}`;\n\n if (signature.startsWith('sha256=')) {\n return constantTimeEqual(signature, expectedPrefixed);\n }\n\n return constantTimeEqual(signature, hexDigest);\n}\n\n/**\n * Parse the `t=<unix>,v1=<hex>` signed-timestamp scheme; returns null if the\n * signature is not in that form (e.g. legacy `sha256=<hex>`).\n */\nfunction parseSignedTimestamp(signature: string): { t: number; v1: string } | null {\n if (!signature.includes('t=') || !signature.includes('v1=')) {\n return null;\n }\n let t: number | undefined;\n let v1: string | undefined;\n for (const part of signature.split(',')) {\n const eq = part.indexOf('=');\n if (eq === -1) continue;\n const key = part.slice(0, eq).trim();\n const value = part.slice(eq + 1).trim();\n if (key === 't') t = Number(value);\n else if (key === 'v1') v1 = value;\n }\n if (t === undefined || Number.isNaN(t) || !v1) {\n return null;\n }\n return { t, v1 };\n}\n\n/**\n * Compute HMAC-SHA256 hex digest.\n * Automatically selects Web Crypto API or Node.js crypto.\n */\nasync function computeHmacSha256(message: string, secret: string): Promise<string> {\n // Try Web Crypto API first (browsers, Deno, Cloudflare Workers, Node 18+)\n if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto.subtle) {\n const encoder = new TextEncoder();\n const key = await globalThis.crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign']\n );\n const sig = await globalThis.crypto.subtle.sign('HMAC', key, encoder.encode(message));\n return Array.from(new Uint8Array(sig))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n }\n\n // Fallback to Node.js crypto module\n try {\n const { createHmac } = await import('crypto');\n return createHmac('sha256', secret).update(message).digest('hex');\n } catch {\n throw new VesantError(\n 'No crypto implementation available. Requires Web Crypto API or Node.js crypto module.',\n 'CRYPTO_UNAVAILABLE'\n );\n }\n}\n\n/**\n * Constant-time string comparison to prevent timing attacks.\n */\nfunction constantTimeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n\n let result = 0;\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return result === 0;\n}\n","/**\n * Browser-feasible GPS integrity heuristics.\n *\n * The web SDK cannot detect OS-level mock-location or do sensor fusion (that\n * needs the native mobile SDK). What it CAN do is sanity-check the shape of a\n * `getCurrentPosition` fix for signatures of a devtools override / fake-GPS\n * extension, and surface advisory `integrity_flags` for the server to weigh as\n * risk factors. These heuristics are advisory and fail-open — they never throw\n * and never block; the server remains the fail-closed authority.\n */\n\nexport interface GpsIntegrityInput {\n latitude: number;\n longitude: number;\n accuracy?: number | null;\n altitude?: number | null;\n altitudeAccuracy?: number | null;\n heading?: number | null;\n speed?: number | null;\n timestamp?: number;\n}\n\nexport interface GpsIntegrityOptions {\n /** Geolocation permission state, if probed (see probeGeolocationPermission). */\n permissionState?: PermissionState | 'unavailable';\n /** Current time source (default: Date.now). */\n now?: () => number;\n /** Max fix age (ms) before it is considered stale (default: 60_000). */\n maxAgeMs?: number;\n /** Smallest plausible browser-GPS accuracy in meters; below this is suspicious (default: 1). */\n minAccuracyMeters?: number;\n}\n\nexport interface GpsIntegrityResult {\n suspicious: boolean;\n flags: string[];\n}\n\nconst isNil = (v: number | null | undefined): v is null | undefined => v === null || v === undefined;\n\n/**\n * Assess a raw GPS fix for spoof/integrity signals. Pure and fail-open.\n */\nexport function assessGpsIntegrity(input: GpsIntegrityInput, opts: GpsIntegrityOptions = {}): GpsIntegrityResult {\n const flags: string[] = [];\n const now = opts.now ?? (() => Date.now());\n const maxAgeMs = opts.maxAgeMs ?? 60_000;\n const minAccuracy = opts.minAccuracyMeters ?? 1;\n const { accuracy, altitude, altitudeAccuracy, heading, speed, timestamp } = input;\n\n // Accuracy sanity — a genuine browser GPS fix reports a positive, non-trivial\n // radius; exactly 0, absurdly small, or absent is a devtools-override tell.\n if (isNil(accuracy)) {\n flags.push('accuracy_missing');\n } else if (accuracy === 0) {\n flags.push('accuracy_zero');\n } else if (accuracy < minAccuracy) {\n flags.push('accuracy_implausibly_small');\n }\n\n // Motion fields present but no valid accuracy — inconsistent with a real fix.\n const hasMotion = !isNil(heading) || !isNil(speed);\n if (hasMotion && (isNil(accuracy) || accuracy === 0)) {\n flags.push('motion_without_accuracy');\n }\n\n // Real fixes report altitude and altitude_accuracy together, or neither.\n if (!isNil(altitude) && isNil(altitudeAccuracy)) {\n flags.push('altitude_without_accuracy');\n }\n\n // Stale fix.\n if (timestamp !== undefined && now() - timestamp > maxAgeMs) {\n flags.push('stale_timestamp');\n }\n\n // A position obtained while permission is not 'granted' is inconsistent.\n if (opts.permissionState === 'denied' || opts.permissionState === 'prompt') {\n flags.push(`permission_${opts.permissionState}`);\n }\n\n return { suspicious: flags.length > 0, flags };\n}\n\n/**\n * Map a browser GeolocationPosition to the integrity input shape. Shared by the\n * cipherText and location-capture flows so the coord mapping lives in one place.\n */\nexport function gpsIntegrityInputFromPosition(position: GeolocationPosition): GpsIntegrityInput {\n const c = position.coords;\n return {\n latitude: c.latitude,\n longitude: c.longitude,\n accuracy: c.accuracy,\n altitude: c.altitude,\n altitudeAccuracy: c.altitudeAccuracy,\n heading: c.heading,\n speed: c.speed,\n timestamp: position.timestamp,\n };\n}\n\n/**\n * Probe the geolocation permission state. Guarded for browsers that lack the\n * Permissions API (Safari / older WebKit) — returns 'unavailable' rather than\n * throwing, so callers can pass the result straight into assessGpsIntegrity.\n */\nexport async function probeGeolocationPermission(): Promise<PermissionState | 'unavailable'> {\n try {\n if (typeof navigator === 'undefined' || !navigator.permissions?.query) {\n return 'unavailable';\n }\n const status = await navigator.permissions.query({ name: 'geolocation' as PermissionName });\n return status.state;\n } catch {\n return 'unavailable';\n }\n}\n","/**\n * Device-signals envelope utility.\n *\n * Collects device fingerprint and location data from the browser into a compact\n * envelope that the server validates. `collectDeviceSignals` is the preferred\n * name; `generateCipherText` remains available as an alias.\n *\n * The cipherText is used for:\n * - Registration verification\n * - Login verification\n * - Transaction verification\n * - Periodic location checks\n *\n * Scope: the web SDK collects GPS + IP only. WiFi/cell/sensor-fusion positioning\n * and OS-level mock-location detection are not possible in a browser and require\n * the native mobile SDK (separate backlog item). GPS fixes are additionally run\n * through advisory in-browser integrity heuristics (see ./integrity).\n */\n\nimport type {\n CipherTextPayload,\n CipherTextOptions,\n CipherTextResult,\n CipherTextReason,\n GeolocationConfigResponse,\n} from './types';\nimport { SDK_VERSION } from '../core/version';\nimport { VesantError } from '../core/errors';\nimport { getBrowserInfo, generateDeviceId as getOrCreateDeviceId } from '../shared/browser-utils';\nimport { assessGpsIntegrity, gpsIntegrityInputFromPosition, probeGeolocationPermission } from './integrity';\n\nconst CIPHER_TEXT_EXPIRY_MINUTES = 5;\n\n\n/**\n * Get WebGL renderer information for fingerprinting\n */\nfunction getWebGLInfo(): { vendor: string; renderer: string } | null {\n if (typeof document === 'undefined') return null;\n\n try {\n const canvas = document.createElement('canvas');\n const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');\n\n if (!gl) return null;\n\n const debugInfo = (gl as WebGLRenderingContext).getExtension('WEBGL_debug_renderer_info');\n if (!debugInfo) return null;\n\n return {\n vendor: (gl as WebGLRenderingContext).getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) || '',\n renderer: (gl as WebGLRenderingContext).getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) || '',\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Get network information if available\n */\nfunction getNetworkInfo(): CipherTextPayload['network'] | undefined {\n if (typeof navigator === 'undefined') return undefined;\n\n const connection = (navigator as any).connection ||\n (navigator as any).mozConnection ||\n (navigator as any).webkitConnection;\n\n if (!connection) return undefined;\n\n return {\n effective_type: connection.effectiveType,\n downlink: connection.downlink,\n rtt: connection.rtt,\n save_data: connection.saveData,\n };\n}\n\n/**\n * Request GPS location from the browser\n */\nasync function requestGPSLocation(\n timeout: number = 10000,\n highAccuracy: boolean = true\n): Promise<CipherTextPayload['location'] | null> {\n if (typeof navigator === 'undefined' || !navigator.geolocation) {\n return null;\n }\n\n // Probed once up-front so the (synchronous) success callback can pass it to the\n // advisory integrity heuristics without awaiting inside the callback.\n const permissionState = await probeGeolocationPermission();\n\n return new Promise((resolve) => {\n navigator.geolocation.getCurrentPosition(\n (position) => {\n const { latitude, longitude, accuracy } = position.coords;\n\n // Validate coordinates\n if (latitude < -90 || latitude > 90) {\n resolve(null);\n return;\n }\n if (longitude < -180 || longitude > 180) {\n resolve(null);\n return;\n }\n if (accuracy !== null && accuracy !== undefined && accuracy <= 0) {\n resolve(null);\n return;\n }\n\n const { flags } = assessGpsIntegrity(gpsIntegrityInputFromPosition(position), { permissionState });\n\n resolve({\n latitude,\n longitude,\n accuracy,\n altitude: position.coords.altitude ?? undefined,\n altitude_accuracy: position.coords.altitudeAccuracy ?? undefined,\n heading: position.coords.heading ?? undefined,\n speed: position.coords.speed ?? undefined,\n timestamp: position.timestamp,\n integrity_flags: flags.length ? flags : undefined,\n });\n },\n () => {\n // Location denied or error - resolve with null (non-fatal)\n resolve(null);\n },\n {\n enableHighAccuracy: highAccuracy,\n timeout: timeout,\n maximumAge: 0,\n }\n );\n });\n}\n\n/**\n * Collect device fingerprint data\n */\nfunction collectDeviceData(includeWebGL: boolean): CipherTextPayload['device'] {\n const browserInfo = getBrowserInfo();\n const webglInfo = includeWebGL ? getWebGLInfo() : null;\n\n return {\n device_id: getOrCreateDeviceId(),\n user_agent: typeof navigator !== 'undefined' ? navigator.userAgent : '',\n platform: typeof navigator !== 'undefined' ? navigator.platform : '',\n browser: browserInfo.browser,\n browser_version: browserInfo.browser_version,\n os: browserInfo.os,\n os_version: browserInfo.os_version,\n screen_resolution:\n typeof screen !== 'undefined' ? `${screen.width}x${screen.height}` : undefined,\n language: typeof navigator !== 'undefined' ? navigator.language : undefined,\n timezone: Intl?.DateTimeFormat?.()?.resolvedOptions?.()?.timeZone,\n color_depth: typeof screen !== 'undefined' ? screen.colorDepth : undefined,\n hardware_concurrency:\n typeof navigator !== 'undefined' ? navigator.hardwareConcurrency : undefined,\n device_memory: typeof navigator !== 'undefined' ? (navigator as any).deviceMemory : undefined,\n touch_support:\n typeof navigator !== 'undefined' ? navigator.maxTouchPoints > 0 : undefined,\n webgl_vendor: webglInfo?.vendor,\n webgl_renderer: webglInfo?.renderer,\n };\n}\n\n/**\n * Encode payload to base64\n */\nfunction encodePayload(payload: CipherTextPayload): string {\n const json = JSON.stringify(payload);\n\n if (typeof btoa !== 'undefined') {\n // Browser\n return btoa(unescape(encodeURIComponent(json)));\n } else if (typeof Buffer !== 'undefined') {\n // Node.js\n return Buffer.from(json, 'utf-8').toString('base64');\n }\n\n throw new VesantError('No base64 encoding method available', 'BASE64_UNAVAILABLE');\n}\n\n/**\n * Generate a cipherText containing encrypted device and location data\n *\n * @param options - Options for cipherText generation\n * @returns CipherText result with the encrypted string\n *\n * @example\n * ```typescript\n * // Basic usage for login\n * const result = await generateCipherText({ reason: 'login' });\n * console.log(result.cipherText);\n *\n * // With GPS location for registration\n * const result = await generateCipherText({\n * reason: 'registration',\n * requestLocation: true,\n * locationTimeout: 15000\n * });\n *\n * if (result.locationCaptured) {\n * console.log('GPS location included');\n * }\n * ```\n */\nexport async function generateCipherText(\n options: CipherTextOptions,\n config?: GeolocationConfigResponse\n): Promise<CipherTextResult> {\n const warnings: string[] = [];\n\n // Auto-enable GPS if tenant config requires it for this event type\n let requestLocation = options.requestLocation ?? false;\n let gpsRequiredByConfig = false;\n if (config?.require_gps) {\n const reason = options.reason;\n if (\n (reason === 'login' && config.require_gps.login) ||\n (reason === 'registration' && config.require_gps.registration) ||\n (reason === 'transaction' && config.require_gps.transaction)\n ) {\n if (!requestLocation) {\n gpsRequiredByConfig = true;\n }\n requestLocation = true;\n }\n }\n\n // Collect device data\n const deviceData = collectDeviceData(options.includeWebGL !== false);\n\n // Optionally request GPS location\n let locationData: CipherTextPayload['location'] | undefined;\n if (requestLocation) {\n const location = await requestGPSLocation(\n options.locationTimeout || 10000,\n options.highAccuracy !== false\n );\n\n if (location) {\n locationData = location;\n if (location.integrity_flags?.length) {\n warnings.push(`GPS integrity flags (advisory): ${location.integrity_flags.join(', ')}`);\n }\n } else if (gpsRequiredByConfig) {\n throw new VesantError(\n `GPS location is required for ${options.reason} by tenant configuration, but GPS was not available or permission was denied`,\n 'GPS_REQUIRED'\n );\n } else {\n warnings.push('GPS location not available or permission denied');\n }\n }\n\n // Collect network info\n let networkData: CipherTextPayload['network'] | undefined;\n if (options.includeNetworkInfo !== false) {\n networkData = getNetworkInfo();\n }\n\n // Build payload\n const now = new Date();\n const expiry = new Date(now.getTime() + CIPHER_TEXT_EXPIRY_MINUTES * 60 * 1000);\n\n const payload: CipherTextPayload = {\n device: deviceData,\n location: locationData,\n network: networkData,\n metadata: {\n collected_at: now.toISOString(),\n sdk_version: SDK_VERSION,\n collection_reason: options.reason,\n page_url: typeof window !== 'undefined' ? window.location.href : undefined,\n referrer: typeof document !== 'undefined' ? document.referrer || undefined : undefined,\n },\n };\n\n // Encode payload (no obfuscation - HTTPS provides transport security)\n const encoded = encodePayload(payload);\n\n // Create final cipherText with version and timestamp prefix\n const timestamp = now.getTime().toString(36); // Base36 timestamp\n\n // Always emit the unsigned v01 envelope `01.{timestamp}.{base64(JSON)}`. The\n // SDK never holds a signing key — a client-side HMAC signed with a tenant secret\n // pulled into the browser proves possession of a leakable secret, not device\n // authenticity, so the server is the sole signer. This is a base64 JSON envelope,\n // NOT encryption; integrity is enforced server-side.\n const cipherText = `01.${timestamp}.${encoded}`;\n\n return {\n cipherText,\n locationCaptured: !!locationData,\n warnings: warnings.length > 0 ? warnings : undefined,\n generatedAt: now.toISOString(),\n expiresAt: expiry.toISOString(),\n };\n}\n\n/**\n * Collect a device-signals envelope for server-side validation. Preferred name\n * for {@link generateCipherText}, which remains available as an alias.\n */\nexport const collectDeviceSignals = generateCipherText;\n\n/**\n * Decode a cipherText (for debugging/testing - not for production use)\n * In production, decryption happens on the server\n */\nexport function decodeCipherText(cipherText: string): CipherTextPayload | null {\n try {\n const parts = cipherText.split('.');\n // v01: 3 parts, v02: 4 parts (4th is HMAC — ignored when decoding)\n if (parts.length !== 3 && parts.length !== 4) return null;\n\n const [version, , encodedB64] = parts;\n if (version !== '01' && version !== '02') return null;\n\n // Decode matches encode: just base64 decode (no obfuscation)\n const json = decodeURIComponent(escape(atob(encodedB64)));\n\n return JSON.parse(json) as CipherTextPayload;\n } catch {\n return null;\n }\n}\n\n/**\n * Check if a cipherText is expired\n */\nexport function isCipherTextExpired(cipherText: string): boolean {\n try {\n const parts = cipherText.split('.');\n if (parts.length !== 3 && parts.length !== 4) return true;\n\n const timestampB36 = parts[1];\n const timestamp = parseInt(timestampB36, 36);\n const now = Date.now();\n const expiryMs = CIPHER_TEXT_EXPIRY_MINUTES * 60 * 1000;\n\n return now - timestamp > expiryMs;\n } catch {\n return true;\n }\n}\n\n// Re-export types\nexport type { CipherTextPayload, CipherTextOptions, CipherTextResult, CipherTextReason, GeolocationConfigResponse };\n","/**\n * GeolocationClient - TypeScript SDK for Vesant Geolocation & Compliance Service\n *\n * Provides type-safe methods to interact with the geolocation service API.\n * Extends BaseClient for consistent retry logic, timeout handling, and error management.\n */\n\nimport { BaseClient } from '../core/client';\nimport { ValidationError } from '../core/errors';\nimport type { BaseClientConfig, RequestOptions } from '../core/config';\nimport type {\n GeolocationClientConfig,\n GeolocationConfigResponse,\n VerifyIPRequest,\n LocationVerification,\n ComplianceCheckResponse,\n PaginationParams,\n // Location Request Types\n LocationRequest,\n CreateLocationRequestRequest,\n LocationRequestResult,\n LocationRequestFilters,\n LocationRequestListResponse,\n ResendLocationRequestRequest,\n LocationShareInfo,\n LocationCaptureRequest,\n LocationCaptureResponse,\n // CipherText Types\n ValidateCipherTextRequest,\n SignalsNonce,\n ValidateCipherTextResponse,\n CipherTextReason,\n CipherTextCustomerData,\n CipherTextOptions,\n CipherTextResult,\n} from './types';\nimport { generateCipherText as generateCipherTextUtil } from './ciphertext';\n\n/**\n * GeolocationClient extends BaseClient for:\n * - Consistent retry logic with exponential backoff\n * - Unified error handling (VesantError, NetworkError, TimeoutError, etc.)\n * - Automatic timeout management\n * - Debug logging\n *\n * All geolocation verification calls use requestWithRetry() to handle\n * transient failures gracefully.\n */\n/** How long a fetched GPS requirement config is reused before it is read again. */\nconst DEFAULT_GPS_CONFIG_TTL_MS = 5 * 60 * 1000;\n\nexport class GeolocationClient extends BaseClient {\n private readonly gpsConfigTtlMs: number;\n private gpsConfigCache: { value: GeolocationConfigResponse; expiresAt: number } | null = null;\n\n constructor(config: GeolocationClientConfig) {\n // Convert GeolocationClientConfig to BaseClientConfig\n const baseConfig: BaseClientConfig = {\n baseURL: config.baseURL,\n tenantId: config.tenantId,\n apiKey: config.apiKey,\n headers: config.headers,\n timeout: config.timeout,\n retries: 3, // Default retry count for geolocation calls\n debug: config.debug,\n logger: config.logger,\n environment: config.environment,\n };\n super(baseConfig);\n this.gpsConfigTtlMs = config.gpsConfigTtlMs ?? DEFAULT_GPS_CONFIG_TTL_MS;\n }\n\n // ============================================================================\n // IP Verification & Compliance\n // ============================================================================\n\n /**\n * Verify an IP address and check compliance\n *\n * Uses requestWithRetry() for automatic retry on transient failures.\n *\n * @param request - Verification request with IP, user ID, event type, and optional device fingerprint\n * @returns Location verification result with risk assessment\n *\n * @example\n * ```typescript\n * const result = await client.verifyIP({\n * ip_address: \"8.8.8.8\",\n * user_id: \"user_123\",\n * event_type: \"login\",\n * device_fingerprint: {\n * device_id: \"device_abc\",\n * user_agent: navigator.userAgent,\n * platform: \"web\"\n * }\n * });\n *\n * if (result.is_blocked) {\n * console.log(\"Access blocked:\", result.risk_reasons);\n * }\n * ```\n */\n async verifyIP(request: VerifyIPRequest, requestOptions?: RequestOptions): Promise<LocationVerification> {\n // ip_address is optional: when omitted the server derives the connecting IP.\n // If a value is supplied it must be non-empty (empty string is a caller bug).\n if (request.ip_address !== undefined && !request.ip_address.trim()) {\n throw new ValidationError('ip_address, when provided, must be a non-empty string', ['ip_address']);\n }\n\n // Use requestWithRetry for critical verification calls\n return this.requestWithRetry<LocationVerification>('/api/v1/geo/verify', {\n method: 'POST',\n body: JSON.stringify(request),\n }, undefined, undefined, requestOptions);\n }\n\n /**\n * Check compliance for a specific country\n *\n * @param countryISO - ISO 3166-1 alpha-2 country code (e.g., \"US\", \"GB\")\n * @returns Jurisdiction configuration and compliance status\n *\n * @example\n * ```typescript\n * const compliance = await client.checkCompliance(\"KP\"); // North Korea\n * if (!compliance.is_compliant) {\n * console.log(\"Country is not allowed:\", compliance.jurisdiction?.status);\n * }\n * ```\n */\n async checkCompliance(countryISO: string, requestOptions?: RequestOptions): Promise<ComplianceCheckResponse> {\n return this.requestWithRetry<ComplianceCheckResponse>(\n `/api/v1/geo/check-compliance`,\n {\n method: 'POST',\n body: JSON.stringify({ country_iso: countryISO }),\n }, undefined, undefined, requestOptions\n );\n }\n\n // ============================================================================\n // GPS Configuration\n // ============================================================================\n\n /**\n * Get the tenant's GPS requirement configuration\n *\n * Returns which event types require GPS location to be collected.\n * Use this to auto-enable GPS collection in generateCipherText when required.\n *\n * @returns GPS requirement config per event type\n *\n * @example\n * ```typescript\n * const config = await client.getGPSConfig();\n * if (config.require_gps.login) {\n * // GPS is required for login — auto-enable location\n * }\n * ```\n */\n async getGPSConfig(requestOptions?: RequestOptions): Promise<GeolocationConfigResponse> {\n const cached = this.gpsConfigCache;\n if (cached && cached.expiresAt > Date.now()) {\n return cached.value;\n }\n return this.refreshGPSConfig(requestOptions);\n }\n\n /**\n * Re-read the tenant's GPS requirement configuration, ignoring any copy held\n * from an earlier read.\n *\n * These requirements are edited in the compliance console while your\n * application is running. `getGPSConfig` reuses a fetched copy for a short\n * period so a long-lived session does not call the API on every event; call\n * this when you need a change to take effect immediately — for example right\n * after an administrator saves new settings.\n *\n * @returns The current GPS requirement config per event type\n *\n * @example\n * ```typescript\n * const config = await client.refreshGPSConfig();\n * if (config.require_gps.login) {\n * // GPS is now required for login\n * }\n * ```\n */\n async refreshGPSConfig(requestOptions?: RequestOptions): Promise<GeolocationConfigResponse> {\n const value = await this.requestWithRetry<GeolocationConfigResponse>(\n '/api/v1/geo/config', undefined, undefined, undefined, requestOptions\n );\n // Only cache a successful read — a failure must not pin a stale copy.\n this.gpsConfigCache = { value, expiresAt: Date.now() + this.gpsConfigTtlMs };\n return value;\n }\n\n /**\n * Mint a short-lived, single-use device-signals nonce.\n *\n * The nonce is bound to the tenant, user, and event type and is consumed\n * server-side during validation, so a captured device-signals envelope cannot\n * be replayed. `validateCipherText` mints and attaches one automatically; call\n * this directly only if you manage the nonce yourself.\n *\n * @param userId - User ID the nonce is bound to\n * @param eventType - Event type the nonce is bound to (login, registration, ...)\n * @returns The nonce and its expiry\n */\n async fetchSignalsNonce(\n userId: string,\n eventType: CipherTextReason,\n requestOptions?: RequestOptions\n ): Promise<SignalsNonce> {\n if (!userId?.trim()) {\n throw new ValidationError('userId is required and must be a non-empty string', ['userId']);\n }\n // Single attempt (no retry): minting is on the validation critical path and\n // is best-effort — the server enforces when a nonce is required, so a retry\n // storm would only add latency.\n const request = { user_id: userId, event_type: eventType };\n return this.request<SignalsNonce>(\n '/api/v1/geo/signals-token',\n {\n method: 'POST',\n body: JSON.stringify(request),\n }, undefined, requestOptions\n );\n }\n\n /**\n * Best-effort nonce mint for validation. Returns undefined if minting fails —\n * the server is the sole authority and blocks when a nonce is required, so this\n * never downgrades security on the client's say-so.\n */\n private async resolveSignalsNonce(\n userId: string,\n eventType: CipherTextReason,\n requestOptions?: RequestOptions\n ): Promise<string | undefined> {\n try {\n const { nonce } = await this.fetchSignalsNonce(userId, eventType, requestOptions);\n return nonce;\n } catch (err) {\n this.logger.warn(\n `Failed to mint device-signals nonce; proceeding without it: ${err instanceof Error ? err.message : String(err)}`\n );\n return undefined;\n }\n }\n\n // ============================================================================\n // CipherText Validation\n // ============================================================================\n\n /**\n * Validate a cipherText generated by the frontend SDK\n *\n * The cipherText contains encrypted device fingerprint and optional location data.\n * This method decrypts and validates the data, returning device info, location,\n * and risk assessment.\n *\n * @param cipherText - The encrypted cipherText string from generateCipherText()\n * @param userId - User ID associated with this verification\n * @param eventType - Reason for verification (login, registration, etc.)\n * @param expectedIP - Optional expected IP address for additional validation\n * @param customerData - Optional customer data for risk profile creation (used when user is blocked)\n * @returns Validation result with device info, location, and risk assessment\n *\n * @example\n * ```typescript\n * // Validate cipherText during registration with customer data\n * const result = await client.validateCipherText(\n * cipherText,\n * \"user_123\",\n * \"registration\",\n * clientIP,\n * {\n * full_name: \"John Doe\",\n * email: \"john@example.com\",\n * country: \"US\",\n * state: \"CA\"\n * }\n * );\n *\n * if (!result.valid) {\n * console.log(\"CipherText validation failed:\", result.errors);\n * return;\n * }\n *\n * if (result.risk.is_blocked) {\n * console.log(\"Access blocked:\", result.risk.block_reasons);\n * // A risk profile with full customer data has been created for the alert\n * }\n * ```\n */\n async validateCipherText(\n cipherText: string,\n userId: string,\n eventType: CipherTextReason,\n expectedIP?: string,\n customerData?: CipherTextCustomerData,\n requestOptions?: RequestOptions\n ): Promise<ValidateCipherTextResponse> {\n if (!cipherText?.trim()) {\n throw new ValidationError('cipherText is required and must be a non-empty string', ['cipherText']);\n }\n if (!userId?.trim()) {\n throw new ValidationError('userId is required and must be a non-empty string', ['userId']);\n }\n\n const nonce = await this.resolveSignalsNonce(userId, eventType, requestOptions);\n\n const request: ValidateCipherTextRequest = {\n cipher_text: cipherText,\n user_id: userId,\n event_type: eventType,\n expected_ip: expectedIP,\n customer_data: customerData,\n nonce,\n };\n\n return this.requestWithRetry<ValidateCipherTextResponse>(\n '/api/v1/geo/validate-ciphertext',\n {\n method: 'POST',\n body: JSON.stringify(request),\n }, undefined, undefined, requestOptions\n );\n }\n\n /**\n * Validate cipherText and verify IP in a single call\n *\n * Combines cipherText validation with IP verification for complete\n * location and device verification in one request.\n *\n * @param cipherText - The encrypted cipherText string\n * @param ipAddress - Client IP address\n * @param userId - User ID\n * @param eventType - Event type (login, registration, etc.)\n * @returns Combined validation and verification result\n *\n * @example\n * ```typescript\n * const result = await client.validateAndVerify(\n * cipherText,\n * clientIP,\n * \"user_123\",\n * \"registration\"\n * );\n *\n * if (!result.ciphertext_valid) {\n * throw new Error(\"Device verification failed\");\n * }\n *\n * if (result.location.is_blocked) {\n * throw new Error(\"Location not allowed\");\n * }\n * ```\n */\n async validateAndVerify(\n cipherText: string,\n ipAddress: string,\n userId: string,\n eventType: CipherTextReason,\n requestOptions?: RequestOptions\n ): Promise<{\n ciphertext_valid: boolean;\n ciphertext_result: ValidateCipherTextResponse;\n location: LocationVerification;\n }> {\n // validate-ciphertext already performs full geo verification on the server\n // (IP lookup, risk scoring, alert triggering, device tracking). A separate\n // verifyIP call would create duplicate geolocation records and alerts.\n const cipherTextResult = await this.validateCipherText(\n cipherText,\n userId,\n eventType,\n ipAddress,\n undefined,\n requestOptions\n );\n\n // Build LocationVerification from the enriched ciphertext response.\n // If risk data is missing (partial response), fall back to verifyIP.\n const loc = cipherTextResult.location;\n const risk = cipherTextResult.risk;\n\n if (!risk) {\n const locationResult = await this.verifyIP({\n ip_address: ipAddress,\n user_id: userId,\n event_type: eventType,\n }, requestOptions);\n return {\n ciphertext_valid: cipherTextResult.valid,\n ciphertext_result: cipherTextResult,\n location: locationResult,\n };\n }\n\n const location: LocationVerification = {\n ip_address: cipherTextResult.ip_address,\n location: {\n country: loc?.country ?? '',\n country_iso: loc?.country_iso ?? '',\n city: loc?.city ?? '',\n region: loc?.region ?? '',\n postal_code: '',\n latitude: loc?.latitude ?? 0,\n longitude: loc?.longitude ?? 0,\n timezone: '',\n is_vpn: risk.is_vpn ?? false,\n is_proxy: risk.is_proxy ?? false,\n is_tor: risk.is_tor ?? false,\n is_hosting: risk.is_hosting ?? false,\n is_anonymizer: risk.is_vpn || risk.is_proxy || risk.is_tor,\n },\n is_compliant: cipherTextResult.is_compliant ?? !risk.is_blocked,\n is_blocked: risk.is_blocked ?? false,\n risk_level: risk.level ?? 'low',\n risk_score: risk.score ?? 0,\n risk_reasons: risk.is_blocked && risk.block_reasons\n ? risk.block_reasons\n : (risk.factors ?? []),\n risk_reasons_structured: risk.block_reasons_structured ?? [],\n jurisdiction: cipherTextResult.jurisdiction,\n geofence_evaluation: cipherTextResult.geofence_evaluation,\n record_id: cipherTextResult.record_id ?? '',\n gps_required: cipherTextResult.gps_required,\n };\n\n return {\n ciphertext_valid: cipherTextResult.valid,\n ciphertext_result: cipherTextResult,\n location,\n };\n }\n\n // ============================================================================\n // Location Request (Live Location Tracking)\n // ============================================================================\n\n /**\n * Create a location request to get customer's live location\n *\n * @param request - Location request details\n * @returns Location request result with share link\n *\n * @example\n * ```typescript\n * const result = await client.createLocationRequest({\n * user_id: \"customer_123\",\n * channel: \"sms\",\n * phone: \"+1234567890\",\n * reason: \"Verification for high-value transaction\"\n * });\n *\n * console.log(`Share link sent: ${result.share_link}`);\n * console.log(`Expires at: ${result.token_expiry}`);\n * ```\n */\n async createLocationRequest(\n request: CreateLocationRequestRequest,\n requestOptions?: RequestOptions\n ): Promise<LocationRequestResult> {\n return this.request<LocationRequestResult>('/api/v1/location-requests', {\n method: 'POST',\n body: JSON.stringify(request),\n }, undefined, requestOptions);\n }\n\n /**\n * Get a location request by ID\n *\n * @param requestId - Location request ID\n * @returns Location request details\n */\n async getLocationRequest(requestId: string, requestOptions?: RequestOptions): Promise<LocationRequest> {\n return this.request<LocationRequest>(`/api/v1/location-requests/${requestId}`, undefined, undefined, requestOptions);\n }\n\n /**\n * List location requests with filters and pagination\n *\n * @param filters - Optional filters\n * @param pagination - Optional pagination\n * @returns Paginated list of location requests\n *\n * @example\n * ```typescript\n * const requests = await client.listLocationRequests(\n * { status: \"completed\", user_id: \"customer_123\" },\n * { page: 1, limit: 20 }\n * );\n * ```\n */\n async listLocationRequests(\n filters?: LocationRequestFilters,\n pagination?: PaginationParams,\n requestOptions?: RequestOptions\n ): Promise<LocationRequestListResponse> {\n const params: Record<string, unknown> = {\n ...filters,\n ...pagination,\n };\n\n return this.request<LocationRequestListResponse>(\n `/api/v1/location-requests${this.buildQueryString(params)}`,\n undefined, undefined, requestOptions\n );\n }\n\n /**\n * Cancel a pending location request\n *\n * @param requestId - Location request ID\n */\n async cancelLocationRequest(requestId: string, requestOptions?: RequestOptions): Promise<void> {\n await this.request(`/api/v1/location-requests/${requestId}/cancel`, {\n method: 'POST',\n }, undefined, requestOptions);\n }\n\n /**\n * Resend notification for a location request\n *\n * @param requestId - Location request ID\n * @param contact - Email or phone to send to\n */\n async resendLocationRequest(\n requestId: string,\n contact: ResendLocationRequestRequest,\n requestOptions?: RequestOptions\n ): Promise<void> {\n await this.request(`/api/v1/location-requests/${requestId}/resend`, {\n method: 'POST',\n body: JSON.stringify(contact),\n }, undefined, requestOptions);\n }\n\n // ============================================================================\n // Location Share (Customer-facing - for SDK integration in customer apps)\n // ============================================================================\n\n /**\n * Get location share info (customer-facing)\n * This is called from the customer's device to get request details\n *\n * @param token - Secure token from share link\n * @returns Location share info\n */\n async getLocationShareInfo(token: string, requestOptions?: RequestOptions): Promise<LocationShareInfo> {\n return this.request<LocationShareInfo>(`/api/v1/location/share/${token}`, undefined, undefined, requestOptions);\n }\n\n /**\n * Submit location capture (customer-facing)\n * This is called from the customer's device to submit their location\n *\n * @param token - Secure token from share link\n * @param capture - Location capture data (GPS or WiFi)\n * @returns Capture response\n *\n * @example\n * ```typescript\n * // GPS (the web SDK is GPS + IP only; the server handles the IP fallback)\n * const result = await client.captureLocation(token, {\n * latitude: 37.7749,\n * longitude: -122.4194,\n * accuracy: 10\n * });\n * ```\n */\n async captureLocation(\n token: string,\n capture: LocationCaptureRequest,\n requestOptions?: RequestOptions\n ): Promise<LocationCaptureResponse> {\n return this.request<LocationCaptureResponse>(`/api/v1/location/share/${token}`, {\n method: 'POST',\n body: JSON.stringify(capture),\n }, undefined, requestOptions);\n }\n\n // ============================================================================\n // CipherText Generation\n // ============================================================================\n\n /**\n * Generate a device-signals envelope containing device and location data,\n * validated by the server.\n *\n * @param options - Options for envelope generation\n * @param gpsConfig - Optional GPS config (from getGPSConfig)\n * @returns The device-signals envelope result\n *\n * @example\n * ```typescript\n * const result = await client.generateCipherText({ reason: 'login' });\n * console.log(result.cipherText); // device-signals envelope\n * ```\n */\n async generateCipherText(\n options: Omit<CipherTextOptions, 'apiKey' | 'signingKey'>,\n gpsConfig?: GeolocationConfigResponse,\n ): Promise<CipherTextResult> {\n // The SDK never holds a signing key and never signs client-side — it just\n // collects the device-signals envelope (base64 JSON, not encrypted). The\n // server is the sole signer. GPS config is fetched to auto-enable location.\n const resolvedGpsConfig = gpsConfig ?? (await this.getGPSConfig());\n return generateCipherTextUtil(options, resolvedGpsConfig);\n }\n\n // ============================================================================\n // Utility Methods (inherited from BaseClient: healthCheck, updateConfig, getConfig, buildQueryString)\n // ============================================================================\n}\n","/**\n * RiskProfileClient - Customer Risk Profile Management\n *\n * Provides methods to create, retrieve, and manage customer risk profiles\n * in the Vesant Compliance Platform.\n */\n\nimport { BaseClient } from '../core/client';\nimport { VesantError } from '../core/errors';\nimport type { BaseClientConfig, RequestOptions } from '../core/config';\nimport type {\n CustomerProfile,\n CreateProfileRequest,\n UpdateProfileRequest,\n} from './types';\n\nexport class RiskProfileClient extends BaseClient {\n constructor(config: BaseClientConfig) {\n super(config);\n }\n\n // ============================================================================\n // Profile Management\n // ============================================================================\n\n /**\n * Create a new customer risk profile\n *\n * @param request - Profile creation data\n * @returns Created customer profile\n *\n * @example\n * ```typescript\n * const profile = await client.createProfile({\n * customer_id: 'CUST-12345',\n * entity_type: 'individual',\n * customer_status: 'active',\n * full_name: 'John Doe',\n * email_address: 'john@example.com',\n * date_of_birth: '1990-01-15',\n * country_of_residence: 'US'\n * });\n * ```\n */\n async createProfile(request: CreateProfileRequest, requestOptions?: RequestOptions): Promise<CustomerProfile> {\n return this.request<CustomerProfile>('/api/v1/profiles', {\n method: 'POST',\n body: JSON.stringify(request),\n }, undefined, requestOptions);\n }\n\n /**\n * Get customer profile by customer ID\n *\n * Note: This searches for the profile using the customer_id field.\n * Returns the first matching profile for the tenant.\n *\n * @param customerId - Customer ID to search for\n * @returns Customer profile\n *\n * @example\n * ```typescript\n * const profile = await client.getProfile('CUST-12345');\n * ```\n */\n async getProfile(customerId: string, requestOptions?: RequestOptions): Promise<CustomerProfile> {\n try {\n // Use the SDK-authenticated endpoint (API key auth)\n return await this.request<CustomerProfile>(\n `/api/v1/profiles?customer_id=${encodeURIComponent(customerId)}`,\n undefined, undefined, requestOptions\n );\n } catch (error) {\n // Normalize to NOT_FOUND for consistent error handling in getOrCreateProfile\n if (error instanceof VesantError && (error.statusCode === 404 || error.code === 'NOT_FOUND')) {\n throw new VesantError('Profile not found', 'NOT_FOUND', 404);\n }\n throw error;\n }\n }\n\n /**\n * Update customer profile\n *\n * @param profileId - Profile UUID\n * @param updates - Fields to update\n * @returns Updated customer profile\n *\n * @example\n * ```typescript\n * const updated = await client.updateProfile(profileId, {\n * location: 'New York, USA',\n * location_compliance: 'compliant',\n * last_recorded_activity: new Date().toISOString()\n * });\n * ```\n */\n async updateProfile(\n profileId: string,\n updates: UpdateProfileRequest,\n requestOptions?: RequestOptions\n ): Promise<CustomerProfile> {\n return this.request<CustomerProfile>(`/api/v1/profiles/${profileId}`, {\n method: 'PUT',\n body: JSON.stringify(updates),\n }, undefined, requestOptions);\n }\n\n /**\n * Get or create profile (idempotent operation)\n *\n * Attempts to get existing profile by customer_id, creates if not found.\n *\n * @param customerId - Customer ID\n * @param createRequest - Profile data to use if creating new profile\n * @returns Existing or newly created profile\n *\n * @example\n * ```typescript\n * const profile = await client.getOrCreateProfile('CUST-123', {\n * customer_id: 'CUST-123',\n * entity_type: 'individual',\n * full_name: 'John Doe',\n * email_address: 'john@example.com'\n * });\n * ```\n */\n async getOrCreateProfile(\n customerId: string,\n createRequest: CreateProfileRequest,\n requestOptions?: RequestOptions\n ): Promise<CustomerProfile> {\n try {\n return await this.getProfile(customerId, requestOptions);\n } catch (error) {\n // Only treat NOT_FOUND as \"profile doesn't exist\" — re-throw other errors\n if (error instanceof VesantError && error.code === 'NOT_FOUND') {\n return await this.createProfile(createRequest, requestOptions);\n }\n throw error;\n }\n }\n\n}\n","import type { BlockReason } from '../core/types';\n\nexport const sdkReasons = {\n // Jurisdiction\n jurisdictionBlocked: (country: string, countryISO: string): BlockReason => ({\n code: 'JURISDICTION_BLOCKED',\n message: 'Access from a blocked jurisdiction',\n metadata: { country, country_iso: countryISO },\n }),\n jurisdictionNonCompliant: (): BlockReason => ({\n code: 'JURISDICTION_NON_COMPLIANT',\n message: 'Location does not meet compliance requirements',\n }),\n jurisdictionRegistrationDenied: (): BlockReason => ({\n code: 'JURISDICTION_REGISTRATION_DENIED',\n message: 'Registration is not permitted in this jurisdiction',\n }),\n jurisdictionRestricted: (): BlockReason => ({\n code: 'JURISDICTION_RESTRICTED',\n message: 'Access from a restricted jurisdiction',\n }),\n\n // Risk\n riskCriticalLevel: (): BlockReason => ({\n code: 'RISK_CRITICAL_LEVEL',\n message: 'Risk assessment reached critical threshold',\n }),\n accountSuspended: (): BlockReason => ({\n code: 'RISK_ACCOUNT_SUSPENDED',\n message: 'Customer account is suspended',\n }),\n sanctionsMatch: (): BlockReason => ({\n code: 'RISK_SANCTIONS_MATCH',\n message: 'Customer profile matched against sanctions list',\n }),\n riskHighLocation: (): BlockReason => ({\n code: 'RISK_HIGH_LOCATION',\n message: 'High-risk geographic location',\n }),\n riskHighCustomer: (): BlockReason => ({\n code: 'RISK_HIGH_CUSTOMER',\n message: 'Customer flagged as high risk',\n }),\n\n // Device\n ciphertextInvalid: (): BlockReason => ({\n code: 'DEVICE_CIPHERTEXT_INVALID',\n message: 'Device verification payload failed validation',\n }),\n gpsIPMismatch: (): BlockReason => ({\n code: 'DEVICE_GPS_IP_MISMATCH',\n message: 'GPS location does not match IP-derived location',\n }),\n gpsRequired: (): BlockReason => ({\n code: 'DEVICE_GPS_REQUIRED',\n message: 'GPS verification is required but was not provided',\n }),\n\n // Transaction\n transactionHighAmount: (amount: number, currency: string, threshold: number): BlockReason => ({\n code: 'TRANSACTION_HIGH_AMOUNT',\n message: 'Transaction amount exceeds high-value threshold',\n metadata: { amount, currency, threshold },\n }),\n transactionElevatedAmount: (amount: number, currency: string, threshold: number): BlockReason => ({\n code: 'TRANSACTION_ELEVATED_AMOUNT',\n message: 'Transaction amount exceeds elevated-value threshold',\n metadata: { amount, currency, threshold },\n }),\n transactionJurisdictionLimit: (): BlockReason => ({\n code: 'TRANSACTION_JURISDICTION_LIMIT',\n message: 'Transaction amount exceeds jurisdiction limit',\n }),\n anonymizationDetected: (): BlockReason => ({\n code: 'NETWORK_ANONYMIZER_DETECTED',\n message: 'Anonymization tool detected',\n }),\n};\n","/**\n * Compliance orchestration types\n *\n * Types for unified compliance verification flows that combine\n * geolocation verification with customer risk profiling.\n */\n\nimport type { BlockReason } from '../core/types';\nimport type { LocationVerification, DeviceFingerprintRequest } from '../geolocation/types';\nimport type { ValidateCipherTextResponse } from '../geolocation/types';\nimport type { CustomerProfile, EntityType } from '../risk-profile/types';\n\n// ============================================================================\n// Registration Verification Types\n// ============================================================================\n\nexport interface RegistrationVerificationRequest {\n // Identity\n customerId: string;\n fullName: string;\n emailAddress: string;\n phoneNumber?: string;\n dateOfBirth?: string;\n address?: string;\n entityType?: EntityType;\n\n // Geolocation\n ipAddress: string;\n deviceFingerprint?: DeviceFingerprintRequest;\n cipherText?: string;\n\n // Additional data\n metadata?: Record<string, unknown>;\n}\n\nexport interface RegistrationVerificationResponse {\n allowed: boolean;\n geolocation: LocationVerification;\n profile: CustomerProfile | null;\n requiresKYC: boolean;\n requiresEDD: boolean;\n blockReasons: string[];\n blockReasonsStructured?: BlockReason[];\n processingTime: number;\n cipherTextValidation?: ValidateCipherTextResponse;\n}\n\n// ============================================================================\n// Login Verification Types\n// ============================================================================\n\nexport interface LoginVerificationRequest {\n customerId: string;\n ipAddress: string;\n deviceFingerprint?: DeviceFingerprintRequest;\n cipherText?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface LoginVerificationResponse {\n allowed: boolean;\n geolocation: LocationVerification;\n profile: CustomerProfile | null;\n requiresStepUp: boolean;\n blockReasons: string[];\n blockReasonsStructured?: BlockReason[];\n processingTime: number;\n cipherTextValidation?: ValidateCipherTextResponse;\n}\n\n// ============================================================================\n// Transaction Verification Types\n// ============================================================================\n\nexport interface TransactionVerificationRequest {\n customerId: string;\n ipAddress: string;\n amount: number;\n currency: string;\n transactionType?: 'deposit' | 'withdrawal' | 'bet' | 'transfer' | 'payout';\n deviceFingerprint?: DeviceFingerprintRequest;\n cipherText?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface TransactionVerificationResponse {\n allowed: boolean;\n geolocation: LocationVerification;\n profile: CustomerProfile | null;\n transactionRisk: TransactionRiskResult;\n requiresApproval: boolean;\n blockReasons: string[];\n blockReasonsStructured?: BlockReason[];\n processingTime: number;\n cipherTextValidation?: ValidateCipherTextResponse;\n}\n\nexport interface TransactionRiskResult {\n score: number;\n level: 'low' | 'medium' | 'high' | 'critical';\n factors: string[];\n factorsStructured?: BlockReason[];\n allowed: boolean;\n requiresManualReview: boolean;\n}\n\n// ============================================================================\n// Generic Event Verification Types\n// ============================================================================\n\nexport interface EventVerificationRequest {\n customerId: string;\n ipAddress: string;\n eventType: string;\n deviceFingerprint?: DeviceFingerprintRequest;\n cipherText?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface EventVerificationResponse {\n allowed: boolean;\n geolocation: LocationVerification;\n blockReasons: string[];\n blockReasonsStructured?: BlockReason[];\n processingTime: number;\n cipherTextValidation?: ValidateCipherTextResponse;\n}\n\n// ============================================================================\n// Currency Exchange Rates (for transaction risk calculation)\n// ============================================================================\n\nexport interface CurrencyRates {\n [currency: string]: number; // Rate to USD\n}\n\nexport const DEFAULT_CURRENCY_RATES: CurrencyRates = {\n USD: 1.0,\n EUR: 1.1,\n GBP: 1.27,\n CAD: 0.74,\n AUD: 0.66,\n JPY: 0.0067,\n CHF: 1.13,\n CNY: 0.14,\n INR: 0.012,\n BRL: 0.20,\n MXN: 0.058,\n ZAR: 0.055,\n};\n\n// ============================================================================\n// Location Request Types (re-exported from geolocation for convenience)\n// ============================================================================\n\nexport type {\n LocationRequest,\n LocationRequestStatus,\n LocationRequestChannel,\n CreateLocationRequestRequest,\n LocationRequestResult,\n LocationRequestFilters,\n LocationRequestListResponse,\n ResendLocationRequestRequest,\n LocationShareInfo,\n LocationCaptureRequest,\n LocationCaptureResponse,\n} from '../geolocation/types';\n\n// ============================================================================\n// Compliance-specific Location Request Types\n// ============================================================================\n\nexport interface ComplianceLocationRequestInput {\n /** Customer user ID to request location from */\n customerId: string;\n /** Notification channel to use */\n channel: 'sms' | 'email' | 'push';\n /** Reason for requesting location (for compliance/audit) */\n reason: string;\n /** Customer email (required for email channel) */\n email?: string;\n /** Customer phone (required for SMS channel) */\n phone?: string;\n /** Custom expiry time in hours (default: 24) */\n expiryHours?: number;\n}\n\nexport interface ComplianceLocationRequestResult {\n /** The created location request */\n request: import('../geolocation/types').LocationRequest;\n /** Shareable link for the customer */\n shareLink: string;\n /** Token expiration time */\n tokenExpiry: string;\n /** Customer profile (if available) */\n profile?: import('../risk-profile/types').CustomerProfile;\n}\n","/**\n * ComplianceClient - Unified Compliance Orchestration\n *\n * Main integration point for casino platforms. Orchestrates geolocation\n * verification with customer risk profiling for complete compliance coverage.\n *\n * SDK is the primary data injection point for compliance verification.\n */\n\nimport { GeolocationClient } from '../geolocation/client';\nimport { RiskProfileClient } from '../risk-profile/client';\nimport type { VesantConfig, Logger, RequestOptions, RequiredVesantConfig, RequestInterceptor } from '../core/config';\nimport type { BlockReason } from '../core/types';\nimport { ComplianceError, ValidationError, VesantError } from '../core/errors';\nimport { sdkReasons } from './block-reasons';\nimport { createConsoleLogger } from '../core/logger';\nimport type { JurisdictionConfig, LocationVerification, ValidateCipherTextResponse } from '../geolocation/types';\nimport type { CustomerProfile } from '../risk-profile/types';\nimport type {\n RegistrationVerificationRequest,\n RegistrationVerificationResponse,\n LoginVerificationRequest,\n LoginVerificationResponse,\n TransactionVerificationRequest,\n TransactionVerificationResponse,\n TransactionRiskResult,\n EventVerificationRequest,\n EventVerificationResponse,\n CurrencyRates,\n ComplianceLocationRequestInput,\n ComplianceLocationRequestResult,\n} from './types';\nimport { DEFAULT_CURRENCY_RATES } from './types';\nimport type {\n LocationRequest,\n LocationRequestFilters,\n LocationRequestListResponse,\n PaginationParams,\n} from '../geolocation/types';\n\nexport class ComplianceClient {\n private geoClient: GeolocationClient;\n private riskClient: RiskProfileClient;\n private config: RequiredVesantConfig;\n private logger: Logger;\n private currencyRates: CurrencyRates;\n private _currencyRatesCustomized: boolean = false;\n private _currencyRatesWarned: boolean = false;\n\n constructor(config: VesantConfig) {\n this.logger = config.logger || createConsoleLogger();\n const interceptors: RequestInterceptor[] = config.interceptors || [];\n this.config = {\n baseURL: config.baseURL,\n tenantId: config.tenantId,\n apiKey: config.apiKey || '',\n headers: config.headers || {},\n timeout: config.timeout || 10000,\n retries: config.retries || 3,\n debug: config.debug || false,\n autoCreateProfiles: config.autoCreateProfiles !== false, // default true\n syncMode: config.syncMode || 'sync',\n environment: config.environment,\n interceptors,\n logger: this.logger,\n };\n\n this.geoClient = new GeolocationClient({\n baseURL: this.config.baseURL,\n tenantId: this.config.tenantId,\n apiKey: this.config.apiKey,\n headers: this.config.headers,\n timeout: this.config.timeout,\n debug: this.config.debug,\n logger: this.logger,\n environment: this.config.environment,\n });\n\n this.riskClient = new RiskProfileClient({\n baseURL: this.config.baseURL,\n tenantId: this.config.tenantId,\n apiKey: this.config.apiKey,\n headers: this.config.headers,\n timeout: this.config.timeout,\n debug: this.config.debug,\n interceptors,\n logger: this.logger,\n environment: this.config.environment,\n });\n\n this.currencyRates = DEFAULT_CURRENCY_RATES;\n }\n\n // ============================================================================\n // Sub-Client Accessors\n // ============================================================================\n\n /** Get the underlying GeolocationClient for direct geolocation API access */\n getGeolocationClient(): GeolocationClient {\n return this.geoClient;\n }\n\n /** Get the underlying RiskProfileClient for direct risk profile API access */\n getRiskProfileClient(): RiskProfileClient {\n return this.riskClient;\n }\n\n // ============================================================================\n // Main Verification Methods\n // ============================================================================\n\n /**\n * Verify customer registration with automatic profile creation\n *\n * This is the primary integration point for new customer sign-ups.\n * Combines geolocation verification with customer risk profile creation.\n *\n * Important: Profile is only created if geolocation verification passes.\n * This prevents orphaned geolocation records when registration is blocked.\n *\n * @param request - Registration verification request\n * @returns Verification response with profile and compliance status\n *\n * @example\n * ```typescript\n * const result = await sdk.verifyAtRegistration({\n * customerId: 'CUST-12345',\n * fullName: 'John Doe',\n * emailAddress: 'john@example.com',\n * ipAddress: req.ip,\n * deviceFingerprint: getDeviceFingerprint()\n * });\n *\n * if (result.allowed) {\n * // Create account\n * console.log('Profile created:', result.profile);\n * if (result.requiresKYC) {\n * // Redirect to KYC flow\n * }\n * } else {\n * // Block registration\n * console.log('Blocked:', result.blockReasons);\n * }\n * ```\n */\n async verifyAtRegistration(\n request: RegistrationVerificationRequest,\n requestOptions?: RequestOptions\n ): Promise<RegistrationVerificationResponse> {\n const startTime = Date.now();\n\n // Validate required fields before making any API calls\n this.validateRegistrationRequest(request);\n\n let geoVerification: LocationVerification | null = null;\n let cipherTextResult: ValidateCipherTextResponse | undefined;\n\n try {\n if (this.config.debug) {\n this.logger.debug('Starting registration verification', { customerId: request.customerId });\n }\n\n // When cipherText is present, validate-ciphertext performs full geo verification\n // server-side. Calling verifyIP separately would create duplicate records/alerts.\n if (request.cipherText) {\n cipherTextResult = await this.executeCipherTextValidation(\n request.cipherText,\n request.customerId,\n 'registration',\n request.ipAddress,\n {\n full_name: request.fullName,\n email: request.emailAddress,\n phone: request.phoneNumber,\n date_of_birth: request.dateOfBirth,\n },\n requestOptions\n );\n geoVerification = (cipherTextResult && this.buildLocationFromCipherText(cipherTextResult, request.ipAddress))\n ?? await this.geoClient.verifyIP({\n ip_address: request.ipAddress,\n user_id: request.customerId,\n event_type: 'registration',\n device_fingerprint: request.deviceFingerprint,\n }, requestOptions);\n } else {\n geoVerification = await this.geoClient.verifyIP({\n ip_address: request.ipAddress,\n user_id: request.customerId,\n event_type: 'registration',\n device_fingerprint: request.deviceFingerprint,\n }, requestOptions);\n }\n\n // Step 2: Check if registration should be blocked BEFORE creating profile\n // This prevents orphaned geo records and ensures atomic behavior\n const structuredBlockReasons = this.evaluateRegistrationBlock(geoVerification, cipherTextResult);\n\n if (structuredBlockReasons.length > 0) {\n if (this.config.debug) {\n this.logger.debug('Registration blocked at geo stage', { blockReasons: structuredBlockReasons });\n }\n\n // Return early without creating profile - prevents orphaned records\n return {\n allowed: false,\n geolocation: geoVerification,\n profile: null,\n requiresKYC: false,\n requiresEDD: false,\n ...this.buildReasonTail(structuredBlockReasons, startTime, cipherTextResult),\n };\n }\n\n // Step 3: Create customer risk profile (only if geo passed)\n const profile = await this.riskClient.createProfile({\n customer_id: request.customerId,\n entity_type: request.entityType || 'individual',\n customer_status: 'active',\n full_name: request.fullName,\n email_address: request.emailAddress,\n primary_phone_number: request.phoneNumber,\n date_of_birth: request.dateOfBirth,\n residential_address: request.address,\n country_of_residence: geoVerification.location.country_iso,\n\n // Geolocation data\n location: `${geoVerification.location.city}, ${geoVerification.location.country}`,\n location_compliance: geoVerification.is_compliant ? 'compliant' : 'non-compliant',\n\n // Initial KYC status\n kyc_status: 'pending',\n }, requestOptions);\n\n // Step 4: Determine final status and requirements\n const requiresKYC = geoVerification.jurisdiction?.require_kyc || false;\n const requiresEDD = geoVerification.jurisdiction?.require_enhanced_verification || false;\n\n if (this.config.debug) {\n this.logger.debug('Registration verification complete', {\n allowed: true,\n requiresKYC,\n requiresEDD,\n });\n }\n\n return {\n allowed: true,\n geolocation: geoVerification,\n profile: profile,\n requiresKYC: requiresKYC,\n requiresEDD: requiresEDD,\n ...this.buildReasonTail([], startTime, cipherTextResult),\n };\n } catch (error) {\n if (this.config.debug) {\n this.logger.error('Registration verification failed', {\n code: error instanceof VesantError ? error.code : undefined,\n message: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n\n // Preserve DUPLICATE_PROFILE errors so callers can distinguish\n // duplicate registrations from other failures\n if (error instanceof VesantError && error.code === 'DUPLICATE_PROFILE') {\n throw error;\n }\n\n throw new ComplianceError(\n 'Registration verification failed',\n error instanceof Error ? error.message : undefined,\n geoVerification ? 'PROFILE_CREATION_FAILED' : 'GEO_VERIFICATION_FAILED'\n );\n }\n }\n\n /**\n * Evaluate if registration should be blocked based on geolocation verification\n *\n * Checks:\n * 1. General compliance status (is_compliant)\n * 2. Explicit block flag (is_blocked)\n * 3. Jurisdiction-specific registration allowance (allow_registration)\n * 4. Risk level thresholds\n *\n * @param geoVerification - Geolocation verification result\n * @returns Array of block reasons (empty if allowed)\n */\n private evaluateRegistrationBlock(\n geoVerification: LocationVerification,\n cipherTextResult?: ValidateCipherTextResponse\n ): BlockReason[] {\n const blockReasons: BlockReason[] = [];\n\n // Check if explicitly blocked — read from the structured parallel field\n if (geoVerification.is_blocked) {\n blockReasons.push(...(geoVerification.risk_reasons_structured ?? []));\n }\n\n // Check general compliance\n if (!geoVerification.is_compliant) {\n if (!blockReasons.some(r => r.code === 'JURISDICTION_NON_COMPLIANT')) {\n blockReasons.push(sdkReasons.jurisdictionNonCompliant());\n }\n }\n\n // CRITICAL: Check if registration is specifically allowed in this jurisdiction\n // Some jurisdictions may allow login but not new registrations\n const jurisdiction = geoVerification.jurisdiction;\n if (jurisdiction) {\n if (jurisdiction.allow_registration === false) {\n blockReasons.push(sdkReasons.jurisdictionRegistrationDenied());\n }\n\n // Check jurisdiction status for registration-specific blocks\n if (jurisdiction.status === 'blocked' || jurisdiction.status === 'sanctioned') {\n if (!blockReasons.some(r => r.code === 'JURISDICTION_BLOCKED')) {\n blockReasons.push(sdkReasons.jurisdictionBlocked(jurisdiction.country_name ?? '', jurisdiction.country_iso ?? ''));\n }\n }\n\n // Restricted jurisdictions need explicit registration permission\n if (jurisdiction.status === 'restricted' && jurisdiction.allow_registration === false) {\n if (!blockReasons.some(r => r.code === 'JURISDICTION_RESTRICTED')) {\n blockReasons.push(sdkReasons.jurisdictionRestricted());\n }\n }\n }\n\n // Check geofence rule evaluation — reasons is now string[], wrap each into a BlockReason\n if (geoVerification.geofence_evaluation?.blocked) {\n blockReasons.push(\n ...(geoVerification.geofence_evaluation.reasons ?? []).map(m => ({\n code: 'JURISDICTION_GEOFENCE_VIOLATION',\n message: m,\n }))\n );\n }\n\n // Critical risk level should block registration\n if (geoVerification.risk_level === 'critical') {\n if (!blockReasons.some(r => r.code === 'RISK_CRITICAL_LEVEL')) {\n blockReasons.push(sdkReasons.riskCriticalLevel());\n }\n }\n\n // CipherText-based blocks (only when cipherText was provided)\n if (cipherTextResult) {\n if (!cipherTextResult.valid) {\n blockReasons.push(sdkReasons.ciphertextInvalid());\n }\n if (cipherTextResult.risk?.is_blocked) {\n blockReasons.push(...(cipherTextResult.risk.block_reasons_structured ?? []));\n }\n // Note: risk.location_mismatch is intentionally NOT a hard block. The server\n // treats a GPS-vs-IP distance over its threshold as a risk factor only —\n // GeoIP city-level inaccuracies (e.g. ISP gateway geolocation) would otherwise\n // block legitimate registrations. Blocks follow the server's is_blocked.\n }\n\n // GPS required but no cipherText provided — block\n if (geoVerification.gps_required && !cipherTextResult) {\n blockReasons.push(sdkReasons.gpsRequired());\n }\n\n const seen = new Set<string>();\n return blockReasons.filter(r => {\n if (seen.has(r.code)) return false;\n seen.add(r.code);\n return true;\n });\n }\n\n /**\n * Validate registration request has all required fields\n *\n * @param request - Registration request to validate\n * @throws ValidationError if required fields are missing or invalid\n */\n private validateRegistrationRequest(request: RegistrationVerificationRequest): void {\n const errors: string[] = [];\n\n if (!request.customerId?.trim()) {\n errors.push('customerId is required');\n }\n\n if (!request.ipAddress?.trim()) {\n errors.push('ipAddress is required');\n } else if (!this.isValidIP(request.ipAddress)) {\n errors.push('ipAddress format is invalid');\n }\n\n if (!request.emailAddress?.trim()) {\n errors.push('emailAddress is required');\n } else if (!this.isValidEmail(request.emailAddress)) {\n errors.push('emailAddress format is invalid');\n }\n\n if (!request.fullName?.trim()) {\n errors.push('fullName is required');\n }\n\n if (errors.length > 0) {\n throw new ValidationError(`Invalid registration request: ${errors.join(', ')}`, errors);\n }\n }\n\n /**\n * Validate IP address format (IPv4 or IPv6)\n */\n private isValidIP(ip: string): boolean {\n // IPv4 pattern\n const ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;\n // Simplified IPv6 pattern (covers most common cases)\n const ipv6Regex = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|^::(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}$|^(?:[0-9a-fA-F]{1,4}:){1,7}:$|^(?:[0-9a-fA-F]{1,4}:){0,6}::(?:[0-9a-fA-F]{1,4}:){0,5}[0-9a-fA-F]{1,4}$/;\n\n return ipv4Regex.test(ip) || ipv6Regex.test(ip);\n }\n\n /**\n * Validate email address format\n */\n private isValidEmail(email: string): boolean {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n return emailRegex.test(email);\n }\n\n private validateLoginRequest(request: LoginVerificationRequest): void {\n const errors: string[] = [];\n\n if (!request.customerId?.trim()) {\n errors.push('customerId is required');\n }\n\n if (!request.ipAddress?.trim()) {\n errors.push('ipAddress is required');\n } else if (!this.isValidIP(request.ipAddress)) {\n errors.push('ipAddress format is invalid');\n }\n\n if (errors.length > 0) {\n throw new ValidationError(`Invalid login request: ${errors.join(', ')}`, errors);\n }\n }\n\n private validateTransactionRequest(request: TransactionVerificationRequest): void {\n const errors: string[] = [];\n\n if (!request.customerId?.trim()) {\n errors.push('customerId is required');\n }\n\n if (!request.ipAddress?.trim()) {\n errors.push('ipAddress is required');\n } else if (!this.isValidIP(request.ipAddress)) {\n errors.push('ipAddress format is invalid');\n }\n\n if (request.amount <= 0) {\n errors.push('amount must be greater than 0');\n }\n\n if (!request.currency?.trim()) {\n errors.push('currency is required');\n }\n\n if (errors.length > 0) {\n throw new ValidationError(`Invalid transaction request: ${errors.join(', ')}`, errors);\n }\n }\n\n private validateEventRequest(request: EventVerificationRequest): void {\n const errors: string[] = [];\n\n if (!request.customerId?.trim()) {\n errors.push('customerId is required');\n }\n\n if (!request.ipAddress?.trim()) {\n errors.push('ipAddress is required');\n } else if (!this.isValidIP(request.ipAddress)) {\n errors.push('ipAddress format is invalid');\n }\n\n if (!request.eventType?.trim()) {\n errors.push('eventType is required');\n }\n\n if (errors.length > 0) {\n throw new ValidationError(`Invalid event request: ${errors.join(', ')}`, errors);\n }\n }\n\n /**\n * Verify customer login with profile activity update\n *\n * Verifies geolocation and updates customer profile with latest activity.\n *\n * @param request - Login verification request\n * @returns Verification response with compliance status\n *\n * @example\n * ```typescript\n * const result = await sdk.verifyAtLogin({\n * customerId: 'CUST-12345',\n * ipAddress: req.ip,\n * deviceFingerprint: getDeviceFingerprint()\n * });\n *\n * if (result.allowed) {\n * // Allow login\n * if (result.requiresStepUp) {\n * // Trigger MFA or additional verification\n * }\n * } else {\n * // Block login\n * console.log('Blocked:', result.blockReasons);\n * }\n * ```\n */\n async verifyAtLogin(\n request: LoginVerificationRequest,\n requestOptions?: RequestOptions\n ): Promise<LoginVerificationResponse> {\n const startTime = Date.now();\n\n this.validateLoginRequest(request);\n\n try {\n if (this.config.debug) {\n this.logger.debug('Starting login verification', { customerId: request.customerId });\n }\n\n // Step 1: Verify geolocation, cipherText, and fetch profile in parallel.\n // When cipherText is present, validate-ciphertext performs full geo verification\n // server-side — calling verifyIP separately would create duplicate records/alerts.\n let cipherTextResult: ValidateCipherTextResponse | undefined;\n let geoVerification: LocationVerification;\n let profileResult: CustomerProfile | null;\n\n if (request.cipherText) {\n [cipherTextResult, profileResult] = await Promise.all([\n this.executeCipherTextValidation(\n request.cipherText, request.customerId, 'login', request.ipAddress,\n undefined, requestOptions\n ),\n this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null),\n ]);\n geoVerification = (cipherTextResult && this.buildLocationFromCipherText(cipherTextResult, request.ipAddress))\n ?? await this.geoClient.verifyIP({\n ip_address: request.ipAddress,\n user_id: request.customerId,\n event_type: 'login',\n device_fingerprint: request.deviceFingerprint,\n }, requestOptions);\n } else {\n [, geoVerification, profileResult] = await Promise.all([\n Promise.resolve(undefined),\n this.geoClient.verifyIP({\n ip_address: request.ipAddress,\n user_id: request.customerId,\n event_type: 'login',\n device_fingerprint: request.deviceFingerprint,\n }, requestOptions),\n this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null),\n ]);\n }\n\n // Step 2: Check if login should be blocked BEFORE creating/updating profile\n const loginBlockReasons = this.getBlockReasons(geoVerification, profileResult, cipherTextResult);\n const isBlocked =\n !geoVerification.is_compliant ||\n geoVerification.is_blocked ||\n !!(cipherTextResult?.risk?.is_blocked) ||\n cipherTextResult?.valid === false ||\n (geoVerification.gps_required && !cipherTextResult);\n\n if (isBlocked && !profileResult) {\n // Blocked and no existing profile — return without creating one\n return {\n allowed: false,\n geolocation: geoVerification,\n profile: null,\n requiresStepUp: false,\n ...this.buildReasonTail(loginBlockReasons, startTime, cipherTextResult),\n };\n }\n\n // Step 3: Get or create profile (only reached if not blocked, or profile already exists)\n let profile: CustomerProfile;\n if (profileResult) {\n profile = profileResult;\n\n // Update last activity and location\n if (!isBlocked && this.shouldUpdateProfile(profile, geoVerification.location.city)) {\n profile = await this.riskClient.updateProfile(profile.id, {\n last_recorded_activity: new Date().toISOString(),\n location: `${geoVerification.location.city}, ${geoVerification.location.country}`,\n location_compliance: geoVerification.is_compliant ? 'compliant' : 'non-compliant',\n }, requestOptions);\n }\n } else {\n // Profile doesn't exist - this shouldn't happen for login\n if (this.config.autoCreateProfiles && this.config.debug) {\n this.logger.warn('Profile not found for login, creating...');\n }\n profile = await this.createProfileFromGeo(request.customerId, geoVerification);\n }\n\n const requiresStepUp =\n geoVerification.risk_level === 'high' ||\n geoVerification.risk_level === 'critical' ||\n (cipherTextResult?.risk?.location_mismatch === true);\n\n const loginFinalStructured = isBlocked || profile.customer_status === 'suspended'\n ? this.getBlockReasons(geoVerification, profile, cipherTextResult)\n : [];\n return {\n allowed: !isBlocked && profile.customer_status !== 'suspended',\n geolocation: geoVerification,\n profile: profile,\n requiresStepUp: requiresStepUp,\n ...this.buildReasonTail(loginFinalStructured, startTime, cipherTextResult),\n };\n } catch (error) {\n throw new ComplianceError('Login verification failed', error instanceof Error ? error.message : undefined);\n }\n }\n\n /**\n * Verify transaction with amount-based risk assessment\n *\n * Combines geolocation verification with transaction amount analysis\n * and customer risk profile for comprehensive transaction screening.\n *\n * @param request - Transaction verification request\n * @returns Verification response with transaction risk assessment\n *\n * @example\n * ```typescript\n * const result = await sdk.verifyAtTransaction({\n * customerId: 'CUST-12345',\n * ipAddress: req.ip,\n * amount: 5000,\n * currency: 'USD',\n * transactionType: 'withdrawal',\n * deviceFingerprint: getDeviceFingerprint()\n * });\n *\n * if (result.allowed) {\n * // Process transaction\n * } else if (result.requiresApproval) {\n * // Queue for manual review\n * } else {\n * // Block transaction\n * console.log('Blocked:', result.blockReasons);\n * }\n * ```\n */\n async verifyAtTransaction(\n request: TransactionVerificationRequest,\n requestOptions?: RequestOptions\n ): Promise<TransactionVerificationResponse> {\n const startTime = Date.now();\n\n this.validateTransactionRequest(request);\n\n try {\n if (this.config.debug) {\n this.logger.debug('Starting transaction verification', {\n customerId: request.customerId,\n amount: request.amount,\n currency: request.currency,\n });\n }\n\n // Step 1: Verify geolocation, cipherText, and fetch profile in parallel.\n // When cipherText is present, validate-ciphertext performs full geo verification\n // server-side — calling verifyIP separately would create duplicate records/alerts.\n let cipherTextResult: ValidateCipherTextResponse | undefined;\n let geoVerification: LocationVerification;\n let profileResult: CustomerProfile | null;\n\n if (request.cipherText) {\n [cipherTextResult, profileResult] = await Promise.all([\n this.executeCipherTextValidation(\n request.cipherText, request.customerId, 'transaction', request.ipAddress,\n undefined, requestOptions\n ),\n this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null),\n ]);\n geoVerification = (cipherTextResult && this.buildLocationFromCipherText(cipherTextResult, request.ipAddress))\n ?? await this.geoClient.verifyIP({\n ip_address: request.ipAddress,\n user_id: request.customerId,\n event_type: 'transaction',\n device_fingerprint: request.deviceFingerprint,\n }, requestOptions);\n } else {\n [, geoVerification, profileResult] = await Promise.all([\n Promise.resolve(undefined),\n this.geoClient.verifyIP({\n ip_address: request.ipAddress,\n user_id: request.customerId,\n event_type: 'transaction',\n device_fingerprint: request.deviceFingerprint,\n }, requestOptions),\n this.riskClient.getProfile(request.customerId, requestOptions).catch(() => null),\n ]);\n }\n\n // Step 2: Check if blocked before proceeding with risk calculation\n const geoBlocked =\n !geoVerification.is_compliant ||\n geoVerification.is_blocked ||\n !!(cipherTextResult?.risk?.is_blocked) ||\n cipherTextResult?.valid === false ||\n (geoVerification.gps_required && !cipherTextResult);\n\n if (geoBlocked && !profileResult) {\n // Blocked and no profile — return early without risk calculation\n const earlyStructured = this.getTransactionBlockReasons(\n geoVerification,\n { score: 0, level: 'low', factors: [], allowed: false, requiresManualReview: false },\n true,\n cipherTextResult\n );\n return {\n allowed: false,\n geolocation: geoVerification,\n profile: null,\n transactionRisk: { score: 0, level: 'low' as const, factors: [], allowed: false, requiresManualReview: false },\n requiresApproval: false,\n ...this.buildReasonTail(earlyStructured, startTime, cipherTextResult),\n };\n }\n\n if (!profileResult) {\n throw new ComplianceError('Customer profile not found', request.customerId);\n }\n const profile = profileResult;\n\n // Step 3: Calculate transaction risk\n const transactionRisk = this.calculateTransactionRisk(\n request.amount,\n request.currency,\n geoVerification,\n profile,\n cipherTextResult\n );\n\n // Step 4: Check jurisdiction limits\n const jurisdictionAllowed = this.checkJurisdictionLimits(\n request.amount,\n request.currency,\n geoVerification.jurisdiction\n );\n\n // Step 5: Determine if transaction is allowed\n const isAllowed =\n !geoBlocked &&\n jurisdictionAllowed &&\n transactionRisk.allowed &&\n profile.customer_status !== 'suspended';\n\n const txStructured = this.getTransactionBlockReasons(\n geoVerification, transactionRisk, jurisdictionAllowed, cipherTextResult\n );\n return {\n allowed: isAllowed,\n geolocation: geoVerification,\n profile: profile,\n transactionRisk: transactionRisk,\n requiresApproval: transactionRisk.requiresManualReview,\n ...this.buildReasonTail(txStructured, startTime, cipherTextResult),\n };\n } catch (error) {\n throw new ComplianceError('Transaction verification failed', error instanceof Error ? error.message : undefined);\n }\n }\n\n /**\n * Generic event verification (for other touchpoints)\n *\n * @param request - Event verification request\n * @returns Verification response\n */\n async verifyEvent(request: EventVerificationRequest, requestOptions?: RequestOptions): Promise<EventVerificationResponse> {\n const startTime = Date.now();\n\n this.validateEventRequest(request);\n\n // When cipherText is present, validate-ciphertext performs full geo verification\n // server-side — calling verifyIP separately would create duplicate records/alerts.\n let cipherTextResult: ValidateCipherTextResponse | undefined;\n let geoVerification: LocationVerification;\n\n if (request.cipherText) {\n cipherTextResult = await this.executeCipherTextValidation(\n request.cipherText, request.customerId, request.eventType, request.ipAddress,\n undefined, requestOptions\n );\n geoVerification = (cipherTextResult && this.buildLocationFromCipherText(cipherTextResult, request.ipAddress))\n ?? await this.geoClient.verifyIP({\n ip_address: request.ipAddress,\n user_id: request.customerId,\n event_type: request.eventType,\n device_fingerprint: request.deviceFingerprint,\n }, requestOptions);\n } else {\n geoVerification = await this.geoClient.verifyIP({\n ip_address: request.ipAddress,\n user_id: request.customerId,\n event_type: request.eventType,\n device_fingerprint: request.deviceFingerprint,\n }, requestOptions);\n }\n\n // Optionally update profile activity\n if (this.config.autoCreateProfiles) {\n try {\n const profile = await this.riskClient.getProfile(request.customerId, requestOptions);\n await this.riskClient.updateProfile(profile.id, {\n last_recorded_activity: new Date().toISOString(),\n }, requestOptions);\n } catch (error) {\n // Profile doesn't exist, ignore or create based on config\n if (this.config.debug) {\n this.logger.warn('Profile not found for event');\n }\n }\n }\n\n const cipherTextBlocked = cipherTextResult\n ? (!cipherTextResult.valid || cipherTextResult.risk?.is_blocked === true)\n : false;\n\n // Build structured block reasons from the structured parallel fields\n const structuredEventReasons: BlockReason[] = [...(geoVerification.risk_reasons_structured ?? [])];\n if (cipherTextResult) {\n if (!cipherTextResult.valid) {\n structuredEventReasons.push(sdkReasons.ciphertextInvalid());\n }\n if (cipherTextResult.risk?.is_blocked) {\n structuredEventReasons.push(...(cipherTextResult.risk.block_reasons_structured ?? []));\n }\n }\n\n // GPS required but no cipherText provided — block\n const gpsBlocked = geoVerification.gps_required && !cipherTextResult;\n if (gpsBlocked) {\n structuredEventReasons.push(sdkReasons.gpsRequired());\n }\n\n const seen = new Set<string>();\n const dedupedStructured = structuredEventReasons.filter(r => {\n if (seen.has(r.code)) return false;\n seen.add(r.code);\n return true;\n });\n\n return {\n allowed: geoVerification.is_compliant && !geoVerification.is_blocked && !cipherTextBlocked && !gpsBlocked,\n geolocation: geoVerification,\n ...this.buildReasonTail(dedupedStructured, startTime, cipherTextResult),\n };\n }\n\n // ============================================================================\n // Helper Methods\n // ============================================================================\n\n private buildReasonTail(\n structured: BlockReason[],\n startTime: number,\n cipherTextResult: ValidateCipherTextResponse | undefined,\n ) {\n return {\n blockReasons: structured.map(r => r.message),\n blockReasonsStructured: structured,\n processingTime: Date.now() - startTime,\n cipherTextValidation: cipherTextResult,\n };\n }\n\n private shouldUpdateProfile(profile: CustomerProfile, newCity: string): boolean {\n // Update if location changed significantly\n return !profile.location || !profile.location.includes(newCity);\n }\n\n private async createProfileFromGeo(\n customerId: string,\n geoVerification: LocationVerification,\n customerData?: {\n fullName?: string;\n email?: string;\n phone?: string;\n dateOfBirth?: string;\n }\n ): Promise<CustomerProfile> {\n // Warn if creating profile without proper customer data\n if (!customerData?.email || !customerData?.fullName) {\n this.logger.warn(\n 'Creating profile with incomplete data. ' +\n 'Profiles should be created during registration with complete customer information.'\n );\n }\n\n return this.riskClient.createProfile({\n customer_id: customerId,\n entity_type: 'individual',\n customer_status: 'active',\n full_name: customerData?.fullName || undefined,\n email_address: customerData?.email || '',\n primary_phone_number: customerData?.phone || undefined,\n date_of_birth: customerData?.dateOfBirth || undefined,\n location: `${geoVerification.location.city}, ${geoVerification.location.country}`,\n location_compliance: geoVerification.is_compliant ? 'compliant' : 'non-compliant',\n country_of_residence: geoVerification.location.country_iso,\n kyc_status: 'pending',\n });\n }\n\n /**\n * Execute cipherText validation with graceful degradation.\n * Returns undefined if cipherText is not provided or validation fails.\n */\n private async executeCipherTextValidation(\n cipherText: string | undefined,\n userId: string,\n eventType: 'registration' | 'login' | 'transaction' | string,\n ipAddress: string,\n customerData?: {\n full_name?: string;\n email?: string;\n phone?: string;\n date_of_birth?: string;\n },\n requestOptions?: RequestOptions\n ): Promise<ValidateCipherTextResponse | undefined> {\n if (!cipherText) return undefined;\n\n try {\n return await this.geoClient.validateCipherText(\n cipherText,\n userId,\n eventType as any,\n ipAddress,\n customerData,\n requestOptions\n );\n } catch (err) {\n this.logger.warn('CipherText validation failed, proceeding with IP-only', {\n error: err instanceof Error ? err.message : 'Unknown error',\n });\n return undefined;\n }\n }\n\n /**\n * Build a LocationVerification from a ValidateCipherTextResponse.\n * The validate-ciphertext endpoint now returns the full geo-verification data\n * (is_compliant, jurisdiction, geofence_evaluation, record_id, gps_required),\n * so a separate verifyIP call is unnecessary.\n */\n private buildLocationFromCipherText(ct: ValidateCipherTextResponse, ipAddress: string): LocationVerification | null {\n const loc = ct.location;\n const risk = ct.risk;\n if (!risk) return null;\n\n return {\n ip_address: ct.ip_address || ipAddress,\n location: {\n country: loc?.country ?? '',\n country_iso: loc?.country_iso ?? '',\n city: loc?.city ?? '',\n region: loc?.region ?? '',\n postal_code: '',\n latitude: loc?.latitude ?? 0,\n longitude: loc?.longitude ?? 0,\n timezone: '',\n is_vpn: risk.is_vpn,\n is_proxy: risk.is_proxy,\n is_tor: risk.is_tor,\n is_hosting: risk.is_hosting ?? false,\n is_anonymizer: risk.is_vpn || risk.is_proxy || risk.is_tor,\n },\n is_compliant: ct.is_compliant ?? !risk.is_blocked,\n is_blocked: risk.is_blocked,\n risk_level: risk.level,\n risk_score: risk.score,\n risk_reasons: [],\n risk_reasons_structured: risk.is_blocked && risk.block_reasons_structured\n ? risk.block_reasons_structured\n : [],\n jurisdiction: ct.jurisdiction,\n geofence_evaluation: ct.geofence_evaluation,\n record_id: ct.record_id ?? '',\n gps_required: ct.gps_required,\n };\n }\n\n private calculateTransactionRisk(\n amount: number,\n currency: string,\n geoVerification: LocationVerification,\n profile: CustomerProfile,\n cipherTextResult?: ValidateCipherTextResponse\n ): TransactionRiskResult {\n if (!this._currencyRatesCustomized && !this._currencyRatesWarned) {\n this._currencyRatesWarned = true;\n this.logger.warn(\n 'Using default currency exchange rates. ' +\n 'Call updateCurrencyRates() or fetchCurrencyRates() for accurate transaction risk calculation.'\n );\n }\n\n let riskScore = 0;\n const structuredFactors: BlockReason[] = [];\n\n // Amount-based risk (normalized to USD)\n const normalizedAmount = this.normalizeToUSD(amount, currency);\n if (normalizedAmount > 10000) {\n riskScore += 30;\n structuredFactors.push(sdkReasons.transactionHighAmount(normalizedAmount, currency, 10000));\n } else if (normalizedAmount > 5000) {\n riskScore += 15;\n structuredFactors.push(sdkReasons.transactionElevatedAmount(normalizedAmount, currency, 5000));\n }\n\n // Geo risk\n riskScore += geoVerification.risk_score * 0.4;\n if (geoVerification.risk_level === 'high' || geoVerification.risk_level === 'critical') {\n structuredFactors.push(sdkReasons.riskHighLocation());\n }\n\n // Profile risk\n riskScore += profile.risk_score * 0.3;\n if (profile.risk_category === 'high' || profile.risk_category === 'critical') {\n structuredFactors.push(sdkReasons.riskHighCustomer());\n }\n\n // VPN/anonymizer during transaction\n if (geoVerification.location.is_vpn || geoVerification.location.is_proxy) {\n riskScore += 20;\n structuredFactors.push(sdkReasons.anonymizationDetected());\n }\n\n // Suspended account\n if (profile.customer_status === 'suspended') {\n riskScore += 50;\n structuredFactors.push(sdkReasons.accountSuspended());\n }\n\n // CipherText risk factors\n if (cipherTextResult) {\n if (cipherTextResult.risk?.location_mismatch) {\n riskScore += 20;\n structuredFactors.push(sdkReasons.gpsIPMismatch());\n }\n if (cipherTextResult.risk?.score) {\n riskScore += cipherTextResult.risk.score * 0.2;\n }\n }\n\n return {\n score: Math.min(riskScore, 100),\n level: this.getRiskLevel(riskScore),\n factors: structuredFactors.map(r => r.message),\n factorsStructured: structuredFactors,\n allowed: riskScore < 70,\n requiresManualReview: riskScore >= 60 && riskScore < 70,\n };\n }\n\n private checkJurisdictionLimits(\n amount: number,\n currency: string,\n jurisdiction?: JurisdictionConfig\n ): boolean {\n if (!jurisdiction || !jurisdiction.max_transaction_amount) {\n return true;\n }\n\n const normalizedAmount = this.normalizeToUSD(amount, currency);\n return normalizedAmount <= jurisdiction.max_transaction_amount;\n }\n\n private normalizeToUSD(amount: number, currency: string): number {\n const rate = this.currencyRates[currency.toUpperCase()] || 1;\n return amount * rate;\n }\n\n private getRiskLevel(score: number): 'low' | 'medium' | 'high' | 'critical' {\n if (score >= 80) return 'critical';\n if (score >= 60) return 'high';\n if (score >= 40) return 'medium';\n return 'low';\n }\n\n private getBlockReasons(\n geoVerification: LocationVerification,\n profile: CustomerProfile | null,\n cipherTextResult?: ValidateCipherTextResponse\n ): BlockReason[] {\n const reasons: BlockReason[] = [];\n\n if (geoVerification.is_blocked) {\n reasons.push(...(geoVerification.risk_reasons_structured ?? []));\n }\n\n if (profile) {\n if (profile.customer_status === 'suspended') {\n reasons.push(sdkReasons.accountSuspended());\n }\n\n if (profile.has_sanctions) {\n reasons.push(sdkReasons.sanctionsMatch());\n }\n }\n\n if (cipherTextResult) {\n if (!cipherTextResult.valid) {\n reasons.push(sdkReasons.ciphertextInvalid());\n }\n if (cipherTextResult.risk?.is_blocked) {\n reasons.push(...(cipherTextResult.risk.block_reasons_structured ?? []));\n }\n }\n\n // GPS required but no cipherText provided — block\n if (geoVerification.gps_required && !cipherTextResult) {\n reasons.push(sdkReasons.gpsRequired());\n }\n\n const seen = new Set<string>();\n return reasons.filter(r => {\n if (seen.has(r.code)) return false;\n seen.add(r.code);\n return true;\n });\n }\n\n private getTransactionBlockReasons(\n geoVerification: LocationVerification,\n transactionRisk: TransactionRiskResult,\n jurisdictionAllowed: boolean,\n cipherTextResult?: ValidateCipherTextResponse\n ): BlockReason[] {\n const reasons: BlockReason[] = [];\n\n if (!geoVerification.is_compliant) {\n reasons.push(sdkReasons.jurisdictionNonCompliant());\n }\n\n if (!jurisdictionAllowed) {\n reasons.push(sdkReasons.transactionJurisdictionLimit());\n }\n\n if (!transactionRisk.allowed) {\n reasons.push(...(transactionRisk.factorsStructured ?? []));\n }\n\n if (cipherTextResult) {\n if (!cipherTextResult.valid) {\n reasons.push(sdkReasons.ciphertextInvalid());\n }\n if (cipherTextResult.risk?.is_blocked) {\n reasons.push(...(cipherTextResult.risk.block_reasons_structured ?? []));\n }\n }\n\n // GPS required but no cipherText provided — block\n if (geoVerification.gps_required && !cipherTextResult) {\n reasons.push(sdkReasons.gpsRequired());\n }\n\n const seen = new Set<string>();\n return reasons.filter(r => {\n if (seen.has(r.code)) return false;\n seen.add(r.code);\n return true;\n });\n }\n\n // ============================================================================\n // Location Request Methods\n // ============================================================================\n\n /**\n * Request live location from a customer\n *\n * Creates a location request and sends a notification to the customer\n * via the specified channel (SMS, email, or push). The customer receives\n * a link to share their location.\n *\n * @param input - Location request details\n * @returns Location request result with share link\n *\n * @example\n * ```typescript\n * // Request location via SMS for transaction verification\n * const result = await sdk.requestCustomerLocation({\n * customerId: 'CUST-12345',\n * channel: 'sms',\n * phone: '+1234567890',\n * reason: 'Verification required for high-value transaction'\n * });\n *\n * console.log('Share link sent:', result.shareLink);\n * console.log('Expires at:', result.tokenExpiry);\n *\n * // Request location via email\n * const emailResult = await sdk.requestCustomerLocation({\n * customerId: 'CUST-12345',\n * channel: 'email',\n * email: 'customer@example.com',\n * reason: 'Account verification',\n * expiryHours: 48\n * });\n * ```\n */\n async requestCustomerLocation(\n input: ComplianceLocationRequestInput,\n requestOptions?: RequestOptions\n ): Promise<ComplianceLocationRequestResult> {\n if (this.config.debug) {\n this.logger.debug('Creating location request for customer', { customerId: input.customerId });\n }\n\n // Validate input\n this.validateLocationRequestInput(input);\n\n // Get customer profile if available\n let profile: CustomerProfile | undefined;\n try {\n profile = await this.riskClient.getProfile(input.customerId, requestOptions);\n } catch (error) {\n if (this.config.debug) {\n this.logger.warn('Customer profile not found', { customerId: input.customerId });\n }\n }\n\n // Use profile data if contact info not provided\n const phone = input.phone || profile?.primary_phone_number;\n const email = input.email || profile?.email_address;\n\n // Create the location request\n const result = await this.geoClient.createLocationRequest({\n user_id: input.customerId,\n channel: input.channel,\n reason: input.reason,\n phone: phone,\n email: email,\n expiry_hours: input.expiryHours,\n }, requestOptions);\n\n if (this.config.debug) {\n this.logger.debug('Location request created', {\n requestId: result.request.id,\n channel: input.channel,\n expiresAt: result.token_expiry,\n });\n }\n\n return {\n request: result.request,\n shareLink: result.share_link,\n tokenExpiry: result.token_expiry,\n profile: profile,\n };\n }\n\n /**\n * Get a specific location request by ID\n *\n * @param requestId - Location request ID\n * @returns Location request details\n *\n * @example\n * ```typescript\n * const request = await sdk.getLocationRequest('req_abc123');\n * console.log('Status:', request.status);\n * if (request.latitude && request.longitude) {\n * console.log('Location captured:', request.latitude, request.longitude);\n * }\n * ```\n */\n async getLocationRequest(requestId: string, requestOptions?: RequestOptions): Promise<LocationRequest> {\n return this.geoClient.getLocationRequest(requestId, requestOptions);\n }\n\n /**\n * List location requests with filters and pagination\n *\n * @param filters - Optional filters\n * @param pagination - Optional pagination\n * @returns Paginated list of location requests\n *\n * @example\n * ```typescript\n * // Get pending requests for a customer\n * const pending = await sdk.listLocationRequests(\n * { status: 'pending', user_id: 'CUST-12345' },\n * { page: 1, limit: 20 }\n * );\n *\n * // Get all completed requests from last week\n * const completed = await sdk.listLocationRequests({\n * status: 'completed',\n * date_from: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString()\n * });\n * ```\n */\n async listLocationRequests(\n filters?: LocationRequestFilters,\n pagination?: PaginationParams,\n requestOptions?: RequestOptions\n ): Promise<LocationRequestListResponse> {\n return this.geoClient.listLocationRequests(filters, pagination, requestOptions);\n }\n\n /**\n * Cancel a pending location request\n *\n * @param requestId - Location request ID\n *\n * @example\n * ```typescript\n * await sdk.cancelLocationRequest('req_abc123');\n * ```\n */\n async cancelLocationRequest(requestId: string, requestOptions?: RequestOptions): Promise<void> {\n if (this.config.debug) {\n this.logger.debug('Cancelling location request', { requestId });\n }\n await this.geoClient.cancelLocationRequest(requestId, requestOptions);\n }\n\n /**\n * Resend notification for a location request\n *\n * @param requestId - Location request ID\n * @param contact - Contact details (email or phone)\n *\n * @example\n * ```typescript\n * // Resend to a different phone number\n * await sdk.resendLocationRequest('req_abc123', { phone: '+0987654321' });\n *\n * // Resend to email\n * await sdk.resendLocationRequest('req_abc123', { email: 'new@example.com' });\n * ```\n */\n async resendLocationRequest(\n requestId: string,\n contact: { email?: string; phone?: string },\n requestOptions?: RequestOptions\n ): Promise<void> {\n if (this.config.debug) {\n this.logger.debug('Resending location request', { requestId });\n }\n await this.geoClient.resendLocationRequest(requestId, contact, requestOptions);\n }\n\n /**\n * Validate location request input\n */\n private validateLocationRequestInput(input: ComplianceLocationRequestInput): void {\n const errors: string[] = [];\n\n if (!input.customerId?.trim()) {\n errors.push('customerId is required');\n }\n\n if (!input.channel) {\n errors.push('channel is required');\n }\n\n if (!input.reason?.trim()) {\n errors.push('reason is required for compliance/audit purposes');\n }\n\n // Channel-specific validation\n if (input.channel === 'sms' && !input.phone) {\n errors.push('phone is required for SMS channel');\n }\n\n if (input.channel === 'email' && !input.email) {\n errors.push('email is required for email channel');\n }\n\n if (errors.length > 0) {\n throw new ValidationError(`Invalid location request: ${errors.join(', ')}`, errors);\n }\n }\n\n // ============================================================================\n // Configuration\n // ============================================================================\n\n /**\n * Update currency exchange rates\n *\n * Use this to keep currency rates current for accurate transaction risk\n * calculation. Rates should be updated regularly (e.g., daily).\n *\n * @param rates - Currency to USD exchange rates\n *\n * @example\n * ```typescript\n * // Update specific rates\n * sdk.updateCurrencyRates({\n * EUR: 1.08,\n * GBP: 1.25,\n * BTC: 42000, // For crypto support\n * });\n *\n * // Or fetch from external service\n * const rates = await fetchExchangeRates();\n * sdk.updateCurrencyRates(rates);\n * ```\n */\n updateCurrencyRates(rates: CurrencyRates): void {\n this.currencyRates = { ...this.currencyRates, ...rates };\n this._currencyRatesCustomized = true;\n }\n\n /**\n * Get current currency rates\n *\n * @returns Current currency to USD exchange rates\n */\n getCurrencyRates(): Readonly<CurrencyRates> {\n return { ...this.currencyRates };\n }\n\n}\n","/**\n * KycClient - TypeScript SDK for Vesant KYC (Know Your Customer) Service\n *\n * Provides type-safe methods to interact with the KYC service API.\n * Extends BaseClient for consistent retry logic, timeout handling, and error management.\n */\n\nimport { BaseClient } from '../core/client';\nimport { ValidationError } from '../core/errors';\nimport type { BaseClientConfig, RequestOptions } from '../core/config';\nimport type {\n KycClientConfig,\n KycRequest,\n KycRequestFilters,\n KycRequestListResponse,\n DocumentVerificationRequest,\n DocumentVerificationResponse,\n UpdateKycStatusRequest,\n RequestAdditionalDocumentsRequest,\n RequestKycSubmitLinkRequest,\n RequestKycSubmitLinkResponse,\n CheckKycStatusRequest,\n CheckKycStatusResponse,\n ProofDownloadURL,\n KycOverview,\n KycAlert,\n KycAlertFilters,\n KycAlertListResponse,\n UpdateKycAlertRequest,\n KycPreferences,\n UpdateKycPreferencesRequest,\n PaginationParams,\n CustomerProfile,\n CustomerProfileFilters,\n CustomerProfileListResponse,\n CreateCustomerProfileRequest,\n CreateEventBasedFaceVerificationSessionRequest,\n CreateEventBasedFaceVerificationSessionResponse,\n SubmitEventBasedFaceVerificationSessionRequest,\n EventBasedFaceVerificationCallback,\n KycHandoffSession,\n} from './types';\n\n/** Helper to add filter value to params, joining arrays with commas */\nfunction addFilterParam(\n params: Record<string, unknown>,\n key: string,\n value: string | string[] | undefined\n): void {\n if (value !== undefined) {\n params[key] = Array.isArray(value) ? value.join(',') : value;\n }\n}\n\n/** Helper to add simple filter values to params */\nfunction addSimpleParams(\n params: Record<string, unknown>,\n source: Record<string, unknown>,\n keys: string[]\n): void {\n for (const key of keys) {\n if (source[key] !== undefined) {\n params[key] = source[key];\n }\n }\n}\n\n/**\n * KycClient extends BaseClient for:\n * - Consistent retry logic with exponential backoff\n * - Unified error handling (VesantError, NetworkError, TimeoutError, etc.)\n * - Automatic timeout management\n * - Debug logging\n *\n * Read calls use requestWithRetry() to ride out transient failures.\n * Calls that create or bill something (submit link, document submit,\n * face session, face submit, hosted journey retry) are made exactly once.\n */\nexport class KycClient extends BaseClient {\n private userId?: string;\n private readonly riskProfileBaseURL?: string;\n\n constructor(config: KycClientConfig) {\n // Convert KycClientConfig to BaseClientConfig\n const baseConfig: BaseClientConfig = {\n baseURL: config.baseURL,\n tenantId: config.tenantId,\n apiKey: config.apiKey,\n headers: config.headers,\n timeout: config.timeout,\n retries: 3, // Default retry count for KYC calls\n debug: config.debug,\n environment: config.environment,\n };\n super(baseConfig);\n this.userId = config.userId;\n this.riskProfileBaseURL = config.riskProfileBaseURL;\n }\n\n /**\n * Set the user ID for operations requiring user context\n */\n setUserId(userId: string): void {\n this.userId = userId;\n }\n\n /**\n * Get current user ID\n */\n getUserId(): string | undefined {\n return this.userId;\n }\n\n /**\n * Build headers including user ID if available\n */\n private getUserHeaders(): Record<string, string> {\n const headers: Record<string, string> = {};\n if (this.userId) {\n headers['X-User-ID'] = this.userId;\n }\n return headers;\n }\n\n // ============================================================================\n // Document Verification\n // ============================================================================\n\n /**\n * Request a KYC submission redirect URL for a user\n *\n * Generates a link that the user can visit to submit their KYC documents.\n *\n * Pass the `trigger_event` that matches the user action so the tenant's\n * trigger preferences decide whether verification is required; inspect\n * `kyc_required` and `reason` on the response before redirecting.\n *\n * Optionally pass the customer's registered identity data as\n * `customer_data` (same shape as the geolocation `customer_data` block).\n * It seeds the customer's risk profile so document verification can\n * cross-check the submitted document against trusted reference data;\n * fields never overwrite data already on the profile.\n *\n * The call is made once and is not retried: each request creates a new\n * KYC record and link, so a retry after a timeout would leave duplicates.\n *\n * @param request - Request containing the user ID, trigger event, optional redirect URL, optional callback URL (receives POST requests), and optional customer identity data\n * @returns Response containing the redirect link, KYC ID, `kyc_required`, `can_skip` and `reason`\n *\n * @example\n * ```typescript\n * const result = await client.requestKycSubmitLink({\n * user_id: \"user_123\",\n * trigger_event: \"onboarding\",\n * redirect_url: \"https://merchant.com/kyc-complete\", // optional\n * callback_url: \"https://merchant.com/api/kyc-webhook\", // optional - receives POST requests on status change\n * customer_data: { // optional - seeds the risk profile for document cross-checks\n * full_name: \"John Doe\",\n * date_of_birth: \"1999-06-02\", // ISO 8601\n * email: \"john@example.com\",\n * phone: \"+94771234567\",\n * address: \"12 Main St, Colombo\", // used for address verification\n * country: \"LK\"\n * }\n * });\n *\n * if (!result.kyc_required) return proceed();\n * console.log(`Redirect user to: ${result.link}`);\n * console.log(`KYC ID: ${result.kyc_id}`);\n * ```\n */\n async requestKycSubmitLink(\n request: RequestKycSubmitLinkRequest,\n requestOptions?: RequestOptions\n ): Promise<RequestKycSubmitLinkResponse> {\n // One-shot: creating a submit link inserts a KYC row and issues a link\n // on every call, and the platform does not replay this route from an\n // idempotency key, so an automatic retry would create duplicates.\n return this.request<RequestKycSubmitLinkResponse>('/api/v1/kyc/request', {\n method: 'POST',\n body: JSON.stringify(request),\n headers: this.getUserHeaders(),\n }, undefined, requestOptions);\n }\n\n /**\n * Create a Event-Based Face Verification session.\n *\n * Inspect the response before showing UI:\n * - `is_required === false` → skip face verification; `reason` explains why.\n * - `verification_url` present → embed the hosted journey and poll status.\n * - `verification_url` absent → use the local camera / QR fallback.\n *\n * @param request - Reference, customer_id, event, amount (for threshold events), optional URLs.\n */\n async createEventBasedFaceVerificationSession(request: CreateEventBasedFaceVerificationSessionRequest): Promise<CreateEventBasedFaceVerificationSessionResponse> {\n // One-shot: do NOT use requestWithRetry. Creating a session is a\n // non-idempotent POST that allocates server-side state (DB row + Redis\n // handoff). Retrying on timeout would create duplicate sessions and\n // burn provider references on the follow-up submit.\n return this.request<CreateEventBasedFaceVerificationSessionResponse>('/api/v1/kyc/face/session', {\n method: 'POST',\n body: JSON.stringify(request),\n headers: this.getUserHeaders(),\n });\n }\n\n /**\n * Submit a real-time face capture for an active Event-Based Face Verification session.\n *\n * Works from any device: the platform does not inspect the User-Agent.\n * `FaceCaptureModal` decides between direct capture and the QR handoff\n * on the client; custom UIs may submit from desktop or mobile alike.\n *\n * The `data` field on the response carries `retries_remaining`,\n * `retry_limit_exceeded`, and the reaction flags (`enforce_logout`,\n * `freeze_account`, etc.) so the tenant app can act on a final failure.\n *\n * @param request - Token from `createEventBasedFaceVerificationSession`, plus the base64 selfie.\n */\n async submitEventBasedFaceVerificationSession(request: SubmitEventBasedFaceVerificationSessionRequest, requestOptions?: RequestOptions): Promise<EventBasedFaceVerificationCallback> {\n // One-shot: do NOT use requestWithRetry. Submitting a selfie is a\n // non-idempotent POST — every call uploads the image, calls the\n // provider (billable), and increments the `attempts` counter on the\n // session row. Retries on transient errors would burn attempts and\n // produce multiple provider responses for one user action. Manual retries\n // (user clicks \"Try again\" in the modal) re-call this method\n // explicitly, which is the right surface for the retry decision.\n return this.request<EventBasedFaceVerificationCallback>('/api/v1/kyc/face/submit', {\n method: 'POST',\n body: JSON.stringify(request),\n headers: this.getUserHeaders(),\n }, undefined, requestOptions);\n }\n\n /**\n * Look up the current state of a Event-Based Face Verification session by its\n * session token. Useful for desktop pollers waiting on the mobile handoff.\n *\n * The lookup is scoped by the unguessable, server-issued session token (not\n * the enumerable forward reference): the endpoint is public/unauthenticated,\n * and scoping by the token is what prevents cross-tenant status reads.\n *\n * @param token - The session token returned by `createEventBasedFaceVerificationSession`.\n */\n async getEventBasedFaceVerificationSessionStatus(token: string): Promise<EventBasedFaceVerificationCallback> {\n return this.requestWithRetry<EventBasedFaceVerificationCallback>(`/api/v1/kyc/face/verify/${encodeURIComponent(token)}`, {\n method: 'GET',\n headers: this.getUserHeaders(),\n });\n }\n\n /**\n * Mint a fresh hosted verification journey for the next attempt on an\n * active session whose previous hosted-journey attempt was declined.\n * Only valid while the session is active and attempts remain; the\n * response carries the new `verification_url` to embed. Used internally\n * by `FaceCaptureModal`'s Try Again flow in hosted-journey mode.\n *\n * @param token - The session token returned by `createEventBasedFaceVerificationSession`.\n */\n async retryEventBasedFaceVerificationJourney(token: string): Promise<CreateEventBasedFaceVerificationSessionResponse> {\n return this.request<CreateEventBasedFaceVerificationSessionResponse>('/api/v1/kyc/face/onsite/journey', {\n method: 'POST',\n body: JSON.stringify({ token }),\n headers: this.getUserHeaders(),\n });\n }\n\n /**\n * Fetch the Redis-backed handoff session for a token. Same backing\n * store as normal KYC (`kyc:session:<token>`, 15-minute TTL). The\n * Event-Based Face Verification database session still expires after\n * 10 minutes. Desktop callers poll `mobile_connected` to detect when a\n * mobile device has scanned the QR and attached.\n *\n * @param token - The session token returned by `createEventBasedFaceVerificationSession`.\n */\n async getHandoffSession(token: string): Promise<KycHandoffSession> {\n return this.request<KycHandoffSession>(\n `/api/v1/kyc/session${this.buildQueryString({ token })}`,\n { headers: this.getUserHeaders() }\n );\n }\n\n /**\n * Attach a mobile device to a desktop-initiated session. The mobile\n * client calls this after scanning the QR code. The desktop poller\n * sees `mobile_connected: true` on the next `getHandoffSession`.\n *\n * @param token - The session token transferred via the QR payload.\n * @param isDisconnect - Pass true to release the session (default false).\n */\n async connectMobileSession(token: string, isDisconnect = false): Promise<{ mobile_connected: boolean }> {\n return this.request<{ mobile_connected: boolean }>('/api/v1/kyc/session/connect', {\n method: 'PUT',\n body: JSON.stringify({ token, is_disconnect: isDisconnect }),\n headers: this.getUserHeaders(),\n });\n }\n /**\n * Check KYC status for a user\n *\n * Returns the current KYC status:\n * - \"accepted\" / \"review.pending\" → verified (limited access while under review)\n * - \"pending\" → documents submitted, verification running: keep polling\n * - \"awaiting_kyc\" → nothing submitted yet; check `link_expired` before\n * re-surfacing or re-requesting the link. Never treat as in progress.\n * - \"declined\" → show `additional_data.declined_reasons` (fallback\n * `declined_reason`) with a retry option\n *\n * @param request - Request containing user_id and kyc_id\n * @returns Response with status, verification flags and, once terminal, the full record in `additional_data`\n *\n * @example\n * ```typescript\n * const result = await client.checkKycStatus({\n * user_id: \"user_123\",\n * kyc_id: \"550e8400-e29b-41d4-a716-446655440000\"\n * });\n *\n * if (result.status === 'accepted' || result.status === 'review.pending') {\n * // Grant access\n * } else if (result.status === 'declined') {\n * const reasons = result.additional_data?.declined_reasons;\n * // Show error + retry option\n * } else if (result.status === 'awaiting_kyc') {\n * // Prompt to verify; request a new link when result.link_expired is true\n * } else {\n * // Keep polling\n * }\n * ```\n */\n async checkKycStatus(\n request: CheckKycStatusRequest\n ): Promise<CheckKycStatusResponse> {\n const params = {\n user_id: request.user_id,\n kyc_id: request.kyc_id,\n };\n\n return this.requestWithRetry<CheckKycStatusResponse>(\n `/api/v1/kyc/request/status${this.buildQueryString(params)}`,\n {\n method: 'GET',\n headers: this.getUserHeaders(),\n }\n );\n }\n\n /**\n * Submit a document verification request with OCR\n *\n * The call is made once and is not retried: every submission is processed\n * and billed, and the platform does not replay this route from an\n * idempotency key. Retry explicitly if the request fails.\n *\n * @param request - Document verification request with documents and customer info\n * @returns Verification response with status and reference\n *\n * @example\n * ```typescript\n * const result = await client.submitVerification({\n * reference: \"4d2aff34-ab86-422d-992e-50b1234a5b67\",\n * email: \"customer@example.com\",\n * country: \"US\",\n * document: {\n * proof: base64EncodedImage,\n * selected_type: [\"id_card\", \"passport\"],\n * name: { first_name: \"John\", last_name: \"Doe\" },\n * dob: \"1990-01-15\"\n * },\n * face: {\n * proof: base64EncodedSelfie\n * }\n * });\n *\n * console.log(`Verification submitted: ${result.reference}`);\n * ```\n */\n async submitVerification(\n request: DocumentVerificationRequest,\n requestOptions?: RequestOptions\n ): Promise<DocumentVerificationResponse> {\n // One-shot: a document submission is billable and non-idempotent.\n return this.request<DocumentVerificationResponse>('/api/v1/kyc/submit', {\n method: 'POST',\n body: JSON.stringify(request),\n headers: this.getUserHeaders(),\n }, undefined, requestOptions);\n }\n\n /**\n * Get a KYC request by ID\n *\n * @param id - KYC request ID\n * @returns KYC request details including proofs and alerts\n *\n * @example\n * ```typescript\n * const kyc = await client.getKycRequest(\"550e8400-e29b-41d4-a716-446655440000\");\n * console.log(`Status: ${kyc.status}, ID Verified: ${kyc.id_verified}`);\n * ```\n */\n async getKycRequest(id: string): Promise<KycRequest> {\n return this.request<KycRequest>(`/api/v1/kyc/requests/${id}`);\n }\n\n /**\n * List KYC requests with filters and pagination\n *\n * @param filters - Optional filters (status, search, date range)\n * @param pagination - Optional pagination (page, page_size)\n * @returns Paginated list of KYC requests\n *\n * @example\n * ```typescript\n * const requests = await client.listKycRequests(\n * { status: \"pending\", search: \"john\" },\n * { page: 1, page_size: 20 }\n * );\n * console.log(`Found ${requests.total} pending requests`);\n * ```\n */\n async listKycRequests(\n filters?: KycRequestFilters,\n pagination?: PaginationParams\n ): Promise<KycRequestListResponse> {\n const params: Record<string, unknown> = {};\n\n if (filters) {\n addFilterParam(params, 'status', filters.status);\n addSimpleParams(params, filters as unknown as Record<string, unknown>, ['search', 'fromDate', 'toDate', 'sortBy', 'order']);\n }\n\n if (pagination) {\n if (pagination.page) params.page = pagination.page;\n if (pagination.page_size) params.limit = pagination.page_size;\n }\n\n return this.request<KycRequestListResponse>(\n `/api/v1/kyc/requests${this.buildQueryString(params)}`,\n { headers: this.getUserHeaders() }\n );\n }\n\n /**\n * Update KYC request status (accept/decline)\n *\n * @param request - Status update request with reference, status, and reason\n *\n * @example\n * ```typescript\n * // Accept a KYC request\n * await client.updateKycStatus({\n * reference: \"kyc-ref-123\",\n * status: \"accepted\",\n * reason: \"All documents verified successfully\"\n * });\n *\n * // Decline a KYC request\n * await client.updateKycStatus({\n * reference: \"kyc-ref-456\",\n * status: \"declined\",\n * reason: \"Document expired\"\n * });\n * ```\n */\n async updateKycStatus(request: UpdateKycStatusRequest): Promise<void> {\n await this.request('/api/v1/kyc/status', {\n method: 'PUT',\n body: JSON.stringify(request),\n headers: this.getUserHeaders(),\n });\n }\n\n /**\n * Request additional documents from customer\n *\n * @deprecated The platform does not expose this operation; the call always\n * fails. Request additional documents from the Vesant console instead.\n * This method will be removed in a future release.\n *\n * @param request - Request with KYC ID and document types needed\n *\n * @example\n * ```typescript\n * await client.requestAdditionalDocuments({\n * id: \"550e8400-e29b-41d4-a716-446655440000\",\n * document_types: [\"address\", \"document_two\"],\n * message: \"Please provide proof of address and secondary ID\"\n * });\n * ```\n */\n async requestAdditionalDocuments(\n request: RequestAdditionalDocumentsRequest\n ): Promise<void> {\n await this.request('/api/v1/kyc/requests', {\n method: 'PUT',\n body: JSON.stringify(request),\n headers: this.getUserHeaders(),\n });\n }\n\n /**\n * Get downloadable URLs for KYC proofs/documents\n *\n * @param kycId - KYC request ID\n * @returns Array of proof download URLs with expiration\n *\n * @example\n * ```typescript\n * const proofs = await client.getProofDownloadURLs(\"550e8400-e29b-41d4-a716-446655440000\");\n * proofs.forEach(proof => {\n * console.log(`${proof.type}: ${proof.url} (expires: ${proof.expires_at})`);\n * });\n * ```\n */\n async getProofDownloadURLs(kycId: string): Promise<ProofDownloadURL[]> {\n return this.request<ProofDownloadURL[]>(\n `/api/v1/kyc/proofs/${kycId}`,\n { headers: this.getUserHeaders() }\n );\n }\n\n // ============================================================================\n // KYC Overview & Statistics\n // ============================================================================\n\n /**\n * Get KYC overview statistics\n *\n * @param fromDate - Optional start date (ISO 8601)\n * @param toDate - Optional end date (ISO 8601)\n * @returns KYC statistics including counts by status\n *\n * @example\n * ```typescript\n * const overview = await client.getOverview(\n * \"2024-01-01T00:00:00Z\",\n * \"2024-12-31T23:59:59Z\"\n * );\n * console.log(`Total: ${overview.total}, Pending: ${overview.pending}`);\n * console.log(`Approved: ${overview.approved}, Rejected: ${overview.rejected}`);\n * ```\n */\n async getOverview(fromDate?: string, toDate?: string): Promise<KycOverview> {\n const params: Record<string, unknown> = {};\n if (fromDate) params.fromDate = fromDate;\n if (toDate) params.toDate = toDate;\n\n return this.request<KycOverview>(\n `/api/v1/kyc/overview${this.buildQueryString(params)}`\n );\n }\n\n // ============================================================================\n // Alert Management\n // ============================================================================\n\n /**\n * Get a KYC alert by ID\n *\n * @param alertId - Alert ID\n * @returns Alert details\n */\n async getAlert(alertId: string): Promise<KycAlert> {\n return this.request<KycAlert>(`/api/v1/kyc/alerts/${alertId}`);\n }\n\n /**\n * List KYC alerts with filters and pagination\n *\n * @param filters - Optional filters (status, risk, alert_type, assigned_for, etc.)\n * @param pagination - Optional pagination (page, page_size)\n * @returns Paginated list of alerts\n *\n * @example\n * ```typescript\n * const alerts = await client.listAlerts(\n * {\n * status: [\"pending\", \"in_progress\"],\n * risk: \"critical\",\n * alert_type: \"kyc\"\n * },\n * { page: 1, page_size: 20 }\n * );\n * console.log(`Found ${alerts.total} alerts`);\n * ```\n */\n async listAlerts(\n filters?: KycAlertFilters,\n pagination?: PaginationParams\n ): Promise<KycAlertListResponse> {\n const params: Record<string, unknown> = {};\n\n if (filters) {\n // Array filters that need comma joining\n addFilterParam(params, 'kyc_id', filters.kyc_id);\n addFilterParam(params, 'alert_type', filters.alert_type);\n addFilterParam(params, 'assigned_for', filters.assigned_for);\n addFilterParam(params, 'status', filters.status);\n addFilterParam(params, 'risk', filters.risk);\n // Simple filters\n addSimpleParams(params, filters as unknown as Record<string, unknown>, ['search', 'fromDate', 'toDate', 'sort_by', 'order']);\n }\n\n if (pagination) {\n if (pagination.page) params.page = pagination.page;\n if (pagination.page_size) params.limit = pagination.page_size;\n }\n\n return this.request<KycAlertListResponse>(\n `/api/v1/kyc/alerts${this.buildQueryString(params)}`\n );\n }\n\n /**\n * Update a KYC alert\n *\n * @param alertId - Alert ID\n * @param update - Fields to update (status, assigned_for, reason, alert_type)\n *\n * @example\n * ```typescript\n * // Assign an alert\n * await client.updateAlert(\"alert_123\", {\n * assigned_for: \"analyst_user_id\",\n * status: \"in_progress\"\n * });\n *\n * // Resolve an alert\n * await client.updateAlert(\"alert_123\", {\n * status: \"resolved\",\n * reason: \"Customer verified via phone call\"\n * });\n *\n * // Escalate an alert\n * await client.updateAlert(\"alert_123\", {\n * status: \"escalated\",\n * assigned_for: \"manager_user_id\",\n * reason: \"Requires senior review - suspicious documents\"\n * });\n * ```\n */\n async updateAlert(alertId: string, update: UpdateKycAlertRequest): Promise<void> {\n await this.request(`/api/v1/kyc/alerts/${alertId}`, {\n method: 'PUT',\n body: JSON.stringify(update),\n headers: this.getUserHeaders(),\n });\n }\n\n // ============================================================================\n // KYC Preferences\n // ============================================================================\n\n /**\n * Get KYC preferences for the tenant\n *\n * @returns KYC preferences configuration\n *\n * @example\n * ```typescript\n * const prefs = await client.getPreferences();\n * console.log(`Face verification required: ${prefs.is_face_verification_required}`);\n * console.log(`Required documents: ${prefs.required_document_count}`);\n * ```\n */\n async getPreferences(): Promise<KycPreferences> {\n return this.request<KycPreferences>('/api/v1/kyc/preferences');\n }\n\n /**\n * Update KYC preferences for the tenant\n *\n * @deprecated KYC preferences are managed in the Vesant console; the\n * platform exposes no update operation to the SDK, so this call always\n * fails. Use `getPreferences()` to read them. This method will be removed\n * in a future release.\n *\n * @param update - Fields to update\n * @returns Updated preferences\n *\n * @example\n * ```typescript\n * await client.updatePreferences({\n * is_face_verification_required: true,\n * is_address_verification_required: true,\n * required_document_count: 2,\n * reasons: [\n * \"Documents verified\",\n * \"Identity confirmed\",\n * \"Address matched\"\n * ]\n * });\n * ```\n */\n async updatePreferences(\n update: UpdateKycPreferencesRequest\n ): Promise<KycPreferences> {\n return this.request<KycPreferences>('/api/v1/kyc/preferences', {\n method: 'PUT',\n body: JSON.stringify(update),\n });\n }\n\n // ============================================================================\n // Customer Profile Management (Risk Profile Service)\n // ============================================================================\n\n /**\n * Make a request to the Risk Profile Service\n * Uses riskProfileBaseURL if configured, otherwise falls back to baseURL\n */\n private async riskProfileRequest<T>(\n path: string,\n options: RequestInit = {}\n ): Promise<T> {\n if (!this.riskProfileBaseURL) {\n throw new ValidationError(\n 'Risk Profile Service URL not configured. Please provide riskProfileBaseURL in KycClientConfig.',\n ['riskProfileBaseURL']\n );\n }\n\n return this.request<T>(path, {\n ...options,\n headers: {\n ...this.getUserHeaders(),\n ...(options.headers as Record<string, string>),\n },\n }, this.riskProfileBaseURL);\n }\n\n /**\n * List customer profiles for the tenant\n *\n * @param filters - Optional filters (risk_category, entity_type, status, search, etc.)\n * @param pagination - Optional pagination (limit, offset)\n * @returns Paginated list of customer profiles\n *\n * @example\n * ```typescript\n * const profiles = await client.listCustomerProfiles(\n * { risk_category: 'high', entity_type: 'individual' },\n * { limit: 20, offset: 0 }\n * );\n * console.log(`Found ${profiles.total} profiles`);\n * profiles.profiles.forEach(p => console.log(p.customer_id, p.full_name));\n * ```\n */\n async listCustomerProfiles(\n filters?: CustomerProfileFilters,\n pagination?: { limit?: number; offset?: number }\n ): Promise<CustomerProfileListResponse> {\n const params: Record<string, unknown> = {};\n\n if (filters) {\n // Array filters (keep as arrays for this API)\n if (filters.risk_category) {\n params.risk_category = Array.isArray(filters.risk_category)\n ? filters.risk_category\n : [filters.risk_category];\n }\n if (filters.entity_type) {\n params.entity_type = Array.isArray(filters.entity_type)\n ? filters.entity_type\n : [filters.entity_type];\n }\n if (filters.status) {\n params.status = Array.isArray(filters.status)\n ? filters.status\n : [filters.status];\n }\n // Simple filters\n addSimpleParams(params, filters as unknown as Record<string, unknown>, [\n 'search', 'is_pep', 'has_sanctions', 'requires_edd', 'sort_by', 'sort_order'\n ]);\n }\n\n if (pagination) {\n addSimpleParams(params, pagination, ['limit', 'offset']);\n }\n\n return this.riskProfileRequest<CustomerProfileListResponse>(\n `/api/v1/risk-dashboard/profiles${this.buildQueryString(params)}`\n );\n }\n\n /**\n * Get a customer profile by ID\n *\n * @param profileId - The profile UUID\n * @returns Customer profile details\n *\n * @example\n * ```typescript\n * const profile = await client.getCustomerProfile('uuid-here');\n * console.log(`Customer: ${profile.full_name}, Risk: ${profile.risk_category}`);\n * ```\n */\n async getCustomerProfile(profileId: string): Promise<CustomerProfile> {\n return this.riskProfileRequest<CustomerProfile>(\n `/api/v1/risk-dashboard/profiles/${profileId}`\n );\n }\n\n /**\n * Create a new customer profile\n *\n * A customer profile must exist before submitting KYC verification.\n * The customer_id field will be used as the 'reference' in KYC submissions.\n *\n * @param profile - Customer profile data\n * @returns Created customer profile\n *\n * @example\n * ```typescript\n * const profile = await client.createCustomerProfile({\n * customer_id: 'cust_123',\n * entity_type: 'individual',\n * full_name: 'John Doe',\n * email_address: 'john@example.com',\n * country_of_residence: 'US'\n * });\n * console.log(`Created profile: ${profile.id}`);\n *\n * // Now you can submit KYC using the customer_id as reference\n * await client.submitVerification({\n * reference: profile.customer_id, // 'cust_123'\n * email: 'john@example.com',\n * // ... other fields\n * });\n * ```\n */\n async createCustomerProfile(\n profile: CreateCustomerProfileRequest\n ): Promise<CustomerProfile> {\n return this.riskProfileRequest<CustomerProfile>('/api/v1/profiles', {\n method: 'POST',\n body: JSON.stringify(profile),\n });\n }\n\n // ============================================================================\n // Utility Methods (inherited from BaseClient: healthCheck, updateConfig, getConfig, buildQueryString)\n // ============================================================================\n}\n","/**\n * TypeScript type definitions for Vesant KYC Service API\n *\n * These types match the Go API structures in:\n * - services/kyc-service/internal/domain/\n * - services/kyc-service/internal/service/\n * - services/kyc-service/internal/handler/\n */\n\nimport type { PaginationParams, RiskLevel, Reason } from '../core/types';\n\n// Re-export commonly used types from core\nexport type { PaginationParams, RiskLevel };\n\n// ============================================================================\n// KYC Status & Enumerations\n// ============================================================================\n\nexport type KycStatus =\n /** Submit link issued but the customer has not submitted documents yet — not \"in progress\". */\n | 'awaiting_kyc'\n /** Documents submitted, verification in progress. */\n | 'pending'\n | 'accepted'\n | 'declined'\n | 'review.pending'\n | 'unknown';\n\nexport type KycDeclinedCode =\n | 'KYC_DOCUMENT_EXPIRED'\n | 'KYC_DOCUMENT_INVALID'\n | 'KYC_FACE_MISMATCH'\n | 'KYC_AGE_REQUIREMENT'\n | 'KYC_DUPLICATE_IDENTITY'\n | 'KYC_ADDRESS_MISMATCH'\n | 'KYC_NAME_MISMATCH'\n | 'KYC_PROVIDER_REJECTED'\n | 'KYC_DECLINED';\n\nexport const KYC_DECLINED_DESCRIPTIONS: Record<KycDeclinedCode, string> = {\n KYC_DOCUMENT_EXPIRED: 'The submitted document has expired',\n KYC_DOCUMENT_INVALID: 'The submitted document could not be verified',\n KYC_FACE_MISMATCH: 'Face verification did not match the identity document',\n KYC_AGE_REQUIREMENT: 'Age requirement not met',\n KYC_DUPLICATE_IDENTITY: 'This identity has already been verified under another account',\n KYC_ADDRESS_MISMATCH: 'Address verification failed',\n KYC_NAME_MISMATCH: 'Name on document does not match the registered name',\n KYC_PROVIDER_REJECTED: 'Identity verification was rejected by the verification provider',\n KYC_DECLINED: 'Identity verification was declined',\n};\n\nexport type KycAlertStatus = 'pending' | 'in_progress' | 'resolved' | 'closed' | 'escalated';\n\nexport type KycAlertType = 'kyc' | 'fraud';\n\nexport type DocumentType = 'id_card' | 'driving_license' | 'passport';\n\nexport type ProofType =\n | 'document'\n | 'document_two'\n | 'face'\n | 'address'\n | 'additional_document';\n\nexport type SupportedDocumentType = 'id_card' | 'passport' | 'driving_license';\n\n/** Document types a tenant can accept as proof of address. */\nexport type SupportedAddressDocumentType =\n | 'id_card'\n | 'passport'\n | 'driving_license'\n | 'utility_bill'\n | 'bank_statement'\n | 'rent_agreement'\n | 'employer_letter'\n | 'insurance_agreement'\n | 'tax_bill'\n | 'envelope'\n | 'cpr_smart_card_reader_copy'\n | 'property_tax'\n | 'lease_agreement'\n | 'insurance_card'\n | 'permanent_residence_permit'\n | 'credit_card_statement'\n | 'insurance_policy'\n | 'e_commerce_receipt'\n | 'bank_letter_receipt'\n | 'birth_certificate'\n | 'salary_slip';\n\n// ============================================================================\n// KYC Request Types\n// ============================================================================\n\nexport interface KycRequest {\n id: string;\n reference: string;\n forward_reference?: string;\n tenant_id: string;\n first_name: string;\n middle_name?: string;\n last_name: string;\n dob?: string;\n full_address?: string;\n email?: string;\n\n // Details extracted from the primary document (present once verification has run)\n gender?: string;\n height?: string;\n country?: string;\n country_code?: string;\n nationality?: string;\n authority?: string;\n document_type?: string;\n document_number?: string;\n personal_number?: string;\n place_of_birth?: string;\n issue_date?: string;\n expiry_date?: string;\n age?: number;\n\n // Details extracted from the secondary document, when one was required\n document_two_type?: string;\n document_two_number?: string;\n document_two_first_name?: string;\n document_two_middle_name?: string;\n document_two_last_name?: string;\n document_two_dob?: string;\n document_two_gender?: string;\n document_two_height?: string;\n document_two_country?: string;\n document_two_country_code?: string;\n document_two_nationality?: string;\n document_two_authority?: string;\n document_two_personal_number?: string;\n document_two_place_of_birth?: string;\n document_two_issue_date?: string;\n document_two_expiry_date?: string;\n\n // Verification Status Flags\n id_verified: boolean;\n address_verified: boolean;\n face_verified: boolean;\n age_verified: boolean;\n\n // Overall Status\n status: KycStatus;\n location?: string;\n identity_hash?: string;\n /** True when verification could not run because of an internal failure. */\n is_internal_error?: boolean;\n /** The `trigger_event` the submit link was requested with. */\n event?: string;\n\n // Preferences at time of submission\n required_document_count: number;\n supported_document_types?: SupportedDocumentType[];\n supported_address_document_types?: SupportedAddressDocumentType[];\n is_id_verification_required: boolean;\n is_face_verification_required: boolean;\n is_address_verification_required: boolean;\n is_age_verification_required: boolean;\n\n // URLs\n callback_url: string;\n redirect_url?: string;\n\n // Reasons & Warnings\n /** Structured decline reasons. Present when status is `declined`. */\n declined_reasons?: Reason[];\n /** Structured, non-blocking warnings. */\n warning_reasons?: Reason[];\n /** @deprecated Use {@link declined_reasons}. Comma-joined message text. */\n declined_reason?: string;\n /** @deprecated Use the `code` on {@link declined_reasons}. */\n declined_code?: KycDeclinedCode;\n accepted_reason?: string;\n other_reason?: string;\n /** @deprecated Use {@link warning_reasons}. */\n warnings?: Record<string, Record<string, string>>;\n\n // Block Action\n /**\n * Tenant app should block onboarding/the action when true. Set when a\n * failed verification matches a per-event KYC alert rule with the `block`\n * reaction; sticky once set (a later non-blocking update won't clear it).\n */\n block: boolean;\n /**\n * Names the configured verification that triggered the block (e.g.\n * `document_verification`, `face_verification`, `address_verification`,\n * `age_verification`). Empty when {@link block} is false.\n */\n block_reason?: string;\n\n // Relationships\n proofs?: Proof[];\n alerts?: KycAlert[];\n risk_profile?: KycCustomerProfile;\n\n created_at: string;\n updated_at: string;\n}\n\nexport interface Proof {\n id: string;\n kyc_id: string;\n type: ProofType;\n document: string;\n document_number?: string;\n created_at: string;\n}\n\nexport interface ProofDownloadURL {\n type: ProofType;\n url: string;\n expires_at: string;\n}\n\n// ============================================================================\n// KYC Customer Profile (Risk Profile Reference)\n// ============================================================================\n\nexport interface KycCustomerProfile {\n id: string;\n tenant_id: string;\n customer_id: string;\n first_name?: string;\n last_name?: string;\n email?: string;\n risk_score: number;\n risk_level: RiskLevel;\n kyc_status?: string;\n pep_status?: boolean;\n sanctions_status?: boolean;\n created_at: string;\n updated_at: string;\n}\n\n// ============================================================================\n// KYC Alert Types\n// ============================================================================\n\nexport interface KycAlert {\n id: string;\n kyc_id: string;\n tenant_id: string;\n alert_type: KycAlertType;\n alert_text: string;\n risk: RiskLevel;\n assigned_for?: string;\n reason?: string;\n status: KycAlertStatus;\n created_at: string;\n updated_at: string;\n}\n\nexport interface KycAlertFilters {\n kyc_id?: string | string[];\n alert_type?: KycAlertType | KycAlertType[];\n assigned_for?: string | string[];\n status?: KycAlertStatus | KycAlertStatus[];\n risk?: RiskLevel | RiskLevel[];\n search?: string;\n fromDate?: string;\n toDate?: string;\n sort_by?: string;\n order?: 'ASC' | 'DESC';\n}\n\nexport interface KycAlertListResponse {\n alerts: KycAlert[];\n pagination: KycPagination;\n}\n\nexport interface UpdateKycAlertRequest {\n assigned_for?: string;\n reason?: string;\n alert_type?: KycAlertType;\n status?: KycAlertStatus;\n}\n\n// ============================================================================\n// KYC Preferences Types\n// ============================================================================\n\n/**\n * Threshold-gated trigger for transaction events. Each rule is\n * self-contained — there is no umbrella flag.\n *\n * - `enabled=false` → event blocked.\n * - `enabled=true`, `threshold=0` (or null/omitted) → every event of this\n * type triggers Event-Based Face Verification, regardless of amount.\n * - `enabled=true`, `threshold>0` → only amounts `>= threshold` trigger.\n */\nexport interface EventBasedFaceVerificationThresholdTrigger {\n enabled: boolean;\n /** USD threshold; 0 / null / omitted means \"any amount\". */\n threshold: number;\n}\n\n/**\n * Rate-of-occurrence trigger (used by `high_frequency_betting`). The\n * tenant tells the server how many events have happened over how many\n * minutes via the request body (`event_count`, `event_window_minutes`);\n * the server triggers when `event_count >= count` AND\n * `event_window_minutes <= window_minutes`. Either bound of 0 means\n * \"don't enforce that bound\".\n */\nexport interface EventBasedFaceVerificationFrequencyTrigger {\n enabled: boolean;\n /** Minimum number of events; 0 / null / omitted means \"any count\". */\n count: number;\n /** Maximum lookback window in minutes; 0 / null / omitted means \"any window\". */\n window_minutes: number;\n}\n\n/** Events that can trigger Event-Based Face Verification for a tenant. */\nexport interface EventBasedFaceVerificationTriggers {\n // Account-sensitive events\n login: boolean;\n password_change: boolean;\n name_change: boolean;\n phone_number_change: boolean;\n two_factor_auth_change: boolean;\n new_device_or_location: boolean;\n device_fingerprint_change: boolean;\n payment_method_change: boolean;\n\n // Transaction events — each rule is self-contained; there is no\n // umbrella flag. To enable a transaction event, set its `enabled`\n // field to true (and configure the relevant threshold / count /\n // window). To disable, set `enabled` to false.\n deposit: EventBasedFaceVerificationThresholdTrigger;\n withdrawal: EventBasedFaceVerificationThresholdTrigger;\n large_bet_placement: EventBasedFaceVerificationThresholdTrigger;\n high_frequency_betting: EventBasedFaceVerificationFrequencyTrigger;\n account_balance_transfer: boolean;\n}\n\n/**\n * Retry budget for Event-Based Face Verification. This is the only field the\n * platform stores here; the reactions taken when the budget is exhausted\n * (`trigger_alert`, `enforce_logout`, `freeze_account`, `block`,\n * `freeze_duration_minutes`) come from the tenant's per-event KYC alert\n * configuration and are reported on\n * {@link EventBasedFaceVerificationReactionResult}.\n */\nexport interface EventBasedFaceVerificationReactions {\n /** Retries after the first attempt; total submissions = this + 1. */\n max_retry_attempts: number;\n /** @deprecated Never populated; read `data.trigger_alert` on the callback instead. */\n trigger_alert?: boolean;\n /** @deprecated Never populated; read `data.enforce_logout` on the callback instead. */\n enforce_logout?: boolean;\n /** @deprecated Never populated; read `data.freeze_account` on the callback instead. */\n freeze_account?: boolean;\n /** @deprecated Never populated; read `data.freeze_duration_minutes` on the callback instead. */\n freeze_duration_minutes?: number;\n}\n\n/** Per-event toggles that decide when a submit-link request requires KYC. */\nexport interface KycVerificationTriggers {\n onboarding: boolean;\n first_withdrawal: boolean;\n first_purchase: boolean;\n /** Re-trigger verification once the customer's identity document has expired. */\n auto_trigger_on_id_expiration: boolean;\n}\n\nexport interface KycSkipOptions {\n /** Let a `manual` trigger be skipped (`can_skip` on the submit-link response). */\n allow_skip_on_manual: boolean;\n}\n\n/** Tenant-defined reasons available to reviewers for a given resource. */\nexport interface KycOtherReason {\n resource: string;\n reasons: string[];\n}\n\n/** Disclosure text shown to the customer on the hosted submission page. */\nexport interface KycDisclosureConsent {\n data_collected: string[];\n data_usage: string[];\n data_sharing: {\n third_party_providers: boolean;\n regulatory_authorities: boolean;\n internal_systems: boolean;\n provider_names?: string[];\n };\n data_retention_period: string;\n customer_rights: {\n can_access: boolean;\n can_correct: boolean;\n can_delete: boolean;\n contact_info?: string;\n };\n}\n\nexport interface KycPreferences {\n id: string;\n tenant_id: string;\n approve_kyc_reasons: string[];\n other_reasons?: KycOtherReason[];\n is_document_verification_required: boolean;\n is_face_verification_required: boolean;\n is_address_verification_required: boolean;\n is_age_verification_required: boolean;\n is_duplicate_verification_required?: boolean;\n /** Master switch for the Event-Based Face Verification feature. */\n is_reuse_kyc_enabled?: boolean;\n min_age: number;\n max_age: number;\n required_document_count: number;\n critical_risk_score: number;\n high_risk_score: number;\n medium_risk_score: number;\n supported_document_types: SupportedDocumentType[];\n supported_address_document_types?: SupportedAddressDocumentType[];\n /** Tenant-level callback URL used when a submit-link request passes none. */\n callback_url?: string;\n address_fuzzy_match?: boolean;\n document_fuzzy_match?: boolean;\n document_translate?: boolean;\n decline_on_single_step?: boolean;\n allow_warnings?: boolean;\n backside_proof_required?: boolean;\n document_two_backside_proof_required?: boolean;\n verification_mode?: string;\n document_upload_option?: boolean;\n disclosure_consent?: KycDisclosureConsent;\n /** Per-event toggles for document verification (`requestKycSubmitLink`). */\n kyc_triggers?: KycVerificationTriggers;\n kyc_skip_options?: KycSkipOptions;\n /** Per-event triggers for Event-Based Face Verification. */\n reuse_kyc_triggers?: EventBasedFaceVerificationTriggers;\n /** Retry budget for Event-Based Face Verification. */\n reuse_kyc_reactions?: EventBasedFaceVerificationReactions;\n created_at: string;\n updated_at: string;\n}\n\n/**\n * @deprecated KYC preferences are managed in the Vesant console; the platform\n * exposes no update operation to the SDK, so `updatePreferences` always fails.\n * This type will be removed in a future release.\n */\nexport interface UpdateKycPreferencesRequest {\n reasons?: string[];\n is_document_verification_required?: boolean;\n is_face_verification_required?: boolean;\n is_address_verification_required?: boolean;\n is_age_verification_required?: boolean;\n is_reuse_kyc_enabled?: boolean;\n min_age?: number;\n max_age?: number;\n required_document_count?: number;\n critical_risk_score?: number;\n high_risk_score?: number;\n medium_risk_score?: number;\n supported_document_types?: SupportedDocumentType[];\n /** Partial update — only the events present here are changed. */\n reuse_kyc_triggers?: Partial<EventBasedFaceVerificationTriggers>;\n /** Partial update — only the keys present here are changed. */\n reuse_kyc_reactions?: Partial<EventBasedFaceVerificationReactions>;\n}\n\n// ============================================================================\n// Document Verification Request Types\n// ============================================================================\n\nexport interface Name {\n first_name?: string;\n middle_name?: string;\n last_name?: string;\n full_name?: string;\n}\n\nexport interface SubmittedDocument {\n /** Base64 encoded document image */\n proof: string;\n /** Base64 additional document image (back side, etc.) */\n additional_proof?: string;\n /** Document number for search/verification */\n document_number?: string;\n /** Document types to verify against */\n selected_type?: DocumentType[];\n /** Extracted/provided name */\n name?: Name;\n /** Date of birth (YYYY-MM-DD) */\n dob?: string;\n /** Issue date (YYYY-MM-DD) */\n issue_date?: string;\n /** Expiry date (YYYY-MM-DD) */\n expiry_date?: string;\n /** Gender */\n gender?: string;\n}\n\nexport interface FaceProof {\n /** Base64 encoded face image or selfie */\n proof: string;\n}\n\nexport interface DocumentVerificationRequest {\n /** Customer reference ID */\n reference: string;\n /** Callback URL for async verification results */\n callback_url: string;\n /** Customer email */\n email: string;\n /** Country code (ISO 3166-1 alpha-2) */\n country: string;\n /** Language code */\n language: string;\n /** Full address for verification */\n full_address?: string;\n /** Base64 encoded address proof document */\n address_proof?: string;\n /** Primary document */\n document: SubmittedDocument;\n /** Secondary document (optional) */\n document_two?: SubmittedDocument;\n /** Face verification proof (optional) */\n face?: FaceProof;\n /** Additional metadata */\n token?: string;\n}\n\nexport interface DocumentVerificationResponse {\n id: string;\n reference: string;\n status: KycStatus;\n verification_url?: string;\n message?: string;\n}\n\n// ============================================================================\n// KYC Status Update Types\n// ============================================================================\n\nexport interface UpdateKycStatusRequest {\n /** Provider reference or KYC ID */\n reference: string;\n /** Target status */\n status: KycStatus;\n /** Acceptance/decline reason */\n reason?: string;\n /** Provider warnings data */\n warnings?: Record<string, Record<string, string>>;\n}\n\n// ============================================================================\n// KYC Submit Link Request Types\n// ============================================================================\n\n/**\n * Events that can trigger a KYC request. Each maps to a per-event toggle in\n * the tenant's KYC verification trigger preferences, except `manual` (always\n * required) and `login` (only for an expired identity document).\n */\nexport type KycTriggerEvent =\n | 'onboarding'\n | 'first_withdrawal'\n | 'first_purchase'\n /** Aliases of `first_withdrawal` / `first_purchase` — same tenant toggles. */\n | 'withdrawal'\n | 'purchase'\n | 'manual'\n /**\n * The customer is signing in. Answers for any state: never verified (asked,\n * not skippable, per the tenant's onboarding policy), document expired\n * (asked, skippable — \"Remind me later\"), or verified with a valid document\n * (not asked). One call covers every customer.\n */\n | 'login';\n\n/**\n * Why verification is — or is not — being asked for. Codes are stable;\n * `message` is display-ready text you can show the customer as-is.\n */\nexport interface KycRequestReason {\n code: KycRequestReasonCode | (string & Record<string, never>);\n message: string;\n}\n\n/**\n * Reason codes returned by `requestKycSubmitLink`. Treat unrecognised codes\n * as \"verification required\" and fall back to `message` for display.\n */\nexport type KycRequestReasonCode =\n /** Required to complete registration. */\n | 'KYC_REQUIRED_ONBOARDING'\n /** Required before the customer's first withdrawal. */\n | 'KYC_REQUIRED_FIRST_WITHDRAWAL'\n /** Required before the customer's first purchase. */\n | 'KYC_REQUIRED_FIRST_PURCHASE'\n /** The customer's identity document has expired and must be re-verified. */\n | 'KYC_REQUIRED_ID_EXPIRED'\n /** Verification was explicitly requested by the tenant. */\n | 'KYC_REQUIRED_MANUAL'\n /** Not required — the customer already has an accepted verification. */\n | 'KYC_NOT_REQUIRED_ALREADY_VERIFIED'\n /** Not required — the tenant has this trigger event switched off. */\n | 'KYC_NOT_REQUIRED_TRIGGER_DISABLED';\n\nexport interface RequestKycSubmitLinkRequest {\n /** User ID to generate KYC submission link for */\n user_id: string;\n /** URL to redirect user after KYC submission (optional) */\n redirect_url?: string;\n /** URL to receive callback notifications via POST request when KYC status changes (optional) */\n callback_url?: string;\n /**\n * Event that triggered the KYC request. The tenant's KYC verification\n * trigger preferences decide, per event, whether KYC is required\n * (`kyc_required` in the response). \"manual\" always requires KYC and\n * honors the tenant's allow-skip-on-manual option (`can_skip`). \"login\"\n * answers for any customer state — never verified (asked, not skippable),\n * document expired (asked, skippable so you can offer \"Remind me later\"),\n * or verified and valid (not asked) — so a platform that gates entry on KYC\n * needs only this one call at sign-in. The same expired document is *not*\n * skippable on withdrawal / purchase events: it is enforced on\n * \"first_withdrawal\", \"withdrawal\", \"first_purchase\" and \"purchase\" alike,\n * so keep sending whichever of those you already send.\n * Omitted or unknown values default to KYC required with no skip.\n */\n trigger_event?: KycTriggerEvent | (string & Record<string, never>);\n /**\n * Registered customer identity data (optional). Seeds the customer's risk\n * profile so document verification can cross-check the submitted document\n * against trusted reference data (name/DOB match, address verification).\n * Fields never overwrite data already on the profile.\n */\n customer_data?: KycCustomerData;\n}\n\n/**\n * Customer identity data supplied by your platform on a submit-link request.\n * Mirrors the geolocation `customer_data` contract. Every field is optional\n * and never overwrites data already on the customer's risk profile.\n */\nexport interface KycCustomerData {\n /**\n * Customer's registered full name. Used to match the OCR-extracted name\n * on the submitted document.\n */\n full_name?: string;\n /**\n * Customer's registered date of birth. ISO 8601 date (\"1999-06-02\") or an\n * RFC 3339 timestamp (\"1986-09-06T18:30:00.000+00:00\", as produced by\n * `Date.prototype.toISOString()`) — for timestamps the date portion is\n * used. Used for DOB matching against the submitted document.\n */\n date_of_birth?: string;\n /** Customer's email address */\n email?: string;\n /** Customer's phone number */\n phone?: string;\n /** Customer's residential address. Used for address verification. */\n address?: string;\n /** Customer's country of residence */\n country?: string;\n}\n\n/**\n * Trigger events that can request Event-Based Face Verification.\n *\n * Account-sensitive: any sensitive change to the account profile.\n * Transaction events: covered by the per-event rules in\n * `EventBasedFaceVerificationTriggers` (`deposit`, `withdrawal`, `large_bet_placement`,\n * `high_frequency_betting`, `account_balance_transfer`).\n */\nexport type EventBasedFaceVerificationEvent =\n | 'login'\n | 'password_change'\n | 'name_change'\n | 'phone_number_change'\n | 'two_factor_auth_change'\n | 'new_device_or_location'\n | 'device_fingerprint_change'\n | 'payment_method_change'\n | 'deposit'\n | 'withdrawal'\n | 'large_bet_placement'\n | 'high_frequency_betting'\n | 'account_balance_transfer';\n\nexport interface CreateEventBasedFaceVerificationSessionRequest {\n /** Unique reference for the KYC session (e.g., customer ID or transaction ID) */\n reference: string;\n /** Customer ID to associate with the KYC session */\n customer_id: string;\n /**\n * The triggering event. One of the `EventBasedFaceVerificationEvent` union members.\n * Required — when empty, the server falls through to the unknown-event\n * passthrough and allows the request silently.\n */\n event: EventBasedFaceVerificationEvent;\n /**\n * USD amount associated with the event. Required for threshold-gated\n * events (`deposit`, `withdrawal`, `large_bet_placement`); ignored for\n * everything else. Missing/zero with a non-zero threshold blocks the\n * session.\n */\n amount?: number;\n /**\n * Number of qualifying events the customer has performed in the\n * window described by `event_window_minutes`. Required for\n * frequency-gated events (`high_frequency_betting`); ignored for\n * everything else.\n */\n event_count?: number;\n /**\n * Lookback window (in minutes) the tenant counted `event_count` over.\n * Required for frequency-gated events alongside `event_count`. A\n * window larger than the tenant's configured `window_minutes`\n * implies a slower rate than \"high frequency\" and blocks the session.\n */\n event_window_minutes?: number;\n /** URL to redirect user after validate the facial submission (optional) */\n redirect_url?: string;\n /** URL to receive callback notifications via POST request when Event-Based Face Verification status changes (optional) */\n callback_url?: string;\n}\n\nexport interface SubmitEventBasedFaceVerificationSessionRequest {\n /** Event-Based Face Verification session token generated from createEventBasedFaceVerificationSession */\n token: string;\n /** Base64 encoded face image or selfie for verification */\n proof: string;\n /** Unique reference for the KYC session (e.g., customer ID or transaction ID) */\n reference?: string;\n /**\n * Optional capture telemetry (JSON string): the face-detection\n * bounding-box samples recorded in the moments before capture. Attached\n * automatically by `FaceCaptureModal` when in-modal detection is active;\n * omit when building a custom capture UI without detection. Stored\n * verbatim server-side for audit/review — a weak presence signal, not\n * certified anti-spoofing.\n */\n liveness_artifact?: string;\n}\n\nexport interface RequestKycSubmitLinkResponse {\n /** Generated KYC submission redirect URL */\n link: string;\n /** KYC request ID */\n kyc_id: string;\n /**\n * Whether KYC is required for the reported `trigger_event`, per the\n * tenant's verification trigger preferences. `false` when the trigger\n * is disabled for the tenant, or when the customer is already verified\n * (in that case `link` and `kyc_id` are empty).\n */\n kyc_required: boolean;\n /**\n * Whether the user may skip verification. `true` for\n * `trigger_event: \"manual\"` when the tenant enables allow-skip-on-manual,\n * for `\"login\"` when an expired identity document triggered the request\n * (offer \"Remind me later\"), and when the customer is already verified.\n * Always `false` at `\"withdrawal\"` / `\"purchase\"` — that is where a\n * postponed re-verification becomes mandatory.\n */\n can_skip: boolean;\n /**\n * Why verification is — or is not — being asked for. Use `reason.code` to\n * branch (for example `KYC_REQUIRED_ID_EXPIRED` warrants a different prompt\n * than a first-time verification) and `reason.message` for display.\n */\n reason?: KycRequestReason;\n}\n\n/**\n * Body POSTed to your `callback_url` when a customer's identity document\n * passes its expiry date. Signed with `X-Webhook-Signature: sha256=<hex>`\n * (HMAC-SHA256 of the raw body), like every other Vesant callback.\n *\n * An expiry happens on a **date**, not on a customer action, so this webhook\n * is the only signal for it — nothing the customer does triggers it. Delivered\n * once per customer, when the document first becomes expired.\n *\n * It is sent regardless of the tenant's auto-trigger-on-ID-expiration setting:\n * that setting governs whether verification is *enforced*, not whether you are\n * *told*.\n */\nexport interface KycDocumentExpiredCallbackEvent {\n /** Always `\"kyc_document_expired\"` — dispatch on this. */\n event: 'kyc_document_expired';\n /** Your customer identifier (the `user_id` you supplied). */\n reference: string;\n /** The customer's risk-profile ID. */\n resource_id: string;\n /**\n * Always `\"expired\"`. Describes the document — not the customer's KYC\n * status, which remains `accepted` until they re-verify.\n */\n status: 'expired';\n data: {\n customer_id: string;\n /** The document's expiry date (ISO 8601 `YYYY-MM-DD`). */\n id_expiry_date: string;\n };\n}\n\n/**\n * Type guard for the identity-document expiry webhook. Narrows an already\n * signature-verified, parsed payload to {@link KycDocumentExpiredCallbackEvent}.\n */\nexport function isKycDocumentExpiredCallbackEvent(\n value: unknown\n): value is KycDocumentExpiredCallbackEvent {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { event?: unknown }).event === 'kyc_document_expired'\n );\n}\n\n/** Device class detected by the SDK (purely client-side — server doesn't care). */\nexport type EventBasedFaceVerificationDeviceType = 'mobile' | 'desktop';\n\nexport interface CreateEventBasedFaceVerificationSessionResponse {\n /** Event-Based Face Verification session reference (echo of the request reference) */\n reference: string;\n /** Generated Event-Based Face Verification session token, valid 10 minutes */\n token: string;\n /**\n * Empty string when Event-Based Face Verification is required. When `is_required` is\n * false, this contains the human-readable reason (e.g. feature\n * disabled, threshold not met, customer has no prior KYC).\n */\n reason: string;\n /** Whether the caller must complete the face capture before proceeding */\n is_required: boolean;\n /**\n * Public HTTPS handoff URL the SDK encodes into a QR code on desktop.\n * The mobile device scans it, lands on the tenant frontend's\n * /reuse-kyc-submit page, and completes the face capture there. Empty\n * when the server has no `BASE_URL_FRONTEND` configured — the SDK\n * falls back to building its own URL in that case.\n */\n link: string;\n /** Failed face-capture attempts so far on this session. 0 on a fresh session. */\n attempts: number;\n /**\n * Total submissions permitted before reactions fire\n * (`reuse_kyc_reactions.max_retry_attempts + 1`).\n */\n max_attempts: number;\n /**\n * Hosted verification journey URL. When present, the capture runs on a\n * hosted page (embedded by `FaceCaptureModal` in an iframe) instead of the\n * SDK's local camera; the verdict is read via the session status poll.\n * Absent when the platform runs the local-capture flow.\n */\n verification_url?: string;\n}\n\n/**\n * Reaction outcome returned on every face-submit callback. Tenant apps\n * use this to decide whether to allow another retry, end the session,\n * or freeze the account. Reaction flags are only populated when\n * `retry_limit_exceeded` is true.\n */\nexport interface EventBasedFaceVerificationReactionResult {\n /** Submissions the customer still has before the retry limit fires. */\n retries_remaining: number;\n /** True once the latest failed attempt exhausts the retry policy. */\n retry_limit_exceeded: boolean;\n trigger_alert: boolean;\n enforce_logout: boolean;\n freeze_account: boolean;\n /** Tenant app should block the action/account when true. */\n block: boolean;\n freeze_duration_minutes: number;\n /** Set when an alert was raised on the dashboard. */\n alert_id?: string;\n}\n\n/**\n * Shape of the webhook body POSTed to `callback_url` after a Event-Based Face Verification\n * submission completes (also returned synchronously from\n * `submitEventBasedFaceVerificationSession`).\n */\nexport interface EventBasedFaceVerificationCallback {\n event: 'reuse_kyc';\n reference: string;\n resource_id: string;\n status: KycStatus;\n /**\n * True when the tenant app should block the action/account. Mirrors the\n * `block` reaction on {@link data} at the top level of the callback so\n * consumers can branch without inspecting `data`. Omitted when false.\n */\n block?: boolean;\n /** Names the event/verification that triggered the block. Omitted when not blocked. */\n block_reason?: string;\n /**\n * Structured decline reasons. Returned by\n * `getEventBasedFaceVerificationSessionStatus`; the submit response and the\n * webhook carry {@link declined_reason} only.\n */\n declined_reasons?: Reason[];\n /** Decline text. Present on the submit response, the webhook, and status lookups. */\n declined_reason?: string;\n /** @deprecated Use structured reasons. */\n warnings?: Record<string, Record<string, string>>;\n data: EventBasedFaceVerificationReactionResult;\n}\n\n/**\n * Server-side handoff state backed by the normal KYC Redis store (15-minute\n * cache TTL). Event-Based Face Verification remains valid for 10 minutes;\n * this cache does not extend that session. Desktop clients poll it to detect\n * when a mobile device has attached to the same token via QR.\n */\nexport interface KycHandoffSession {\n document: string;\n document_backside: string;\n document_two: string;\n document_two_backside: string;\n address: string;\n face: string;\n /** True after a mobile device hits PUT /api/v1/kyc/session/connect. */\n mobile_connected: boolean;\n /** True after the (normal-KYC) document submission completes; unused for Event-Based Face Verification. */\n is_submitted: boolean;\n}\n\n// ============================================================================\n// KYC Status Check Types\n// ============================================================================\n\nexport interface CheckKycStatusRequest {\n /** Customer identifier. Sent for context only — the lookup is by kyc_id. */\n user_id: string;\n /** The KYC request ID returned by requestKycSubmitLink; drives the status lookup. */\n kyc_id: string;\n}\n\n/**\n * Response from checkKycStatus. Always returns the same shape.\n *\n * `additional_data` is absent or `null` while `status` is `'awaiting_kyc'` or\n * `'pending'` — the key is omitted on a newly created record, so guard with a\n * truthiness check (`if (result.additional_data)`), never `!== null`.\n * Otherwise it contains the full KYC record including document details,\n * proofs, and the customer's risk profile.\n *\n * `status === 'awaiting_kyc'` means the submit link was issued but the\n * customer has not submitted documents — treat it as \"not started\", never as\n * \"in progress\". Check `link_expired`: `false` → re-surface the existing\n * link; `true` → request a fresh one via `requestKycSubmitLink`.\n */\nexport interface CheckKycStatusResponse {\n id: string;\n forward_reference: string;\n status: KycStatus;\n id_verified: boolean;\n address_verified: boolean;\n face_verified: boolean;\n age_verified: boolean;\n /**\n * Structured decline reasons. The platform currently returns these only on\n * the full record: read `additional_data.declined_reasons` and fall back to\n * {@link declined_reason}. This top-level field is reserved and not populated.\n */\n declined_reasons?: Reason[];\n /**\n * Structured, non-blocking warnings. Currently returned only as\n * `additional_data.warning_reasons`; this top-level field is not populated.\n */\n warning_reasons?: Reason[];\n /** Comma-joined decline text. Always present on a declined response. */\n declined_reason?: string;\n /** Legacy decline code; prefer the `code` on `additional_data.declined_reasons`. */\n declined_code?: KycDeclinedCode;\n other_reason?: string;\n accepted_reason?: string;\n /** Legacy warning map; prefer `additional_data.warning_reasons`. */\n warnings?: Record<string, Record<string, string>>;\n required_document_count: number;\n supported_document_types?: SupportedDocumentType[];\n supported_address_document_types?: SupportedAddressDocumentType[];\n is_id_verification_required: boolean;\n is_face_verification_required: boolean;\n is_address_verification_required: boolean;\n is_age_verification_required: boolean;\n created_at: string;\n /**\n * Full KYC record with document details, proofs, and risk profile. Absent or\n * `null` while status is 'awaiting_kyc' or 'pending': the key is omitted on\n * a newly created record, so check truthiness rather than comparing to null.\n */\n additional_data?: KycRequest | null;\n /** Present when status is 'awaiting_kyc': whether the submit link has expired (request a new one when true). */\n link_expired?: boolean;\n /** Present when status is 'awaiting_kyc': the submit link's expiry time (RFC 3339). */\n link_expires_at?: string;\n}\n\nexport interface RequestAdditionalDocumentsRequest {\n /** KYC request ID */\n id: string;\n /** Document types to request */\n document_types: ProofType[];\n /** Message to customer */\n message?: string;\n}\n\n// ============================================================================\n// KYC Overview & Statistics Types\n// ============================================================================\n\nexport interface KycOverview {\n total: number;\n pending: number;\n approved: number;\n high_risk: number;\n rejected: number;\n id_verified: number;\n address_verified: number;\n face_verified: number;\n rejections: number;\n total_alerts: number;\n pending_alerts: number;\n resolved_alerts: number;\n}\n\n// ============================================================================\n// KYC Request Listing Types\n// ============================================================================\n\nexport interface KycRequestFilters {\n status?: KycStatus | KycStatus[];\n search?: string;\n fromDate?: string;\n toDate?: string;\n sortBy?: string;\n order?: 'ASC' | 'DESC';\n}\n\nexport interface KycPagination {\n limit: number;\n page: number;\n total: number;\n totalPages: number;\n}\n\nexport interface KycRequestListResponse {\n data: KycRequest[];\n pagination: KycPagination;\n}\n\n// ============================================================================\n// Customer Profile Types (Re-exported from risk-profile module)\n// ============================================================================\n\n// Import types from risk-profile module for use in KYC client\nimport type {\n CustomerProfile as RiskProfileCustomerProfile,\n CreateProfileRequest,\n ProfileFilters,\n ProfileListResponse,\n} from '../risk-profile/types';\n\n// Export types for internal use in KYC client (aliased to avoid conflicts with main exports)\n// Users should import CustomerProfile, CreateProfileRequest, etc. from 'vesant-sdk/risk-profile'\nexport type {\n RiskProfileCustomerProfile as CustomerProfile,\n CreateProfileRequest as CreateCustomerProfileRequest,\n ProfileFilters as CustomerProfileFilters,\n ProfileListResponse as CustomerProfileListResponse,\n};\n\n// ============================================================================\n// SDK Configuration Types\n// ============================================================================\n\nexport interface KycClientConfig {\n /** Base URL of the KYC Service API (e.g., \"http://localhost:8088\") */\n baseURL: string;\n\n /** Base URL of the Customer Risk Profile Service API (e.g., \"http://localhost:8094\") */\n riskProfileBaseURL?: string;\n\n /** Tenant ID for multi-tenancy */\n tenantId: string;\n\n /** API key or JWT token for authentication */\n apiKey?: string;\n\n /** User ID for operations requiring user context */\n userId?: string;\n\n /** Custom headers to include in every request */\n headers?: Record<string, string>;\n\n /** Request timeout in milliseconds (default: 10000) */\n timeout?: number;\n\n /** Enable debug logging */\n debug?: boolean;\n\n /** Environment mode - 'sandbox' uses isolated sandbox data */\n environment?: 'production' | 'sandbox';\n}\n\n// ============================================================================\n// React Hook Types\n// ============================================================================\n\n/** Base hook state with loading and error */\ninterface BaseHookState {\n loading: boolean;\n error: Error | null;\n}\n\n/** Base options for hooks with auto-fetch capability */\ninterface BaseAutoFetchOptions {\n autoFetch?: boolean;\n}\n\n/** Base options for hooks with polling capability */\ninterface BasePollOptions extends BaseAutoFetchOptions {\n pollInterval?: number;\n}\n\n/** Base options for list hooks with filters and pagination */\ninterface BaseListOptions<TFilters> extends BasePollOptions {\n filters?: TFilters;\n pagination?: PaginationParams;\n}\n\nexport interface UseKycSubmissionOptions {\n onComplete?: (result: DocumentVerificationResponse) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UseKycSubmissionResult extends BaseHookState {\n submit: (request: DocumentVerificationRequest) => Promise<DocumentVerificationResponse>;\n submission: DocumentVerificationResponse | null;\n reset: () => void;\n}\n\nexport type UseKycRequestsOptions = BaseListOptions<KycRequestFilters>;\n\nexport interface UseKycRequestsResult extends BaseHookState {\n requests: KycRequest[];\n pagination: KycPagination | null;\n fetchRequests: (filters?: KycRequestFilters, pagination?: PaginationParams) => Promise<void>;\n getRequest: (id: string) => Promise<KycRequest>;\n updateStatus: (reference: string, status: KycStatus, reason?: string) => Promise<void>;\n refresh: () => Promise<void>;\n}\n\nexport type UseKycAlertsOptions = BaseListOptions<KycAlertFilters>;\n\nexport interface UseKycAlertsResult extends BaseHookState {\n alerts: KycAlert[];\n pagination: KycPagination | null;\n fetchAlerts: (filters?: KycAlertFilters, pagination?: PaginationParams) => Promise<void>;\n getAlert: (id: string) => Promise<KycAlert>;\n updateAlert: (id: string, update: UpdateKycAlertRequest) => Promise<void>;\n refresh: () => Promise<void>;\n}\n\nexport interface UseKycOverviewOptions extends BaseAutoFetchOptions {\n fromDate?: string;\n toDate?: string;\n}\n\nexport interface UseKycOverviewResult extends BaseHookState {\n overview: KycOverview | null;\n refresh: (fromDate?: string, toDate?: string) => Promise<void>;\n}\n\nexport interface UseKycPreferencesResult extends BaseHookState {\n preferences: KycPreferences | null;\n /** @deprecated The platform exposes no preference-update operation; this call always fails. */\n updatePreferences: (update: UpdateKycPreferencesRequest) => Promise<void>;\n refresh: () => Promise<void>;\n}\n","import { BaseClient } from '../core/client';\nimport type { BaseClientConfig, RequestOptions } from '../core/config';\nimport type {\n TaxClientConfig,\n CustomerTaxProfileRecord,\n CustomerTaxProfileDocuments,\n ReRequestTaxFormInput,\n EnableWithholdingInput,\n EnableWithholdingResponse,\n TINCheckResult,\n TaxRules,\n UpdateTaxRulesInput,\n TaxRuleVersion,\n RemindersRunResult,\n ComplianceStats,\n ComplianceStatsFilters,\n GlobalTaxRule,\n TreatyCountry,\n TreatyCountryListResponse,\n} from './types';\n\nexport class TaxClient extends BaseClient {\n constructor(config: TaxClientConfig) {\n const baseConfig: BaseClientConfig = {\n baseURL: config.baseURL,\n tenantId: config.tenantId,\n apiKey: config.apiKey,\n headers: config.headers,\n timeout: config.timeout,\n retries: 3,\n debug: config.debug,\n environment: config.environment,\n };\n super(baseConfig);\n }\n\n // ==========================================================================\n // P1 — Customer Tax Profile (core compliance flow)\n // ==========================================================================\n\n async getCustomerTaxProfileRecord(customerID: string): Promise<CustomerTaxProfileRecord> {\n return this.request<CustomerTaxProfileRecord>(\n `/api/v1/tax/customer-tax-profiles/${customerID}`\n );\n }\n\n async requestTaxForm(customerID: string): Promise<CustomerTaxProfileRecord> {\n return this.request<CustomerTaxProfileRecord>(\n `/api/v1/tax/customer-tax-profiles/${customerID}/request-form`,\n { method: 'POST' }\n );\n }\n\n async checkTINStatus(customerID: string, requestOptions?: RequestOptions): Promise<TINCheckResult> {\n return this.requestWithRetry<TINCheckResult>(\n `/api/v1/tax/customer-tax-profiles/${customerID}/check-tin`,\n { method: 'POST' },\n undefined,\n undefined,\n requestOptions\n );\n }\n\n async reRequestTaxForm(\n customerID: string,\n input: ReRequestTaxFormInput\n ): Promise<CustomerTaxProfileRecord> {\n return this.request<CustomerTaxProfileRecord>(\n `/api/v1/tax/customer-tax-profiles/${customerID}/re-request-form`,\n {\n method: 'POST',\n body: JSON.stringify(input),\n }\n );\n }\n\n async enableBackupWithholding(\n customerID: string,\n input: EnableWithholdingInput\n ): Promise<EnableWithholdingResponse> {\n return this.request<EnableWithholdingResponse>(\n `/api/v1/tax/customer-tax-profiles/${customerID}/enable-withholding`,\n {\n method: 'POST',\n body: JSON.stringify(input),\n }\n );\n }\n\n async getCustomerDocuments(customerID: string): Promise<CustomerTaxProfileDocuments> {\n return this.request<CustomerTaxProfileDocuments>(\n `/api/v1/tm/customer-tax-profiles/${customerID}/documents`\n );\n }\n\n async downloadTaxForm(\n customerID: string,\n requestOptions?: RequestOptions\n ): Promise<ArrayBuffer> {\n return this.request<ArrayBuffer>(\n `/api/v1/tax/customer-tax-profiles/${customerID}/download-form`,\n { method: 'GET' },\n undefined,\n { ...requestOptions, responseType: 'arraybuffer' }\n );\n }\n\n // ==========================================================================\n // P2 — Tenant Tax Rules\n // ==========================================================================\n\n async getTaxRules(): Promise<TaxRules> {\n const res = await this.request<{ rules: TaxRules }>('/api/v1/tax/rules');\n return res.rules;\n }\n\n async updateTaxRules(input: UpdateTaxRulesInput): Promise<TaxRuleVersion> {\n const res = await this.request<{ version: TaxRuleVersion }>('/api/v1/tax/rules', {\n method: 'PUT',\n body: JSON.stringify({ rules: input }),\n });\n return res.version;\n }\n\n async runReminders(): Promise<RemindersRunResult> {\n return this.request<RemindersRunResult>('/api/v1/tax/reminders/run', { method: 'POST' });\n }\n\n async getComplianceStats(filters?: ComplianceStatsFilters): Promise<ComplianceStats> {\n const params: Record<string, unknown> = {};\n if (filters?.time_range) params.time_range = filters.time_range;\n if (filters?.from_date) params.from_date = filters.from_date;\n if (filters?.to_date) params.to_date = filters.to_date;\n return this.request<ComplianceStats>(\n `/api/v1/tax/tenant/w-form-tenant-stats${this.buildQueryString(params)}`\n );\n }\n\n // ==========================================================================\n // P3 — Global Tax Rule & Treaty Countries\n // ==========================================================================\n\n async getCurrentGlobalTaxRule(): Promise<GlobalTaxRule> {\n const res = await this.request<{ success: boolean; message: string; data: GlobalTaxRule }>(\n '/api/v1/tm/tenant/global-tax-rules/current'\n );\n return res.data;\n }\n\n async listTreatyCountries(): Promise<TreatyCountryListResponse> {\n return this.request<TreatyCountryListResponse>('/api/v1/tax/treaty-countries');\n }\n\n async getTreatyCountry(code: string): Promise<TreatyCountry> {\n const res = await this.request<{ treaty_country: TreatyCountry }>(\n `/api/v1/tax/treaty-countries/${encodeURIComponent(code)}`\n );\n return res.treaty_country;\n }\n}\n","/**\n * Webhook event handler with signature verification and typed dispatch.\n */\n\nimport { verifyWebhookSignature } from '../core/webhook-utils';\nimport { ValidationError } from '../core/errors';\nimport { InMemoryDedupStore, type WebhookDedupStore } from '../core';\nimport type {\n WebhookEvent,\n WebhookEventType,\n WebhookEventHandler,\n WebhookAnyHandler,\n WebhookHandlerConfig,\n} from './types';\n\n/** Resolve the event id: the top-level `id`, or `notification.id` for the notification envelope. */\nfunction resolveEventId(event: WebhookEvent): string | undefined {\n if (event.id) {\n return event.id;\n }\n if (event.event_type === 'notification.created') {\n return event.notification?.id;\n }\n return undefined;\n}\n\nexport class WebhookHandler {\n private handlers = new Map<WebhookEventType, WebhookEventHandler[]>();\n private anyHandlers: WebhookAnyHandler[] = [];\n private readonly secret: string;\n private readonly tolerance: number;\n private readonly replayProtection: boolean;\n private readonly allowLegacySignature: boolean;\n private readonly dedupStore: WebhookDedupStore;\n\n constructor(config: WebhookHandlerConfig) {\n this.secret = config.secret;\n this.tolerance = config.tolerance ?? 300000; // 5 minutes\n this.replayProtection = config.replayProtection ?? true;\n this.allowLegacySignature = config.allowLegacySignature ?? true;\n this.dedupStore = config.dedupStore ?? new InMemoryDedupStore();\n }\n\n /**\n * Register a handler for a specific event type.\n */\n on<T extends WebhookEventType>(\n eventType: T,\n handler: WebhookEventHandler<T>\n ): this {\n const existing = this.handlers.get(eventType) || [];\n existing.push(handler as unknown as WebhookEventHandler);\n this.handlers.set(eventType, existing);\n return this;\n }\n\n /**\n * Register a catch-all handler for all event types.\n */\n onAny(handler: WebhookAnyHandler): this {\n this.anyHandlers.push(handler);\n return this;\n }\n\n /**\n * Verify signature and parse the webhook body.\n */\n async verifyAndParse(body: string, signature: string): Promise<WebhookEvent> {\n const isValid = await verifyWebhookSignature(body, signature, this.secret, {\n tolerance: this.tolerance,\n allowLegacy: this.allowLegacySignature,\n });\n if (!isValid) {\n throw new ValidationError('Invalid webhook signature', ['signature']);\n }\n\n return this.parseAndValidate(body);\n }\n\n /**\n * Verify signature, parse, and dispatch to registered handlers.\n */\n async handle(body: string, signature: string): Promise<void> {\n const event = await this.verifyAndParse(body, signature);\n await this.dispatch(event);\n }\n\n /**\n * Parse an event without signature verification (for testing).\n */\n async parseEvent(body: string): Promise<WebhookEvent> {\n return this.parseAndValidate(body);\n }\n\n private async parseAndValidate(body: string): Promise<WebhookEvent> {\n const event = JSON.parse(body) as WebhookEvent;\n const eventId = resolveEventId(event);\n\n if (!event.event_type || !eventId || !event.timestamp) {\n throw new ValidationError(\n 'Invalid webhook event: missing required fields (event_type, id, timestamp)',\n ['event_type', 'id', 'timestamp']\n );\n }\n\n // Timestamp tolerance check (defense in depth; the signed-timestamp scheme\n // also authenticates the timestamp in verifyWebhookSignature).\n if (this.tolerance > 0) {\n const eventTime = new Date(event.timestamp).getTime();\n if (Math.abs(Date.now() - eventTime) > this.tolerance) {\n throw new ValidationError(\n `Webhook event timestamp is outside tolerance window (${this.tolerance}ms)`,\n ['timestamp']\n );\n }\n }\n\n // Replay protection via the (pluggable) dedup store.\n if (this.replayProtection) {\n if (await this.dedupStore.seen(eventId)) {\n throw new ValidationError(\n `Duplicate webhook event: ${eventId} has already been processed`,\n ['id']\n );\n }\n await this.dedupStore.mark(eventId, this.tolerance);\n }\n\n return event;\n }\n\n private async dispatch(event: WebhookEvent): Promise<void> {\n const typeHandlers = this.handlers.get(event.event_type) || [];\n const allHandlers = [...typeHandlers, ...this.anyHandlers];\n\n for (const handler of allHandlers) {\n await (handler as WebhookAnyHandler)(event);\n }\n }\n}\n","/**\n * Framework middleware helpers for webhook handling.\n *\n * Provides pre-built integrations for Express/Connect and Next.js App Router.\n */\n\nimport { WebhookHandler } from './handler';\nimport type { WebhookHandlerConfig, WebhookEventType, WebhookEventHandler, WebhookAnyHandler } from './types';\n\nexport interface WebhookMiddlewareOptions extends WebhookHandlerConfig {\n /** Event handlers to register */\n handlers?: Partial<Record<WebhookEventType, WebhookEventHandler>>;\n /** Catch-all handler */\n onAny?: WebhookAnyHandler;\n}\n\n/**\n * Create an Express/Connect-compatible middleware for webhook handling.\n *\n * Expects the raw body to be available as `req.body` (string).\n * Use `express.raw({ type: 'application/json' })` or similar middleware upstream.\n */\nexport function createWebhookMiddleware(options: WebhookMiddlewareOptions) {\n const handler = buildHandler(options);\n const signatureHeader = options.signatureHeader || 'x-webhook-signature';\n\n return async (\n req: { body: string | Buffer; headers: Record<string, string | string[] | undefined> },\n res: { status(code: number): { json(body: unknown): void }; json?(body: unknown): void },\n next?: (err?: unknown) => void\n ) => {\n try {\n const body = typeof req.body === 'string' ? req.body : req.body.toString('utf-8');\n const signature = req.headers[signatureHeader];\n\n if (!signature || typeof signature !== 'string') {\n res.status(401).json({ error: 'Missing webhook signature' });\n return;\n }\n\n await handler.handle(body, signature);\n res.status(200).json({ received: true });\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Webhook processing failed';\n\n if (message.includes('signature')) {\n res.status(401).json({ error: message });\n } else if (message.includes('tolerance') || message.includes('timestamp')) {\n res.status(400).json({ error: message });\n } else if (message.includes('Duplicate')) {\n res.status(409).json({ error: message });\n } else if (next) {\n next(error);\n } else {\n res.status(500).json({ error: message });\n }\n }\n };\n}\n\n/**\n * Create a Next.js App Router-compatible webhook handler.\n *\n * Returns an async function `(request: Request) => Promise<Response>`.\n */\nexport function createNextWebhookHandler(\n options: WebhookMiddlewareOptions\n): (request: Request) => Promise<Response> {\n const handler = buildHandler(options);\n const signatureHeader = options.signatureHeader || 'x-webhook-signature';\n\n return async (request: Request): Promise<Response> => {\n try {\n const body = await request.text();\n const signature = request.headers.get(signatureHeader);\n\n if (!signature) {\n return new Response(JSON.stringify({ error: 'Missing webhook signature' }), {\n status: 401,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n await handler.handle(body, signature);\n\n return new Response(JSON.stringify({ received: true }), {\n status: 200,\n headers: { 'Content-Type': 'application/json' },\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Webhook processing failed';\n const status = message.includes('signature')\n ? 401\n : message.includes('tolerance') || message.includes('timestamp')\n ? 400\n : message.includes('Duplicate')\n ? 409\n : 500;\n\n return new Response(JSON.stringify({ error: message }), {\n status,\n headers: { 'Content-Type': 'application/json' },\n });\n }\n };\n}\n\nfunction buildHandler(options: WebhookMiddlewareOptions): WebhookHandler {\n const handler = new WebhookHandler(options);\n\n if (options.handlers) {\n for (const [eventType, eventHandler] of Object.entries(options.handlers)) {\n if (eventHandler) {\n handler.on(eventType as WebhookEventType, eventHandler);\n }\n }\n }\n\n if (options.onAny) {\n handler.onAny(options.onAny);\n }\n\n return handler;\n}\n","/**\n * Webhook event types and payload definitions.\n */\n\nimport type { Timestamp, UUID, RiskLevel } from '../core/types';\nimport type { WebhookDedupStore } from '../core';\n\n// --- Event Types ---\n\nexport type WebhookEventType =\n | 'notification.created'\n | 'risk.score.changed'\n | 'risk.category.changed'\n | 'profile.created'\n | 'profile.updated'\n | 'geolocation.verified'\n | 'geolocation.blocked'\n | 'kyc.status.changed'\n | 'kyc.approved'\n | 'kyc.declined'\n | 'decision.recorded'\n | 'label.applied'\n | 'location_request.completed'\n | 'compliance.check.failed'\n | 'tax.reminder.sent';\n\n// --- Base Event ---\n\nexport interface BaseWebhookEvent<\n T extends WebhookEventType = WebhookEventType,\n P = unknown,\n> {\n /**\n * Top-level event id (typed events). The notification envelope carries none —\n * the handler resolves the id from `notification.id`.\n */\n id?: UUID;\n event_type: T;\n tenant_id: string;\n environment: 'production' | 'sandbox';\n /** Absent on the notification envelope; present on typed events. */\n customer_id?: string;\n payload: P;\n timestamp: Timestamp;\n metadata?: Record<string, unknown>;\n}\n\n// --- Typed Payloads ---\n\nexport interface RiskScoreChangedPayload {\n previous_score: number;\n new_score: number;\n risk_level: RiskLevel;\n factors: string[];\n}\n\nexport interface RiskCategoryChangedPayload {\n previous_category: string;\n new_category: string;\n risk_level: RiskLevel;\n}\n\nexport interface ProfileCreatedPayload {\n customer_id: string;\n entity_type: string;\n source: string;\n}\n\nexport interface ProfileUpdatedPayload {\n customer_id: string;\n updated_fields: string[];\n}\n\nexport interface GeolocationVerifiedPayload {\n latitude: number;\n longitude: number;\n country: string;\n region?: string;\n is_compliant: boolean;\n}\n\nexport interface GeolocationBlockedPayload {\n latitude: number;\n longitude: number;\n country: string;\n region?: string;\n reasons: string[];\n}\n\nexport interface KycStatusChangedPayload {\n previous_status: string;\n new_status: string;\n provider?: string;\n}\n\nexport interface DecisionRecordedPayload {\n decision_id: string;\n decision_type: string;\n category: string;\n source: string;\n risk_score?: number;\n}\n\nexport interface LabelAppliedPayload {\n label_type: string;\n reasons?: string[];\n}\n\nexport interface LocationRequestCompletedPayload {\n request_id: string;\n status: string;\n latitude?: number;\n longitude?: number;\n}\n\nexport interface ComplianceCheckFailedPayload {\n check_type: string;\n reasons: string[];\n severity: string;\n}\n\nexport interface TaxReminderSentPayload {\n /** W-form the reminder is for (e.g. \"W-9\", \"W-8BEN\", \"W-8BEN-E\") */\n form_type: string;\n /** Sequential count of reminders sent in the current solicitation cycle */\n reminder_count: number;\n /** Configured maximum reminders per cycle (reminder_max_count) */\n max_count: number;\n}\n\n// --- Notification Envelope (the real notification-service producer payload) ---\n\nexport interface WebhookNotification {\n id: string;\n user_id?: string;\n title?: string;\n message?: string;\n}\n\n/**\n * The `notification.created` envelope emitted by notification-service. Unlike the\n * typed events it has no top-level `id`/`customer_id` and no `payload`; the data\n * is nested under `notification`.\n */\nexport interface NotificationWebhookEvent {\n id?: UUID;\n event_type: 'notification.created';\n tenant_id: string;\n environment: 'production' | 'sandbox';\n customer_id?: string;\n notification: WebhookNotification;\n timestamp: Timestamp;\n metadata?: Record<string, unknown>;\n}\n\n// --- Discriminated Union ---\n\nexport type WebhookEvent =\n | NotificationWebhookEvent\n | BaseWebhookEvent<'risk.score.changed', RiskScoreChangedPayload>\n | BaseWebhookEvent<'risk.category.changed', RiskCategoryChangedPayload>\n | BaseWebhookEvent<'profile.created', ProfileCreatedPayload>\n | BaseWebhookEvent<'profile.updated', ProfileUpdatedPayload>\n | BaseWebhookEvent<'geolocation.verified', GeolocationVerifiedPayload>\n | BaseWebhookEvent<'geolocation.blocked', GeolocationBlockedPayload>\n | BaseWebhookEvent<'kyc.status.changed', KycStatusChangedPayload>\n | BaseWebhookEvent<'kyc.approved', KycStatusChangedPayload>\n | BaseWebhookEvent<'kyc.declined', KycStatusChangedPayload>\n | BaseWebhookEvent<'decision.recorded', DecisionRecordedPayload>\n | BaseWebhookEvent<'label.applied', LabelAppliedPayload>\n | BaseWebhookEvent<'location_request.completed', LocationRequestCompletedPayload>\n | BaseWebhookEvent<'compliance.check.failed', ComplianceCheckFailedPayload>\n | BaseWebhookEvent<'tax.reminder.sent', TaxReminderSentPayload>;\n\n// --- Handler Config ---\n\nexport interface WebhookHandlerConfig {\n /** Webhook signing secret for signature verification */\n secret: string;\n /** Header name containing the signature (default: 'x-webhook-signature') */\n signatureHeader?: string;\n /** Maximum age of webhook event in ms (default: 300000 = 5 minutes) */\n tolerance?: number;\n /** Enable replay protection to reject duplicate event IDs (default: true) */\n replayProtection?: boolean;\n /** Pluggable dedup store for replay protection (default: in-memory, process-local). */\n dedupStore?: WebhookDedupStore;\n /** Accept the legacy body-only `sha256=<hex>` signature during migration (default: true). */\n allowLegacySignature?: boolean;\n}\n\n// --- Handler Types ---\n\nexport type WebhookEventHandler<T extends WebhookEventType = WebhookEventType> = (\n event: Extract<WebhookEvent, { event_type: T }>\n) => void | Promise<void>;\n\nexport type WebhookAnyHandler = (event: WebhookEvent) => void | Promise<void>;\n\n// --- AML Block Callback ---\n\n/** Watchlist category an AML screening matched. */\nexport type AmlCallbackCategory =\n | 'sanction'\n | 'pep'\n | 'adverse_media'\n | 'fraud'\n | 'terrorism'\n | 'narcotics'\n | 'financial_crime'\n | 'warning'\n | 'fitness_probity'\n | 'previous_client'\n | 'unknown'\n | (string & Record<string, never>);\n\nexport interface AmlBlockCallbackData {\n /** Your customer identifier — the one the screening ran against. */\n customer_id: string;\n /** Screened full name. Omitted when the screening had no full name. */\n customer_name?: string;\n /**\n * Derived from the number of matches against your tenant's risk thresholds —\n * not from the category. A sanction match is not automatically `high`.\n */\n risk_level: RiskLevel;\n /** The category that matched. `previous_client` is a match on your internal watchlist only. */\n category: AmlCallbackCategory;\n /** Total matches, including internal watchlist matches. */\n hits_count: number;\n /** Name of the AML alert rule that decided the block. */\n applied_rule?: string;\n /** ISO 8601 UTC time the screening ran. */\n screened_at?: Timestamp;\n}\n\n/**\n * Body POSTed to the webhook URL in your AML screening settings when a\n * screening matches a watchlist and the governing alert rule carries the\n * `block` reaction. Signed with `X-Webhook-Signature: sha256=<hex>`\n * (HMAC-SHA256 of the raw body).\n *\n * Sent only for blocks — nothing is delivered for a clear screening or for a\n * rule that only alerts. Screenings that run without a request from you (after\n * an accepted KYC, or after a name or date-of-birth change) are reported only\n * through this webhook.\n */\nexport interface AmlBlockCallbackEvent {\n /** Always `\"aml\"` — dispatch on this. */\n event: 'aml';\n /** The screening reference you supplied, or a generated identifier for automatic screenings. */\n reference: string;\n /** The screening record ID — unique per screening, so dedup on it. */\n resource_id: string;\n /** Always `\"blocked\"`. */\n status: 'blocked';\n /** Always `true`. */\n block: true;\n /**\n * Human-readable reason for display and audit. Wording is not stable — branch\n * on `data.category` and `data.risk_level` instead.\n */\n block_reason: string;\n data: AmlBlockCallbackData;\n}\n\n/**\n * Type guard for the AML block webhook. Narrows an already signature-verified,\n * parsed payload to {@link AmlBlockCallbackEvent}.\n */\nexport function isAmlBlockCallbackEvent(value: unknown): value is AmlBlockCallbackEvent {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { event?: unknown }).event === 'aml' &&\n (value as { block?: unknown }).block === true\n );\n}\n"]}
|